OpenAPI para Fetch

Gerador de Cliente TypeScript Fetch Nativo a partir de OpenAPI e Swagger

Gere clientes de API em TypeScript com fetch nativo sem dependências externas, serialização de query string, cabeçalhos e tipagem completa.

6 operações • 4 modelos
Predefinições:
Arquitetura:
Formato de Resposta:
YAMLBase: https://petstore3.swagger.io/api/v3
Especificação OpenAPI / Swagger (YAML ou JSON)YAML
/**
 * Zero-Dependency Native Fetch TypeScript Client
 * API: Swagger Petstore (v1.0.0)
 * Base URL: https://petstore3.swagger.io/api/v3
 * Standard Web Fetch API compatible with Browsers, Node.js 18+, Bun, Deno, and Next.js
 */

/**
 * Generated TypeScript Interfaces & Models
 * API: Swagger Petstore (v1.0.0)
 * Spec: OpenAPI 3.0.3
 * Generated automatically by ToolsAA Native Fetch Generator
 */

Category {
  id?: number | undefined;
  name?: string | undefined;
}

Tag {
  id?: number | undefined;
  name?: string | undefined;
}

Pet {
  id: number;
  name: string;
  category?: Category | undefined;
  photoUrls?: string[] | undefined;
  tags?: Tag[] | undefined;
  status?: 'available' | 'pending' | 'sold' | undefined;
}

ApiResponse {
  code?: number | undefined;
  type?: string | undefined;
  message?: string | undefined;
}

// ============================================================================
// Operation Parameter Interfaces
// ============================================================================

ListPetsQueryParams {
  /** Status values that need to be considered for filter */
  status?: 'available' | 'pending' | 'sold' | undefined;
  /** How many items to return at one time (max 100) */
  limit?: number | undefined;
}

GetPetByIdPathParams {
  /** The id of the pet to retrieve */
  petId: number;
}

DeletePetPathParams {
  /** Pet id to delete */
  petId: number;
}

DeletePetHeaders {
  api_key?: string | undefined;
}

UploadFilePathParams {
  /** ID of pet to update */
  petId: number;
}

UploadFileQueryParams {
  additionalMetadata?: string | undefined;
}


// ============================================================================
// Runtime ApiError & Client Infrastructure
// ============================================================================

export class ApiError extends Error {
  readonly status: number;
  readonly statusText: string;
  readonly data: unknown;
  readonly headers: Headers;

  constructor(status: number, statusText: string, data: unknown, headers: Headers) {
    super(`HTTP ${status} ${statusText}`);
    this.name = 'ApiError';
    this.status = status;
    this.statusText = statusText;
    this.data = data;
    this.headers = headers;
  }
}

FetchClientConfig {
  baseUrl?: string;
  headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
  customFetch?: typeof fetch;
  timeoutMs?: number;
  onRequest?: (url: string, init: RequestInit) => void | Promise<void>;
  onResponse?: (response: Response) => void | Promise<void>;
}

RequestOptions extends Omit<RequestInit, 'body' | 'headers'> {
  headers?: Record<string, string>;
  query?: Record<string, any>;
  timeoutMs?: number;
}

ApiResponseEnvelope<T> {
  data: T;
  status: number;
  headers: Headers;
}

function serializeQuery(query?: Record<string, any>): string {
  if (!query) return '';
  const params = new URLSearchParams();
  for (const [key, value] of Object.entries(query)) {
    if (value === undefined || value === null) continue;
    if (Array.isArray(value)) {
      value.forEach((v) => params.append(key, String(v)));
    } else {
      params.append(key, String(value));
    }
  }
  const str = params.toString();
  return str ? `?${str}` : '';
}

async function executeFetch<T>(
  config: FetchClientConfig,
  method: string,
  path: string,
  options?: RequestOptions & { body?: any }
): Promise<T> {
  const baseUrl = (config.baseUrl || 'https://petstore3.swagger.io/api/v3').replace(/\/+$/, '');
  const queryString = serializeQuery(options?.query);
  const fullUrl = `${baseUrl}${path.startsWith('/') ? path : '/' + path}${queryString}`;

  let dynamicHeaders: Record<string, string> = {};
  if (typeof config.headers === 'function') {
    dynamicHeaders = await config.headers();
  } else if (config.headers) {
    dynamicHeaders = config.headers;
  }

  const headers = new Headers({
    ...dynamicHeaders,
    ...options?.headers,
  });

  let requestBody: any = undefined;
  if (options?.body !== undefined) {
    if (typeof FormData !== 'undefined' && options.body instanceof FormData) {
      requestBody = options.body;
      // Browser sets multipart boundary automatically, remove conflicting content-type
      headers.delete('Content-Type');
    } else if (typeof Blob !== 'undefined' && options.body instanceof Blob) {
      requestBody = options.body;
    } else if (typeof options.body === 'object') {
      if (!headers.has('Content-Type')) {
        headers.set('Content-Type', 'application/json');
      }
      requestBody = JSON.stringify(options.body);
    } else {
      requestBody = String(options.body);
    }
  }

  const timeoutMs = options?.timeoutMs ?? config.timeoutMs ?? 15000;
  let signal = options?.signal;
  let timeoutId: any = null;

  if (!signal && typeof AbortController !== 'undefined') {
    const controller = new AbortController();
    timeoutId = setTimeout(() => controller.abort(new Error('Request Timeout')), timeoutMs);
    signal = controller.signal;
  }

  const requestInit: RequestInit = {
    method,
    headers,
    body: requestBody,
    signal,
    ...options,
  };

  if (config.onRequest) {
    await config.onRequest(fullUrl, requestInit);
  }

  const fetchFn = config.customFetch || fetch;

  try {
    const response = await fetchFn(fullUrl, requestInit);
    if (config.onResponse) {
      await config.onResponse(response);
    }

    let responseData: any = null;
    if (response.status !== 204) {
      const contentType = response.headers.get('content-type') || '';
      if (contentType.includes('application/json')) {
        responseData = await response.json();
      } else {
        responseData = await response.text();
      }
    }

    if (!response.ok) {
      throw new ApiError(response.status, response.statusText, responseData, response.headers);
    }

    return responseData as T;
  } finally {
    if (timeoutId) clearTimeout(timeoutId);
  }
}

// ============================================================================
// Flagship ApiClient Class
// ============================================================================

export class ApiClient {
  private config: FetchClientConfig;

  constructor(config: FetchClientConfig = {}) {
    this.config = config;
  }

  public setBaseUrl(url: string): void {
    this.config.baseUrl = url;
  }

  public setHeaders(headers: Record<string, string>): void {
    this.config.headers = headers;
  }

  public setBearerToken(token: string): void {
    this.config.headers = { ...((typeof this.config.headers === 'object' ? this.config.headers : {})), Authorization: `Bearer ${token}` };
  }

  public setApiKey(key: string, headerName: string = 'X-API-Key'): void {
    this.config.headers = { ...((typeof this.config.headers === 'object' ? this.config.headers : {})), [headerName]: key };
  }

  /**
   * List all pets
   * @description Returns all pets from the store with optional status and tag filtering.
   * @route GET /pets
   * @param query URL search query parameters
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async listPets(query?: ListPetsQueryParams, options?: RequestOptions): Promise<Pet[]> {
    const path = '/pets';
    return executeFetch<Pet[]>(this.config, 'GET', path, { ...options, query });
  }

  /**
   * Create a pet
   * @description Adds a new pet to the catalog.
   * @route POST /pets
   * @param body Request payload (application/json)
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async createPet(body: Pet, options?: RequestOptions): Promise<Pet> {
    const path = '/pets';
    return executeFetch<Pet>(this.config, 'POST', path, { ...options, body });
  }

  /**
   * Info for a specific pet
   * @route GET /pets/{petId}
   * @param pathParams URL path interpolation parameters
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async getPetById(pathParams: GetPetByIdPathParams, options?: RequestOptions): Promise<Pet> {
    const path = `/pets/${encodeURIComponent(String(pathParams['petId']))}`;
    return executeFetch<Pet>(this.config, 'GET', path, { ...options });
  }

  /**
   * Deletes a pet
   * @route DELETE /pets/{petId}
   * @param pathParams URL path interpolation parameters
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async deletePet(pathParams: DeletePetPathParams, options?: RequestOptions): Promise<void> {
    const path = `/pets/${encodeURIComponent(String(pathParams['petId']))}`;
    return executeFetch<void>(this.config, 'DELETE', path, { ...options });
  }

  /**
   * Uploads an image
   * @route POST /pets/{petId}/uploadImage
   * @param pathParams URL path interpolation parameters
   * @param body Request payload (multipart/form-data)
   * @param query URL search query parameters
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async uploadFile(pathParams: UploadFilePathParams, body?: {
   /** File to upload @format binary */
  file?: Blob | File | undefined;
}, query?: UploadFileQueryParams, options?: RequestOptions): Promise<ApiResponse> {
    const path = `/pets/${encodeURIComponent(String(pathParams['petId']))}/uploadImage`;
    return executeFetch<ApiResponse>(this.config, 'POST', path, { ...options, query, body });
  }

  /**
   * Returns pet inventories by status
   * @route GET /store/inventory
   * @param options Additional RequestInit options
   * @throws {ApiError}
   */
  async getInventory(options?: RequestOptions): Promise<Record<string, number>> {
    const path = '/store/inventory';
    return executeFetch<Record<string, number>>(this.config, 'GET', path, { ...options });
  }

}

api = new ApiClient();
export default ApiClient;
6
Operações da API
4
Modelos TypeScript
9.5 KB
Tamanho Gerado

100% de Privacidade no Navegador

Zero uploads ou telemetria externa. Suas especificações confidenciais são analisadas estritamente na memória local do navegador.

Fetch Nativo Sem Dependências

Gera código baseado na Web Fetch API padrão, compatível com navegadores modernos, Node.js 18+, Bun, Deno e Next.js Server Components.

Serialização Totalmente Tipada

Substituição automática de parâmetros de URL, URLSearchParams para query string, multipart/form-data e tratamento estruturado de ApiError.

Referência técnica e guia de arquitetura

Guia do Desenvolvedor: Gerador de Cliente TypeScript com Fetch Nativo a partir de OpenAPI e Swagger — Guia de referência

Gere clientes de API em TypeScript com fetch nativo sem dependências externas, serialização de query string, cabeçalhos e tipagem completa.

Parâmetros principais e controles

architecture'class' | 'functional'

Define a arquitetura do código gerado: classe orientada a objetos com configuração centralizada ou funções avulsas otimizadas para tree-shaking.

Padrão: 'class'
unwrapResponse'direct' | 'envelope'

Determina o formato do retorno: dados da resposta desempacotados diretamente (Promise<T>) ou envelope HTTP completo ({ data, status, headers }).

Padrão: 'direct'
includeJsdocboolean

Insere resumos, descrições e anotações de parâmetros da OpenAPI como comentários JSDoc nos métodos TypeScript.

Padrão: true
strictNullChecksboolean

Garante propriedades opcionais estritas e uniões explícitas de nulos (T | null) totalmente alinhadas ao strict mode do TypeScript.

Padrão: true
includeTimeoutboolean

Adiciona suporte integrado a timeout configurável em milissegundos via sinais de AbortController para maior resiliência de rede.

Padrão: true
includeMockStubsboolean

Gera stubs e dados mockados realistas para facilitar testes unitários offline e prototipação de interfaces.

Padrão: false

Dicas profissionais e melhores práticas

Ao criar micro-frontends ou funções

Ao criar micro-frontends ou funções serverless edge, selecione a arquitetura 'SDK Funcional'. Empacotadores como Vite, Rollup e Webpack eliminam rotas não invocadas via tree-shaking com precisão.

Passe parâmetros de RequestInit como

Passe parâmetros de RequestInit como next: { revalidate: 60, tags: ['dados'] } ou cache: 'no-store' diretamente aos métodos gerados para controlar o cache nativo e ISR do Next.js.

Capture a classe tipada ApiError

Capture a classe tipada ApiError gerada em blocos try/catch convencionais para inspecionar códigos de status e respostas de erro sem precisar de interceptores do Axios.

Problemas comuns e solução de problemas

Referências de esquema ($ref) em definitions do Swagger 2.0 não resolvem

O analisador converte automaticamente ponteiros legados #/definitions/ do Swagger 2.0 e componentes #/components/schemas/ da OpenAPI 3.x em interfaces TypeScript no padrão PascalCase.

Parâmetros de consulta do tipo lista/array não são reconhecidos pelo backend

Ajuste a formatação de serialização de URLSearchParams conforme o padrão esperado pelo seu backend (chaves repetidas, delimitadas por vírgula ou colchetes em Express, FastAPI ou Spring).

Bloqueio por CORS ou ausência de cookies de sessão no navegador

Adicione { credentials: 'include' } na configuração do cliente ou nas opções individuais de requisição para transmitir cookies HttpOnly e cabeçalhos de autorização com segurança.

Perguntas frequentes (FAQ)

Por que gerar clientes com fetch nativo em vez de Axios ou bibliotecas pesadas?▼

O Fetch nativo é um padrão web implementado em todos os navegadores modernos, Node.js 18+, Bun, Deno e Edge runtimes. Eliminar o Axios economiza entre 15 e 40 KB de bundle e reduz vulnerabilidades de pacotes de terceiros.

Como funcionam a interpolação de rotas e a serialização de parâmetros?▼

Parâmetros na rota (ex.: /users/{id}) são interpolados com encodeURIComponent de forma segura, e parâmetros de consulta são serializados via URLSearchParams, descartando valores nulos ou indefinidos automaticamente.

Minhas especificações de API proprietárias são enviadas para algum servidor?▼

Não. Todo o processo de interpretação da especificação, geração de AST e emissão do código TypeScript ocorre 100% no navegador via memória local, garantindo sigilo absoluto.

É possível gerar React Hooks prontos para TanStack Query ou SWR?▼

Sim. Acesse a aba 'React Hooks' para copiar hooks e funções fetcher prontas para uso direto com TanStack Query (React Query) e SWR.

Como o código gerado gerencia códigos de erro HTTP (4xx e 5xx)?▼

Como o fetch nativo não rejeita requisições por códigos de erro comuns, o cliente gerado verifica response.ok, analisa o JSON de erro e lança uma exceção tipada ApiError com status e cabeçalhos.

Ferramentas e utilitários relacionados

Todas as ferramentas →
Guia do Desenvolvedor: Gerador de DDL SQL CREATE TABLE a partir de Esquemas Drizzle ORMDesenvolvimento

Converta definições pgTable, mysqlTable e sqliteTable do Drizzle ORM em scripts executáveis de migração SQL CREATE TABLE com máxima precisão.

Abrir ferramenta→
Guia do desenvolvedor para gerador de YAML do GitHub Actions CI/CDDesenvolvimento

Crie pipelines YAML de fluxo de trabalho do GitHub Actions prontos para produção para Node.js, Go, Python, builds Docker, testes automatizados e releases contínuas.

Abrir ferramenta→
Gerador de Configuração do Linux Logrotate (Retenção e Compactação)Desenvolvimento

Gere arquivos de configuração para /etc/logrotate.d/ prontos para produção com rotação diária/semanal, compactação gzip, dateext, limites de tamanho e scripts postrotate.

Abrir ferramenta→
Guia do Desenvolvedor: Gerador de Configuração YAML do Ubuntu NetplanDesenvolvimento

Gere configurações YAML do Netplan para Ubuntu 20.04/22.04/24.04: IPs estáticos, DHCP, servidores DNS, rotas de gateway, bridges e bonds.

Abrir ferramenta→
Guia do Desenvolvedor: Gerador de Modelos Python SQLAlchemy 2.0 a partir de SQL DDLDesenvolvimento

Converta instruções SQL CREATE TABLE em modelos fortemente tipados do Python SQLAlchemy 2.0 DeclarativeBase com anotações modernas Mapped e mapped_column.

Abrir ferramenta→
Guia do Desenvolvedor: Gerador de Modelos Struct GORM em Golang a partir de DDL SQLDesenvolvimento

Converta esquemas SQL CREATE TABLE em definições de struct em Golang com tags GORM, tags JSON e correspondência tipada de tipos Go.

Abrir ferramenta→