// Escrita na API: login, cadastro, alteração e remoção de um livro, com os // dois clientes. As rotas de escrita da aula 10 exigem token de ADMINISTRADOR. import axios from 'axios'; import { ADMINISTRADOR, API_URL, LEITORA, NOVO_LIVRO, descrever, type CorpoDeErro, type Livro, type Pagina, } from './api.js'; // ---------------------------------------------------------------- fetch async function loginComFetch(conta: { email: string; senha: string }): Promise { const resposta = await fetch(`${API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(conta), }); if (!resposta.ok) throw new Error(`login respondeu ${resposta.status}`); const { accessToken } = (await resposta.json()) as { accessToken: string }; return accessToken; } // Um id de autor que existe agora: os ids mudam a cada seed. const { data: acervo } = await axios.get>(`${API_URL}/livros`); const autorId = acervo.dados[0].autor.id; const livro = { ...NOVO_LIVRO, autorId }; const tokenAdmin = await loginComFetch(ADMINISTRADOR); const tokenLeitora = await loginComFetch(LEITORA); async function postarComFetch(rotulo: string, init: RequestInit): Promise { const resposta = await fetch(`${API_URL}/livros`, { method: 'POST', ...init }); const corpo = (await resposta.json()) as CorpoDeErro | Livro; // O `as` é uma promessa sua sobre o formato, não uma verificação (Parte 6). const resumo = 'detalhes' in corpo ? `${corpo.detalhes.length} detalhe(s), o primeiro: "${corpo.detalhes[0]}"` : `id ${corpo.id}`; console.log(`fetch ${rotulo.padEnd(34)} → ${resposta.status} · ${resumo}`); return resposta; } console.log('--- fetch'); // 1. Corpo em texto, sem declarar o formato: o fetch envia text/plain e a // API não interpreta o corpo como JSON. await postarComFetch('sem Content-Type', { headers: { Authorization: `Bearer ${tokenAdmin}` }, body: JSON.stringify(livro), }); // 2. Corpo correto, sem token. await postarComFetch('sem token', { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(livro), }); // 3. Token de LEITOR numa rota de ADMINISTRADOR. await postarComFetch('token de LEITOR', { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${tokenLeitora}` }, body: JSON.stringify(livro), }); // 4. Tudo certo. await postarComFetch('token de ADMINISTRADOR', { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${tokenAdmin}` }, body: JSON.stringify(livro), }); // Para remover, o id do livro recém-criado. const { data: busca } = await axios.get>(`${API_URL}/livros`, { params: { tamanho: 100 }, }); const id = busca.dados.find((l) => l.isbn === livro.isbn)!.id; // 5. Remoção: 204, sem corpo. Tentar ler JSON de um corpo vazio falha. const remocao = await fetch(`${API_URL}/livros/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${tokenAdmin}` }, }); console.log('fetch DELETE →', remocao.status, '· content-length', remocao.headers.get('content-length')); try { await remocao.json(); } catch (erro) { console.log('fetch .json() num 204 →', descrever(erro)); } // ---------------------------------------------------------------- axios console.log('--- axios'); const { data: sessao } = await axios.post<{ accessToken: string }>( `${API_URL}/auth/login`, ADMINISTRADOR, // objeto: o axios serializa e declara application/json ); const autorizacao = { headers: { Authorization: `Bearer ${sessao.accessToken}` } }; const post = await axios.post(`${API_URL}/livros`, livro, autorizacao); console.log('axios POST →', post.status, '· id', post.data.id); console.log('axios Content-Type enviado:', post.config.headers['Content-Type']); const patch = await axios.patch(`${API_URL}/livros/${post.data.id}`, { ano: 1892 }, autorizacao); console.log('axios PATCH →', patch.status, '· ano', patch.data.ano); const del = await axios.delete(`${API_URL}/livros/${post.data.id}`, autorizacao); console.log('axios DELETE →', del.status, '· data =', JSON.stringify(del.data));