@ygorazambuja/sauron 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +570 -0
- package/bin.ts +15 -0
- package/docs/plugins.md +154 -0
- package/package.json +59 -0
- package/src/cli/args.ts +196 -0
- package/src/cli/config.ts +228 -0
- package/src/cli/main.ts +276 -0
- package/src/cli/project.ts +113 -0
- package/src/cli/types.ts +22 -0
- package/src/generators/angular.ts +76 -0
- package/src/generators/fetch.ts +994 -0
- package/src/generators/missing-definitions.ts +776 -0
- package/src/generators/type-coverage.ts +938 -0
- package/src/index.ts +47 -0
- package/src/plugins/builtin/angular.ts +146 -0
- package/src/plugins/builtin/axios.ts +307 -0
- package/src/plugins/builtin/fetch.ts +140 -0
- package/src/plugins/registry.ts +84 -0
- package/src/plugins/runner.ts +174 -0
- package/src/plugins/types.ts +97 -0
- package/src/schemas/swagger.ts +134 -0
- package/src/utils/index.ts +1599 -0
package/README.md
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
# OpenAPI to TypeScript Converter
|
|
2
|
+
|
|
3
|
+
Este projeto converte automaticamente schemas OpenAPI/Swagger JSON em definições TypeScript (interfaces e tipos).
|
|
4
|
+
|
|
5
|
+
## Funcionalidades
|
|
6
|
+
|
|
7
|
+
- ✅ **Interfaces TypeScript**: Converte objetos OpenAPI em interfaces TypeScript
|
|
8
|
+
- ✅ **Tipos Union**: Converte enums OpenAPI em tipos union TypeScript
|
|
9
|
+
- ✅ **Tipos Primitivos**: Suporte completo a string, number, boolean, integer
|
|
10
|
+
- ✅ **Arrays**: Suporte a arrays com tipagem correta
|
|
11
|
+
- ✅ **Propriedades Nullable**: Converte `nullable: true` para `| null`
|
|
12
|
+
- ✅ **Referências ($ref)**: Resolve referências entre schemas
|
|
13
|
+
- ✅ **Datas**: Converte `format: "date-time"` para tipo `Date`
|
|
14
|
+
- ✅ **Propriedades Obrigatórias**: Todas as propriedades definidas são obrigatórias por padrão
|
|
15
|
+
- ✅ **Plugin system para geradores HTTP**: Plugins built-in `fetch`, `angular` e `axios`
|
|
16
|
+
- ✅ **Seleção explícita de plugin**: `--plugin <id>` (aceita múltiplos)
|
|
17
|
+
- ✅ **Compatibilidade retroativa**: `--http` e `--angular` continuam funcionando como aliases
|
|
18
|
+
- ✅ **Relatório de definições ausentes**: Cada plugin HTTP gera relatório com os pontos que viraram `any`
|
|
19
|
+
|
|
20
|
+
## Como Usar
|
|
21
|
+
|
|
22
|
+
### Opção 1: Binário Compilado (Recomendado)
|
|
23
|
+
|
|
24
|
+
Após compilar o projeto, você pode usar o binário executável diretamente:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Compilar o projeto
|
|
28
|
+
bun build --compile ./src/index.ts --outfile sauron
|
|
29
|
+
|
|
30
|
+
# Usar o binário
|
|
31
|
+
./sauron --input swaggerAfEstoque.json --angular --http
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Opção 2: Desenvolvimento com Bun
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Instalar dependências
|
|
38
|
+
bun install
|
|
39
|
+
|
|
40
|
+
# Criar arquivo de configuração inicial
|
|
41
|
+
bun run cli -- init
|
|
42
|
+
|
|
43
|
+
# Executar diretamente
|
|
44
|
+
bun run src/index.ts
|
|
45
|
+
|
|
46
|
+
# Ou usar o CLI wrapper
|
|
47
|
+
bun run cli --input swaggerAfEstoque.json --angular
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Executar Testes
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Executar todos os testes
|
|
54
|
+
bun test
|
|
55
|
+
|
|
56
|
+
# Executar testes em modo watch
|
|
57
|
+
bun test --watch
|
|
58
|
+
|
|
59
|
+
# Executar com cobertura
|
|
60
|
+
bun test --coverage
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
O comando irá:
|
|
64
|
+
|
|
65
|
+
1. Ler o arquivo OpenAPI/Swagger especificado
|
|
66
|
+
2. Validar o schema OpenAPI
|
|
67
|
+
3. **Por padrão**: Gerar apenas interfaces TypeScript (models)
|
|
68
|
+
4. **Com `--http`**: Gerar também métodos HTTP (fetch por padrão)
|
|
69
|
+
5. **Com `--angular --http`**: Detectar projeto Angular e gerar serviço Angular
|
|
70
|
+
6. **Com `--plugin <id>`**: Escolher explicitamente o plugin (`fetch`, `angular`, `axios`)
|
|
71
|
+
7. **Com `--plugin angular` fora de projeto Angular**: fallback automático para `fetch`
|
|
72
|
+
8. Salvar nos diretórios apropriados (`outputs/` ou `src/app/sauron/`)
|
|
73
|
+
9. Gerar relatório de definições ausentes ao lado do cliente/serviço HTTP gerado
|
|
74
|
+
|
|
75
|
+
### Flags Disponíveis
|
|
76
|
+
|
|
77
|
+
- **`init`**: Cria `sauron.config.ts` com configurações iniciais
|
|
78
|
+
- **Sem flags**: Apenas models TypeScript
|
|
79
|
+
- **`--http`**: Models + métodos HTTP com plugin padrão (`fetch`)
|
|
80
|
+
- **`--angular --http`**: Models + serviço Angular (alias compatível)
|
|
81
|
+
- **`--plugin <id>`**: Seleciona plugin HTTP explicitamente (`fetch`, `angular`, `axios`)
|
|
82
|
+
- **`--input arquivo.json`**: Especificar arquivo de entrada
|
|
83
|
+
- **`--output diretorio`**: Diretório de saída customizado
|
|
84
|
+
- **`--config arquivo.ts`**: Caminho para arquivo de configuração (padrão: `sauron.config.ts`)
|
|
85
|
+
|
|
86
|
+
Regras de precedência:
|
|
87
|
+
|
|
88
|
+
- Se `--plugin` for informado, ele tem prioridade sobre `--http` e `--angular`.
|
|
89
|
+
- Se `--plugin` não for informado, `--http` usa `fetch`.
|
|
90
|
+
- Se `--plugin` não for informado, `--http --angular` usa `angular`.
|
|
91
|
+
|
|
92
|
+
### Arquivo de Configuração (`sauron.config.ts`)
|
|
93
|
+
|
|
94
|
+
Você pode centralizar as opções do CLI em um arquivo:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import type { SauronConfig } from "@ygorazambuja/sauron";
|
|
98
|
+
|
|
99
|
+
export default {
|
|
100
|
+
input: "swagger.json",
|
|
101
|
+
// url: "https://api.exemplo.com/openapi.json",
|
|
102
|
+
// plugin: ["fetch"], // fetch | angular | axios
|
|
103
|
+
output: "outputs",
|
|
104
|
+
angular: false,
|
|
105
|
+
http: true,
|
|
106
|
+
} satisfies SauronConfig;
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
As flags da CLI têm prioridade sobre os valores do arquivo de configuração.
|
|
110
|
+
|
|
111
|
+
### Uso Programático
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import {
|
|
115
|
+
readJsonFile,
|
|
116
|
+
verifySwaggerComposition,
|
|
117
|
+
createModels,
|
|
118
|
+
} from "./src/utils";
|
|
119
|
+
|
|
120
|
+
// 1. Ler arquivo JSON
|
|
121
|
+
const swaggerData = await readJsonFile("swagger.json");
|
|
122
|
+
|
|
123
|
+
// 2. Validar schema
|
|
124
|
+
const validatedSchema = verifySwaggerComposition(swaggerData);
|
|
125
|
+
|
|
126
|
+
// 3. Gerar definições TypeScript
|
|
127
|
+
const typeDefinitions = createModels(validatedSchema);
|
|
128
|
+
|
|
129
|
+
// Resultado: array de strings com definições TypeScript
|
|
130
|
+
console.log(typeDefinitions);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Estrutura dos Arquivos
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
src/
|
|
137
|
+
├── index.ts # Ponto de entrada principal
|
|
138
|
+
├── utils/
|
|
139
|
+
│ └── index.ts # Funções utilitárias de conversão
|
|
140
|
+
└── schemas/
|
|
141
|
+
└── swagger.ts # Schema Zod para validação OpenAPI
|
|
142
|
+
|
|
143
|
+
outputs/
|
|
144
|
+
├── models/
|
|
145
|
+
│ └── index.ts # Arquivo gerado com tipos TypeScript
|
|
146
|
+
└── http-client/ # Quando plugin fetch/axios
|
|
147
|
+
├── sauron-api.client.ts # Cliente fetch (plugin fetch)
|
|
148
|
+
├── sauron-api.axios-client.ts # Cliente axios (plugin axios)
|
|
149
|
+
├── missing-swagger-definitions.json # Relatório (plugin fetch)
|
|
150
|
+
├── type-coverage-report.json # Cobertura de tipos (plugin fetch)
|
|
151
|
+
├── missing-swagger-definitions.axios.json # Relatório (plugin axios)
|
|
152
|
+
└── type-coverage-report.axios.json # Cobertura de tipos (plugin axios)
|
|
153
|
+
|
|
154
|
+
src/app/sauron/
|
|
155
|
+
├── models/
|
|
156
|
+
│ └── index.ts # Arquivo gerado com tipos TypeScript
|
|
157
|
+
└── angular-http-client/ # Quando --angular --http
|
|
158
|
+
├── sauron-api.service.ts # Serviço Angular
|
|
159
|
+
├── missing-swagger-definitions.json # Relatório de definições ausentes
|
|
160
|
+
└── type-coverage-report.json # Cobertura de tipos
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Exemplo de Saída
|
|
164
|
+
|
|
165
|
+
**Schema OpenAPI:**
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"MesValorIndexadorDto": {
|
|
170
|
+
"type": "object",
|
|
171
|
+
"properties": {
|
|
172
|
+
"dominioMesID": { "type": "integer" },
|
|
173
|
+
"valor": { "type": "number" }
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Resultado TypeScript:**
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
export interface MesValorIndexadorDto {
|
|
183
|
+
dominioMesID: number;
|
|
184
|
+
valor: number;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## API Reference
|
|
189
|
+
|
|
190
|
+
### `readJsonFile(filePath: string): Promise<unknown>`
|
|
191
|
+
|
|
192
|
+
Lê e faz parse de um arquivo JSON do sistema de arquivos.
|
|
193
|
+
|
|
194
|
+
**Parâmetros:**
|
|
195
|
+
|
|
196
|
+
- `filePath`: Caminho para o arquivo JSON
|
|
197
|
+
|
|
198
|
+
**Retorna:** Conteúdo JSON parseado
|
|
199
|
+
|
|
200
|
+
### `verifySwaggerComposition(swaggerData: Record<string, unknown>)`
|
|
201
|
+
|
|
202
|
+
Valida dados OpenAPI/Swagger contra o schema esperado.
|
|
203
|
+
|
|
204
|
+
**Parâmetros:**
|
|
205
|
+
|
|
206
|
+
- `swaggerData`: Dados brutos do OpenAPI JSON
|
|
207
|
+
|
|
208
|
+
**Retorna:** Schema validado e tipado
|
|
209
|
+
|
|
210
|
+
**Lança:** Error se a validação falhar
|
|
211
|
+
|
|
212
|
+
### `createModels(openApiSchema): string[]`
|
|
213
|
+
|
|
214
|
+
Gera definições TypeScript a partir de schemas OpenAPI.
|
|
215
|
+
|
|
216
|
+
**Parâmetros:**
|
|
217
|
+
|
|
218
|
+
- `openApiSchema`: Schema OpenAPI validado
|
|
219
|
+
|
|
220
|
+
**Retorna:** Array de strings com definições TypeScript
|
|
221
|
+
|
|
222
|
+
## Regras de Conversão
|
|
223
|
+
|
|
224
|
+
### Propriedades Obrigatórias vs Opcionais
|
|
225
|
+
|
|
226
|
+
- **Por padrão**: Todas as propriedades definidas no schema são obrigatórias
|
|
227
|
+
- **Se houver lista `required`**: Apenas propriedades na lista são obrigatórias
|
|
228
|
+
- **Nullable**: Propriedades com `nullable: true` recebem `| null`
|
|
229
|
+
|
|
230
|
+
### Tipos Suportados
|
|
231
|
+
|
|
232
|
+
| OpenAPI | TypeScript |
|
|
233
|
+
| ------------------------------------ | ---------- | --- | --- |
|
|
234
|
+
| `string` | `string` |
|
|
235
|
+
| `integer` | `number` |
|
|
236
|
+
| `number` | `number` |
|
|
237
|
+
| `boolean` | `boolean` |
|
|
238
|
+
| `string` + `format: "date-time"` | `Date` |
|
|
239
|
+
| `array` + `items` | `T[]` |
|
|
240
|
+
| `enum: [1, 2, 3]` | `1 | 2 | 3` |
|
|
241
|
+
| `$ref: "#/components/schemas/Model"` | `Model` |
|
|
242
|
+
|
|
243
|
+
## Desenvolvimento
|
|
244
|
+
|
|
245
|
+
### Executar Testes
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
bun run src/index.ts
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Modificar Schemas
|
|
252
|
+
|
|
253
|
+
Os schemas de validação estão em `src/schemas/swagger.ts`. Eles usam a biblioteca Zod para validação robusta.
|
|
254
|
+
|
|
255
|
+
### Adicionar Novos Conversores
|
|
256
|
+
|
|
257
|
+
Para adicionar suporte a novos tipos OpenAPI, modifique a função `convertSchemaToTypeScript` em `src/utils/index.ts`.
|
|
258
|
+
|
|
259
|
+
## Serviço Angular Gerado
|
|
260
|
+
|
|
261
|
+
Além dos tipos TypeScript, o projeto também gera um serviço Angular completo com métodos HTTP Client para todas as rotas da API.
|
|
262
|
+
|
|
263
|
+
### Características do Serviço Gerado
|
|
264
|
+
|
|
265
|
+
- ✅ **HttpClient injection**: Usa o novo sistema de injeção do Angular
|
|
266
|
+
- ✅ **Métodos tipados**: Cada método tem assinatura correta de parâmetros
|
|
267
|
+
- ✅ **Tipos de resposta**: Retorna `Observable<T>` com tipos específicos (quando definido no schema)
|
|
268
|
+
- ✅ **Observables**: Retorna `Observable<any>` quando tipo não é especificado
|
|
269
|
+
- ✅ **Parâmetros de path**: Suporte a parâmetros na URL (`/users/{id}`)
|
|
270
|
+
- ✅ **Query parameters**: Suporte a parâmetros de query
|
|
271
|
+
- ✅ **Request body**: Suporte a POST/PUT/PATCH com body
|
|
272
|
+
- ✅ **Nomes únicos**: Evita conflitos de nomes entre métodos
|
|
273
|
+
- ✅ **Imports automáticos**: Importa apenas os tipos utilizados
|
|
274
|
+
|
|
275
|
+
### Exemplo de Serviço Gerado
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { Injectable, inject } from "@angular/core";
|
|
279
|
+
import { HttpClient } from "@angular/common/http";
|
|
280
|
+
import { Observable } from "rxjs";
|
|
281
|
+
import { LaboratorioDtoResultPaginateFilterDto, LaboratorioDto } from "../models";
|
|
282
|
+
|
|
283
|
+
@Injectable({
|
|
284
|
+
providedIn: "root"
|
|
285
|
+
})
|
|
286
|
+
export class SauronApiService {
|
|
287
|
+
private readonly httpClient = inject(HttpClient);
|
|
288
|
+
|
|
289
|
+
// Padrão: Get{Resource}{Modifier}
|
|
290
|
+
|
|
291
|
+
// Retorna Observable<any> quando não há schema definido
|
|
292
|
+
GetApiGenerica(): Observable<any> {
|
|
293
|
+
return this.httpClient.get("/api/ApiGenerica/credorDivida");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Retorna tipo específico quando schema está definido
|
|
297
|
+
GetLaboratorioWithParams(Nome?: any, AlteracaoCadastro?: any, Pagina?: any, TamanhoDaPagina?: any, Ordenacao?: any, TipoOrdenacao?: any): Observable<LaboratorioDtoResultPaginateFilterDto> {
|
|
298
|
+
return this.httpClient.get("/api/Laboratorio/ListarTodos", { params: { Nome, AlteracaoCadastro, Pagina, TamanhoDaPagina, Ordenacao, TipoOrdenacao } });
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Retorna objeto único
|
|
302
|
+
GetLaboratorioById(id: any): Observable<LaboratorioDto> {
|
|
303
|
+
return this.httpClient.get(\`/api/Laboratorio/\${id}\`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Operações CREATE/UPDATE/DELETE
|
|
307
|
+
PostLaboratorioCreate(body: any): Observable<LaboratorioDto> {
|
|
308
|
+
return this.httpClient.post("/api/Laboratorio/Incluir", body);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
PutLaboratorioCreate(body: any): Observable<any> {
|
|
312
|
+
return this.httpClient.put("/api/Laboratorio/Alterar", body);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
DeleteLaboratorio(id?: any): Observable<any> {
|
|
316
|
+
return this.httpClient.delete("/api/Laboratorio/Excluir", { params: { id } });
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ... mais métodos
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Tipos de Saída
|
|
324
|
+
|
|
325
|
+
### Apenas Models (Padrão)
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
sauron swagger.json
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Gera apenas interfaces TypeScript em `outputs/models/`.
|
|
332
|
+
|
|
333
|
+
### Cliente Fetch (Vanilla JS/TS)
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
sauron swagger.json --http
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Gera models + cliente fetch-based em `outputs/http-client/sauron-api.client.ts`.
|
|
340
|
+
Também gera `outputs/http-client/missing-swagger-definitions.json`.
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Exemplo de uso
|
|
344
|
+
import { SauronApiClient } from "./outputs/http-client/sauron-api.client";
|
|
345
|
+
import type {
|
|
346
|
+
LaboratorioDto,
|
|
347
|
+
LaboratorioDtoResultPaginateFilterDto,
|
|
348
|
+
} from "./outputs/models";
|
|
349
|
+
|
|
350
|
+
// Criar instância com base URL
|
|
351
|
+
const api = new SauronApiClient("https://api.exemplo.com");
|
|
352
|
+
|
|
353
|
+
// Usar métodos assíncronos com tipos específicos
|
|
354
|
+
try {
|
|
355
|
+
const laboratorios: LaboratorioDtoResultPaginateFilterDto =
|
|
356
|
+
await api.GetLaboratorioWithParams("search", 1, 10);
|
|
357
|
+
console.log("Resultados:", laboratorios);
|
|
358
|
+
|
|
359
|
+
const laboratorio: LaboratorioDto = await api.GetLaboratorioById(123);
|
|
360
|
+
console.log("Laboratório específico:", laboratorio);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
console.error("Erro na API:", error);
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Ou usar a instância padrão:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { sauronApi } from "./outputs/http-client/sauron-api.client";
|
|
370
|
+
|
|
371
|
+
// Configura uma única vez para todas as chamadas
|
|
372
|
+
sauronApi.setBaseUrl("https://api.exemplo.com");
|
|
373
|
+
|
|
374
|
+
const result = await sauronApi.GetLaboratorioWithParams("search", 1, 10);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Cliente Axios
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
sauron swagger.json --plugin axios
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Gera models + cliente axios em `outputs/http-client/sauron-api.axios-client.ts`.
|
|
384
|
+
Também gera `outputs/http-client/missing-swagger-definitions.axios.json`.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { SauronAxiosApiClient } from "./outputs/http-client/sauron-api.axios-client";
|
|
388
|
+
|
|
389
|
+
const api = new SauronAxiosApiClient("https://api.exemplo.com");
|
|
390
|
+
const result = await api.GetLaboratorioWithParams("search", 1, 10);
|
|
391
|
+
console.log(result);
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Serviço Angular
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
sauron swagger.json --angular --http
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Gera models + serviço Angular em `src/app/sauron/angular-http-client/sauron-api.service.ts`.
|
|
401
|
+
Também gera `src/app/sauron/angular-http-client/missing-swagger-definitions.json`.
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// Exemplo de uso
|
|
405
|
+
import { SauronApiService } from './src/app/sauron/angular-http-client/sauron-api.service';
|
|
406
|
+
|
|
407
|
+
constructor(private api: SauronApiService) {}
|
|
408
|
+
|
|
409
|
+
loadData() {
|
|
410
|
+
this.api.GetLaboratorioWithParams('search', 1, 10)
|
|
411
|
+
.subscribe(result => console.log(result));
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Como Usar o Serviço Gerado
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { Component, inject } from '@angular/core';
|
|
419
|
+
import { SauronApiService } from './outputs/angular-http-client/sauron-api.service';
|
|
420
|
+
import { LaboratorioDtoResultPaginateFilterDto } from './outputs/models';
|
|
421
|
+
|
|
422
|
+
@Component({...})
|
|
423
|
+
export class MyComponent {
|
|
424
|
+
private readonly api = inject(SauronApiService);
|
|
425
|
+
|
|
426
|
+
// Com tipos específicos - IntelliSense e type safety
|
|
427
|
+
loadLaboratorios() {
|
|
428
|
+
this.api.GetLaboratorioWithParams(
|
|
429
|
+
'search term',
|
|
430
|
+
undefined, // AlteracaoCadastro
|
|
431
|
+
1, // Pagina
|
|
432
|
+
10, // TamanhoDaPagina
|
|
433
|
+
'Nome', // Ordenacao
|
|
434
|
+
'asc' // TipoOrdenacao
|
|
435
|
+
).subscribe((response: LaboratorioDtoResultPaginateFilterDto) => {
|
|
436
|
+
// response.dados é tipado como LaboratorioDto[]
|
|
437
|
+
// response.totalRegistros é tipado como number
|
|
438
|
+
console.log('Total:', response.totalRegistros);
|
|
439
|
+
console.log('Dados:', response.dados);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Buscar laboratório específico
|
|
444
|
+
getLaboratorio(id: number) {
|
|
445
|
+
this.api.GetLaboratorioById(id).subscribe(lab => {
|
|
446
|
+
console.log('Laboratório:', lab);
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Criar novo laboratório
|
|
451
|
+
createLaboratorio(labData: any) {
|
|
452
|
+
this.api.PostLaboratorioCreate(labData).subscribe(result => {
|
|
453
|
+
console.log('Criado:', result);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Sem tipos específicos - ainda funciona
|
|
458
|
+
loadGenericData() {
|
|
459
|
+
this.api.GetApiGenerica().subscribe((data: any) => {
|
|
460
|
+
console.log(data);
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Relatório de Definições Ausentes
|
|
467
|
+
|
|
468
|
+
Quando há geração HTTP, o CLI gera automaticamente um relatório ao lado do cliente/serviço.
|
|
469
|
+
|
|
470
|
+
Arquivos atuais:
|
|
471
|
+
|
|
472
|
+
- `missing-swagger-definitions.json` (plugin `fetch` e `angular`)
|
|
473
|
+
- `missing-swagger-definitions.axios.json` (plugin `axios`)
|
|
474
|
+
- `type-coverage-report.json` (plugin `fetch` e `angular`)
|
|
475
|
+
- `type-coverage-report.axios.json` (plugin `axios`)
|
|
476
|
+
|
|
477
|
+
Esse relatório lista os pontos da especificação Swagger/OpenAPI que resultaram em `any` na
|
|
478
|
+
camada HTTP gerada, para facilitar correções no contrato da API.
|
|
479
|
+
|
|
480
|
+
## Relatório de Cobertura de Tipos
|
|
481
|
+
|
|
482
|
+
Quando há geração HTTP, o CLI também gera um relatório de cobertura de tipos por operação.
|
|
483
|
+
|
|
484
|
+
Esse relatório mostra:
|
|
485
|
+
|
|
486
|
+
- Cobertura total de tipagem (`typed` vs `untyped`)
|
|
487
|
+
- Cobertura por localização (`path.parameter`, `query.parameter`, `request.body`, `response.body`)
|
|
488
|
+
- Resumo por operação (rota + método)
|
|
489
|
+
- Lista de ocorrências não tipadas em `issues`
|
|
490
|
+
|
|
491
|
+
### Estrutura do arquivo
|
|
492
|
+
|
|
493
|
+
- `generatedAt`: data/hora de geração (ISO string)
|
|
494
|
+
- `totalIssues`: total de ocorrências encontradas
|
|
495
|
+
- `summary.pathParameters`: total de problemas em parâmetros de path
|
|
496
|
+
- `summary.queryParameters`: total de problemas em parâmetros de query
|
|
497
|
+
- `summary.requestBodies`: total de problemas em corpos de requisição
|
|
498
|
+
- `summary.responseBodies`: total de problemas em corpos de resposta
|
|
499
|
+
- `issues`: lista detalhada de ocorrências
|
|
500
|
+
|
|
501
|
+
### Exemplo de item em `issues`
|
|
502
|
+
|
|
503
|
+
```json
|
|
504
|
+
{
|
|
505
|
+
"path": "/api/users/{id}",
|
|
506
|
+
"method": "GET",
|
|
507
|
+
"location": "path.parameter",
|
|
508
|
+
"field": "id",
|
|
509
|
+
"reason": "Path parameter schema is missing or unresolved.",
|
|
510
|
+
"recommendedDefinition": "Define parameter.schema with a primitive type, enum, object, array, or valid $ref."
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Sistema de Plugins
|
|
515
|
+
|
|
516
|
+
Plugins HTTP built-in:
|
|
517
|
+
|
|
518
|
+
- `fetch`
|
|
519
|
+
- `angular`
|
|
520
|
+
- `axios`
|
|
521
|
+
|
|
522
|
+
Exemplos:
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
sauron swagger.json --plugin fetch
|
|
526
|
+
sauron swagger.json --plugin angular
|
|
527
|
+
sauron swagger.json --plugin axios
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Para criar novos plugins, veja `docs/plugins.md`.
|
|
531
|
+
|
|
532
|
+
## Distribuição
|
|
533
|
+
|
|
534
|
+
### Binário Executável
|
|
535
|
+
|
|
536
|
+
O projeto pode ser compilado em um único arquivo executável que roda em qualquer sistema com suporte ao Bun runtime:
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
# Compilar
|
|
540
|
+
bun build --compile ./src/index.ts --outfile sauron
|
|
541
|
+
|
|
542
|
+
# O arquivo 'sauron' pode ser distribuído e executado diretamente
|
|
543
|
+
./sauron --input api.json --angular
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Publicação no NPM com Bun
|
|
547
|
+
|
|
548
|
+
Para validar e publicar no registro npm usando Bun:
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
bun publish --dry-run
|
|
552
|
+
bun publish --access public
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Então outros projetos podem instalar e usar:
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
npm install -g @ygorazambuja/sauron
|
|
559
|
+
sauron --input swagger.json --angular
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## Limitações
|
|
563
|
+
|
|
564
|
+
- Não suporta todos os recursos avançados do OpenAPI 3.x
|
|
565
|
+
- Focado principalmente em schemas de componentes
|
|
566
|
+
- Não gera validações em runtime (apenas tipos TypeScript)
|
|
567
|
+
|
|
568
|
+
## Licença
|
|
569
|
+
|
|
570
|
+
Este projeto é parte do sistema Sauron para conversão de APIs.
|
package/bin.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
// Execute the main TypeScript file with all arguments passed through
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const scriptPath = join(__dirname, "src", "index.ts");
|
|
11
|
+
|
|
12
|
+
execSync(`bun run "${scriptPath}" ${process.argv.slice(2).join(" ")}`, {
|
|
13
|
+
stdio: "inherit",
|
|
14
|
+
cwd: process.cwd(),
|
|
15
|
+
});
|