Compare commits
No commits in common. "bun" and "master" have entirely different histories.
20 changed files with 1665 additions and 1118 deletions
38
AI.md
38
AI.md
|
|
@ -79,46 +79,8 @@ const respostas = gerarRespostas((op) => {
|
||||||
const r = respostas.erroInterno({ erro: new Error("boom"), local: "user.service" })
|
const r = respostas.erroInterno({ erro: new Error("boom"), local: "user.service" })
|
||||||
```
|
```
|
||||||
|
|
||||||
## Validação com Zod (`zRespostas`)
|
|
||||||
|
|
||||||
Para validar payloads de resposta recebidos de APIs ou serviços com [Zod](https://zod.dev):
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import z from "zod"
|
|
||||||
import { zRespostas, type tipoZResposta } from "p-respostas"
|
|
||||||
|
|
||||||
// 1. Validando payload com tipo específico de sucesso
|
|
||||||
const schemaUsuario = zRespostas(
|
|
||||||
z.object({
|
|
||||||
id: z.string(),
|
|
||||||
nome: z.string(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const resposta = schemaUsuario.parse(jsonRecebidoDaApi)
|
|
||||||
|
|
||||||
if (resposta.eCerto) {
|
|
||||||
// TypeScript sabe que resposta.valor tem { id: string; nome: string }
|
|
||||||
console.log("Dados do usuário:", resposta.valor.nome)
|
|
||||||
} else {
|
|
||||||
// TypeScript sabe que resposta.mensagem é string e cod é um dos códigos de erro
|
|
||||||
console.error("Falha:", resposta.mensagem, "Código:", resposta.cod)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Aceitando qualquer valor no sucesso (default z.any())
|
|
||||||
const schemaGenerico = zRespostas()
|
|
||||||
|
|
||||||
// 3. Schemas e tipos auxiliares exportados:
|
|
||||||
// - zResposta (alias idêntico a zRespostas)
|
|
||||||
// - zRespostaSucesso(zValor?)
|
|
||||||
// - zRespostaErro
|
|
||||||
// - zCodigosRespostaErro
|
|
||||||
// - tipoZResposta<T>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Garantias / restrições
|
## Garantias / restrições
|
||||||
|
|
||||||
- Este pacote é amplamente importado por outros projetos.
|
- Este pacote é amplamente importado por outros projetos.
|
||||||
- Os arquivos em `dist-*` são gerados automaticamente.
|
- Os arquivos em `dist-*` são gerados automaticamente.
|
||||||
- Mudanças aqui devem focar em **melhorar o consumo (exports/tipos/docs)** sem alterar comportamento.
|
- Mudanças aqui devem focar em **melhorar o consumo (exports/tipos/docs)** sem alterar comportamento.
|
||||||
|
|
||||||
|
|
|
||||||
22
README.md
22
README.md
|
|
@ -11,8 +11,6 @@ Contrato simples e tipado de respostas para APIs e serviços (sucesso/erro), com
|
||||||
## Instalação
|
## Instalação
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun add p-respostas
|
|
||||||
# ou
|
|
||||||
pnpm add p-respostas
|
pnpm add p-respostas
|
||||||
# ou
|
# ou
|
||||||
npm i p-respostas
|
npm i p-respostas
|
||||||
|
|
@ -70,26 +68,6 @@ Cria um conjunto de funções padronizadas para gerar respostas.
|
||||||
|
|
||||||
Instância default de `gerarRespostas(() => ({}))`.
|
Instância default de `gerarRespostas(() => ({}))`.
|
||||||
|
|
||||||
### Validação Zod (`zRespostas`)
|
|
||||||
|
|
||||||
Permite validar e inferir tipos de payloads recebidos via HTTP/APIs:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import z from "zod"
|
|
||||||
import { zRespostas } from "p-respostas"
|
|
||||||
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
const resultado = schema.parse(payload)
|
|
||||||
|
|
||||||
if (resultado.eCerto) {
|
|
||||||
console.log("Sucesso:", resultado.valor)
|
|
||||||
} else {
|
|
||||||
console.log("Erro:", resultado.mensagem, resultado.cod)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Também exporta `zResposta`, `zRespostaSucesso`, `zRespostaErro`, `zCodigosRespostaErro` e `type tipoZResposta<T>`.
|
|
||||||
|
|
||||||
## Compatibilidade
|
## Compatibilidade
|
||||||
|
|
||||||
- Node: `>=20`
|
- Node: `>=20`
|
||||||
|
|
|
||||||
98
bun.lock
98
bun.lock
|
|
@ -1,98 +0,0 @@
|
||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "p-respostas",
|
|
||||||
"devDependencies": {
|
|
||||||
"@biomejs/biome": "^2",
|
|
||||||
"@types/bun": "^1.4.2",
|
|
||||||
"@types/node": "^22.19.15",
|
|
||||||
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git#bun",
|
|
||||||
"typescript": "^7",
|
|
||||||
"zod": "4.4.3",
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git#bun",
|
|
||||||
"zod": "4.4.3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@biomejs/biome": ["@biomejs/biome@2.4.12", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.12", "@biomejs/cli-darwin-x64": "2.4.12", "@biomejs/cli-linux-arm64": "2.4.12", "@biomejs/cli-linux-arm64-musl": "2.4.12", "@biomejs/cli-linux-x64": "2.4.12", "@biomejs/cli-linux-x64-musl": "2.4.12", "@biomejs/cli-win32-arm64": "2.4.12", "@biomejs/cli-win32-x64": "2.4.12" }, "bin": { "biome": "bin/biome" } }, "sha512-Rro7adQl3NLq/zJCIL98eElXKI8eEiBtoeu5TbXF/U3qbjuSc7Jb5rjUbeHHcquDWeSf3HnGP7XI5qGrlRk/pA=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BnMU4Pc3ciEVteVpZ0BK33MLr7X57F5w1dwDLDn+/iy/yTrA4Q/N2yftidFtsA4vrDh0FMXDpacNV/Tl3fbmng=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-x9uJ0bI1rJsWICp3VH8w/5PnAVD3A7SqzDpbrfoUQX1QyWrK5jSU4fRLo/wSgGeplCivbxBRKmt5Xq4/nWvq8A=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-tOwuCuZZtKi1jVzbk/5nXmIsziOB6yqN8c9r9QM0EJYPU6DpQWf11uBOSCfFKKM4H3d9ZoarvlgMfbcuD051Pw=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-FhfpkAAlKL6kwvcVap0Hgp4AhZmtd3YImg0kK1jd7C/aSoh4SfsB2f++yG1rU0lr8Y5MCFJrcSkmssiL9Xnnig=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.12", "", { "os": "linux", "cpu": "x64" }, "sha512-8pFeAnLU9QdW9jCIslB/v82bI0lhBmz2ZAKc8pVMFPO0t0wAHsoEkrUQUbMkIorTRIjbqyNZHA3lEXavsPWYSw=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.12", "", { "os": "linux", "cpu": "x64" }, "sha512-dwTIgZrGutzhkQCuvHynCkyW6hJxUuyZqKKO0YNfaS2GUoRO+tOvxXZqZB6SkWAOdfZTzwaw8IEdUnIkHKHoew=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-B0DLnx0vA9ya/3v7XyCaP+/lCpnbWbMOfUFFve+xb5OxyYvdHaS55YsSddr228Y+JAFk58agCuZTsqNiw2a6ig=="],
|
|
||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.12", "", { "os": "win32", "cpu": "x64" }, "sha512-yMckRzTyZ83hkk8iDFWswqSdU8tvZxspJKnYNh7JZr/zhZNOlzH13k4ecboU6MurKExCe2HUkH75pGI/O2JwGA=="],
|
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.4.2", "", { "dependencies": { "bun-types": "1.4.2" } }, "sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@22.20.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="],
|
|
||||||
|
|
||||||
"@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="],
|
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.4.2", "", { "dependencies": { "@types/node": "*" } }, "sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w=="],
|
|
||||||
|
|
||||||
"dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="],
|
|
||||||
|
|
||||||
"p-comuns": ["p-comuns@git+https://git2.idz.one/publico/_comuns.git#cd4ea4d36b1ca745076865cb16d785d2e5f14446", { "peerDependencies": { "dayjs": "^1.11.18", "uuid": "^11.1.0", "zod": "4.4.3" } }, "cd4ea4d36b1ca745076865cb16d785d2e5f14446"],
|
|
||||||
|
|
||||||
"typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
|
||||||
|
|
||||||
"uuid": ["uuid@11.1.1", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ=="],
|
|
||||||
|
|
||||||
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,154 +1,123 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
var __defProp = Object.defineProperty;
|
||||||
exports.converterRespostaELicencieParaPResposta = exports.codigosErros = void 0;
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
const respostas_1 = require("./respostas");
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
// ─── Tipagem ELicencie ──────────────────────────────────────────────
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
/**
|
var __export = (target, all) => {
|
||||||
* Mapa de códigos HTTP de erro usados pelo sistema ELicencie.
|
for (var name in all)
|
||||||
*
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
* Single source of truth para derivar `codigoErroELicencie`.
|
};
|
||||||
*/
|
var __copyProps = (to, from, except, desc) => {
|
||||||
exports.codigosErros = {
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
400: "Erro de requisição",
|
for (let key of __getOwnPropNames(from))
|
||||||
403: "Não autenticado",
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
500: "Erro interno",
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
504: "Tempo de resposta excedido",
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var converter_resposta_e_licencie_para_p_resposta_exports = {};
|
||||||
|
__export(converter_resposta_e_licencie_para_p_resposta_exports, {
|
||||||
|
codigosErros: () => codigosErros,
|
||||||
|
converterRespostaELicencieParaPResposta: () => converterRespostaELicencieParaPResposta
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(converter_resposta_e_licencie_para_p_resposta_exports);
|
||||||
|
var import_respostas = require("./respostas");
|
||||||
|
const codigosErros = {
|
||||||
|
400: "Erro de requisi\xE7\xE3o",
|
||||||
|
403: "N\xE3o autenticado",
|
||||||
|
500: "Erro interno",
|
||||||
|
504: "Tempo de resposta excedido"
|
||||||
};
|
};
|
||||||
// ─── Mapeamento bidirecional de códigos ─────────────────────────────
|
|
||||||
/** ELicencie → P-Resposta (403 → 401) */
|
|
||||||
const mapaCodigoELicencieParaPResposta = {
|
const mapaCodigoELicencieParaPResposta = {
|
||||||
400: respostas_1.codigosResposta.erroConhecido,
|
400: import_respostas.codigosResposta.erroConhecido,
|
||||||
403: respostas_1.codigosResposta.erroPermissao,
|
403: import_respostas.codigosResposta.erroPermissao,
|
||||||
500: respostas_1.codigosResposta.erroDesconhecido,
|
500: import_respostas.codigosResposta.erroDesconhecido,
|
||||||
504: respostas_1.codigosResposta.tempoEsgotado,
|
504: import_respostas.codigosResposta.tempoEsgotado
|
||||||
};
|
};
|
||||||
/** P-Resposta → ELicencie (401 → 403, 404 → 400) */
|
|
||||||
const mapaCodigoPRespostaParaELicencie = {
|
const mapaCodigoPRespostaParaELicencie = {
|
||||||
[respostas_1.codigosResposta.erroConhecido]: 400,
|
[import_respostas.codigosResposta.erroConhecido]: 400,
|
||||||
[respostas_1.codigosResposta.erroPermissao]: 403,
|
[import_respostas.codigosResposta.erroPermissao]: 403,
|
||||||
[respostas_1.codigosResposta.erroDesconhecido]: 500,
|
[import_respostas.codigosResposta.erroDesconhecido]: 500,
|
||||||
[respostas_1.codigosResposta.erroNaoEncontrado]: 400,
|
[import_respostas.codigosResposta.erroNaoEncontrado]: 400,
|
||||||
[respostas_1.codigosResposta.tempoEsgotado]: 504,
|
[import_respostas.codigosResposta.tempoEsgotado]: 504
|
||||||
};
|
};
|
||||||
// ─── Type guard ─────────────────────────────────────────────────────
|
|
||||||
/** Detecta se a entrada já está no formato P-Resposta (possui campo `cod`). */
|
|
||||||
function eRespostaPadrao(entrada) {
|
function eRespostaPadrao(entrada) {
|
||||||
return "cod" in entrada;
|
return "cod" in entrada;
|
||||||
}
|
}
|
||||||
// ─── Conversores de detalhes ────────────────────────────────────────
|
|
||||||
/** `Record<string, any>` → `string[]` (passthrough se já for array). */
|
|
||||||
function detalhesParaArray(detalhes) {
|
function detalhesParaArray(detalhes) {
|
||||||
if (!detalhes)
|
if (!detalhes) return void 0;
|
||||||
return undefined;
|
if (Array.isArray(detalhes)) return detalhes;
|
||||||
if (Array.isArray(detalhes))
|
const entries = Object.entries(detalhes);
|
||||||
return detalhes;
|
if (entries.length === 0) return void 0;
|
||||||
const entries = Object.entries(detalhes);
|
return entries.map(([chave, valor]) => {
|
||||||
if (entries.length === 0)
|
const valorStr = typeof valor === "string" ? valor : JSON.stringify(valor);
|
||||||
return undefined;
|
return `${chave}: ${valorStr}`;
|
||||||
return entries.map(([chave, valor]) => {
|
});
|
||||||
const valorStr = typeof valor === "string" ? valor : JSON.stringify(valor);
|
|
||||||
return `${chave}: ${valorStr}`;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// ─── Builder de resposta dual ───────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Monta um objeto compatível com **ambos** os formatos em runtime.
|
|
||||||
*
|
|
||||||
* Tipado como `tipoResposta<T>`, mas em runtime também contém
|
|
||||||
* `codigo`, `erro` e `detalhes` (Record) do formato ELicencie.
|
|
||||||
*/
|
|
||||||
function montarRespostaDual(op) {
|
function montarRespostaDual(op) {
|
||||||
const detalhesArray = detalhesParaArray(op.detalhesOriginal);
|
const detalhesArray = detalhesParaArray(op.detalhesOriginal);
|
||||||
const detalhesRecord = op.detalhesOriginal && !Array.isArray(op.detalhesOriginal) ? op.detalhesOriginal : undefined;
|
const detalhesRecord = op.detalhesOriginal && !Array.isArray(op.detalhesOriginal) ? op.detalhesOriginal : void 0;
|
||||||
return {
|
return {
|
||||||
// P-Resposta
|
// P-Resposta
|
||||||
cod: op.cod,
|
cod: op.cod,
|
||||||
valor: op.valor,
|
valor: op.valor,
|
||||||
mensagem: op.mensagem,
|
mensagem: op.mensagem,
|
||||||
eErro: op.eErro,
|
eErro: op.eErro,
|
||||||
eCerto: !op.eErro,
|
eCerto: !op.eErro,
|
||||||
detalhes: detalhesArray,
|
detalhes: detalhesArray,
|
||||||
// ELicencie (runtime)
|
// ELicencie (runtime)
|
||||||
codigo: op.codigoELicencie,
|
codigo: op.codigoELicencie,
|
||||||
erro: op.erroELicencie,
|
erro: op.erroELicencie,
|
||||||
...(detalhesRecord ? { detalhes: detalhesRecord } : {}),
|
...detalhesRecord ? { detalhes: detalhesRecord } : {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// ─── Conversor principal ────────────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Converte uma resposta para o formato **P-Resposta** (padrão do pacote),
|
|
||||||
* mantendo em runtime os campos de **ambos** os formatos para
|
|
||||||
* compatibilidade durante a transição de sistema.
|
|
||||||
*
|
|
||||||
* **Tipo de retorno:** `tipoResposta<T>`
|
|
||||||
*
|
|
||||||
* **Conteúdo em runtime:** campos P-Resposta + campos ELicencie
|
|
||||||
*
|
|
||||||
* | P-Resposta | ELicencie | Relação |
|
|
||||||
* |-------------|-------------|----------------------|
|
|
||||||
* | `cod` | `codigo` | mapeamento de código |
|
|
||||||
* | `mensagem` | `erro` | mesmo conteúdo |
|
|
||||||
* | `valor` | `valor` | direto |
|
|
||||||
* | `eErro` | `eErro` | direto |
|
|
||||||
* | `eCerto` | — | derivado |
|
|
||||||
* | `detalhes` | `detalhes` | string[] / Record |
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* const res = converterRespostaELicencieParaPResposta(respostaQualquer)
|
|
||||||
*
|
|
||||||
* // Consumidor P-Resposta
|
|
||||||
* if (res.eCerto) console.log(res.valor)
|
|
||||||
*
|
|
||||||
* // Consumidor ELicencie (lê campo extra em runtime)
|
|
||||||
* const resAny = res as any
|
|
||||||
* if (!resAny.eErro) console.log(resAny.valor)
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
const converterRespostaELicencieParaPResposta = (entrada) => {
|
const converterRespostaELicencieParaPResposta = (entrada) => {
|
||||||
// ── Entrada já é P-Resposta: enriquecer com campos ELicencie ──
|
if (eRespostaPadrao(entrada)) {
|
||||||
if (eRespostaPadrao(entrada)) {
|
|
||||||
if (!entrada.eErro) {
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: respostas_1.codigosResposta.sucesso,
|
|
||||||
valor: entrada.valor,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
codigoELicencie: 200,
|
|
||||||
erroELicencie: undefined,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: entrada.cod,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: entrada.mensagem,
|
|
||||||
eErro: true,
|
|
||||||
codigoELicencie: mapaCodigoPRespostaParaELicencie[entrada.cod],
|
|
||||||
erroELicencie: entrada.mensagem,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// ── Entrada é ELicencie: construir P-Resposta + preservar campos ──
|
|
||||||
if (!entrada.eErro) {
|
if (!entrada.eErro) {
|
||||||
return montarRespostaDual({
|
return montarRespostaDual({
|
||||||
cod: respostas_1.codigosResposta.sucesso,
|
cod: import_respostas.codigosResposta.sucesso,
|
||||||
valor: entrada.valor,
|
valor: entrada.valor,
|
||||||
mensagem: undefined,
|
mensagem: void 0,
|
||||||
eErro: false,
|
eErro: false,
|
||||||
codigoELicencie: entrada.codigo,
|
codigoELicencie: 200,
|
||||||
erroELicencie: undefined,
|
erroELicencie: void 0,
|
||||||
detalhesOriginal: entrada.detalhes,
|
detalhesOriginal: entrada.detalhes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return montarRespostaDual({
|
return montarRespostaDual({
|
||||||
cod: mapaCodigoELicencieParaPResposta[entrada.codigo],
|
cod: entrada.cod,
|
||||||
valor: undefined,
|
valor: void 0,
|
||||||
mensagem: entrada.erro,
|
mensagem: entrada.mensagem,
|
||||||
eErro: true,
|
eErro: true,
|
||||||
codigoELicencie: entrada.codigo,
|
codigoELicencie: mapaCodigoPRespostaParaELicencie[entrada.cod],
|
||||||
erroELicencie: entrada.erro,
|
erroELicencie: entrada.mensagem,
|
||||||
detalhesOriginal: entrada.detalhes,
|
detalhesOriginal: entrada.detalhes
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (!entrada.eErro) {
|
||||||
|
return montarRespostaDual({
|
||||||
|
cod: import_respostas.codigosResposta.sucesso,
|
||||||
|
valor: entrada.valor,
|
||||||
|
mensagem: void 0,
|
||||||
|
eErro: false,
|
||||||
|
codigoELicencie: entrada.codigo,
|
||||||
|
erroELicencie: void 0,
|
||||||
|
detalhesOriginal: entrada.detalhes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return montarRespostaDual({
|
||||||
|
cod: mapaCodigoELicencieParaPResposta[entrada.codigo],
|
||||||
|
valor: void 0,
|
||||||
|
mensagem: entrada.erro,
|
||||||
|
eErro: true,
|
||||||
|
codigoELicencie: entrada.codigo,
|
||||||
|
erroELicencie: entrada.erro,
|
||||||
|
detalhesOriginal: entrada.detalhes
|
||||||
|
});
|
||||||
};
|
};
|
||||||
exports.converterRespostaELicencieParaPResposta = converterRespostaELicencieParaPResposta;
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
codigosErros,
|
||||||
|
converterRespostaELicencieParaPResposta
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
// Re-export da API pública do pacote.
|
var __defProp = Object.defineProperty;
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
if (k2 === undefined) k2 = k;
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
var __copyProps = (to, from, except, desc) => {
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
}
|
for (let key of __getOwnPropNames(from))
|
||||||
Object.defineProperty(o, k2, desc);
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
}) : (function(o, m, k, k2) {
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
if (k2 === undefined) k2 = k;
|
}
|
||||||
o[k2] = m[k];
|
return to;
|
||||||
}));
|
|
||||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
||||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
||||||
__exportStar(require("./converter-resposta-e-licencie-para-p-resposta"), exports);
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
__exportStar(require("./respostas"), exports);
|
var index_exports = {};
|
||||||
|
module.exports = __toCommonJS(index_exports);
|
||||||
|
__reExport(index_exports, require("./converter-resposta-e-licencie-para-p-resposta"), module.exports);
|
||||||
|
__reExport(index_exports, require("./respostas"), module.exports);
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
...require("./converter-resposta-e-licencie-para-p-resposta"),
|
||||||
|
...require("./respostas")
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,156 +1,162 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
var __defProp = Object.defineProperty;
|
||||||
exports.respostaComuns = exports.gerarRespostas = exports.IniciarRespostas = exports.codigosResposta = void 0;
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
/**
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
* Códigos padrão usados pelo contrato de respostas.
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
*
|
var __export = (target, all) => {
|
||||||
* Observação: este enum é parte da API pública do pacote.
|
for (var name in all)
|
||||||
*/
|
__defProp(target, name, { get: all[name], enumerable: true });
|
||||||
var codigosResposta;
|
|
||||||
(function (codigosResposta) {
|
|
||||||
codigosResposta[codigosResposta["sucesso"] = 200] = "sucesso";
|
|
||||||
codigosResposta[codigosResposta["erroConhecido"] = 400] = "erroConhecido";
|
|
||||||
codigosResposta[codigosResposta["erroPermissao"] = 401] = "erroPermissao";
|
|
||||||
codigosResposta[codigosResposta["erroNaoEncontrado"] = 404] = "erroNaoEncontrado";
|
|
||||||
codigosResposta[codigosResposta["erroDesconhecido"] = 500] = "erroDesconhecido";
|
|
||||||
codigosResposta[codigosResposta["tempoEsgotado"] = 504] = "tempoEsgotado";
|
|
||||||
})(codigosResposta || (exports.codigosResposta = codigosResposta = {}));
|
|
||||||
// ─── Helper interno ─────────────────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Aplica o callback de interceptação quando fornecido.
|
|
||||||
* Retorno com cast seguro: o callback preserva a forma da resposta,
|
|
||||||
* mas o TypeScript não consegue estreitar o genérico <X> ao subtipo
|
|
||||||
* concreto (ex.: tipoRespostaSucesso<T>), então o cast é inevitável
|
|
||||||
* e está isolado neste único ponto.
|
|
||||||
*/
|
|
||||||
function aplicarCallback(resposta, callback) {
|
|
||||||
if (!callback)
|
|
||||||
return resposta;
|
|
||||||
return callback(resposta);
|
|
||||||
}
|
|
||||||
const IniciarRespostas = (
|
|
||||||
/** Callback opcional de interceptação — invocado após a construção de cada resposta */
|
|
||||||
callback) => {
|
|
||||||
const valor = (valor, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
eCerto: true,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const valorTrue = (detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor: true,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
eCerto: true,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erro = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroConhecido,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem,
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroPermissao = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroPermissao,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem || "Sem permissão para esse recurso.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const naoEncontrado = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroNaoEncontrado,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem ||
|
|
||||||
"Registro não encontrado ou a execução dessa ação depende de um registro existente.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroInterno = (op) => {
|
|
||||||
const mensagemFim = `${op.mensagem || "Erro interno"}`;
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroDesconhecido,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagemFim,
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const tempoEsgotado = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.tempoEsgotado,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroEspera = tempoEsgotado;
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de sucesso
|
|
||||||
*/
|
|
||||||
valor,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de sucesso com valor true
|
|
||||||
*/
|
|
||||||
valorTrue,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro conhecido
|
|
||||||
*/
|
|
||||||
erro,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
|
|
||||||
*/
|
|
||||||
erroPermissao,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
|
|
||||||
*/
|
|
||||||
erroInterno,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
|
|
||||||
*/
|
|
||||||
naoEncontrado,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
|
||||||
*/
|
|
||||||
tempoEsgotado,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
|
||||||
*/
|
|
||||||
erroEspera,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
exports.IniciarRespostas = IniciarRespostas;
|
var __copyProps = (to, from, except, desc) => {
|
||||||
/**
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
* @deprecated Use IniciarRespostas em seu lugar
|
for (let key of __getOwnPropNames(from))
|
||||||
*/
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
exports.gerarRespostas = exports.IniciarRespostas;
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
/**
|
}
|
||||||
* Instância default (sem handler de interceptação).
|
return to;
|
||||||
*/
|
};
|
||||||
exports.respostaComuns = (0, exports.IniciarRespostas)();
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||||
|
var respostas_exports = {};
|
||||||
|
__export(respostas_exports, {
|
||||||
|
IniciarRespostas: () => IniciarRespostas,
|
||||||
|
codigosResposta: () => codigosResposta,
|
||||||
|
gerarRespostas: () => gerarRespostas,
|
||||||
|
respostaComuns: () => respostaComuns
|
||||||
|
});
|
||||||
|
module.exports = __toCommonJS(respostas_exports);
|
||||||
|
var codigosResposta = /* @__PURE__ */ ((codigosResposta2) => {
|
||||||
|
codigosResposta2[codigosResposta2["sucesso"] = 200] = "sucesso";
|
||||||
|
codigosResposta2[codigosResposta2["erroConhecido"] = 400] = "erroConhecido";
|
||||||
|
codigosResposta2[codigosResposta2["erroPermissao"] = 401] = "erroPermissao";
|
||||||
|
codigosResposta2[codigosResposta2["erroNaoEncontrado"] = 404] = "erroNaoEncontrado";
|
||||||
|
codigosResposta2[codigosResposta2["erroDesconhecido"] = 500] = "erroDesconhecido";
|
||||||
|
codigosResposta2[codigosResposta2["tempoEsgotado"] = 504] = "tempoEsgotado";
|
||||||
|
return codigosResposta2;
|
||||||
|
})(codigosResposta || {});
|
||||||
|
function aplicarCallback(resposta, callback) {
|
||||||
|
if (!callback) return resposta;
|
||||||
|
return callback(resposta);
|
||||||
|
}
|
||||||
|
const IniciarRespostas = (callback) => {
|
||||||
|
const valor = (valor2, detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 200 /* sucesso */,
|
||||||
|
valor: valor2,
|
||||||
|
mensagem: void 0,
|
||||||
|
eErro: false,
|
||||||
|
eCerto: true,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const valorTrue = (detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 200 /* sucesso */,
|
||||||
|
valor: true,
|
||||||
|
mensagem: void 0,
|
||||||
|
eErro: false,
|
||||||
|
eCerto: true,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const erro = (mensagem, detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 400 /* erroConhecido */,
|
||||||
|
valor: void 0,
|
||||||
|
mensagem,
|
||||||
|
eErro: true,
|
||||||
|
eCerto: false,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const erroPermissao = (mensagem, detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 401 /* erroPermissao */,
|
||||||
|
valor: void 0,
|
||||||
|
mensagem: mensagem || "Sem permiss\xE3o para esse recurso.",
|
||||||
|
eErro: true,
|
||||||
|
eCerto: false,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const naoEncontrado = (mensagem, detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 404 /* erroNaoEncontrado */,
|
||||||
|
valor: void 0,
|
||||||
|
mensagem: mensagem || "Registro n\xE3o encontrado ou a execu\xE7\xE3o dessa a\xE7\xE3o depende de um registro existente.",
|
||||||
|
eErro: true,
|
||||||
|
eCerto: false,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const erroInterno = (op) => {
|
||||||
|
const mensagemFim = `${op.mensagem || "Erro interno"}`;
|
||||||
|
const resposta = {
|
||||||
|
cod: 500 /* erroDesconhecido */,
|
||||||
|
valor: void 0,
|
||||||
|
mensagem: mensagemFim,
|
||||||
|
eErro: true,
|
||||||
|
eCerto: false
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const tempoEsgotado = (mensagem, detalhes) => {
|
||||||
|
const resposta = {
|
||||||
|
cod: 504 /* tempoEsgotado */,
|
||||||
|
valor: void 0,
|
||||||
|
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
|
||||||
|
eErro: true,
|
||||||
|
eCerto: false,
|
||||||
|
detalhes
|
||||||
|
};
|
||||||
|
return aplicarCallback(resposta, callback);
|
||||||
|
};
|
||||||
|
const erroEspera = tempoEsgotado;
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de sucesso
|
||||||
|
*/
|
||||||
|
valor,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de sucesso com valor true
|
||||||
|
*/
|
||||||
|
valorTrue,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro conhecido
|
||||||
|
*/
|
||||||
|
erro,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
|
||||||
|
*/
|
||||||
|
erroPermissao,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
|
||||||
|
*/
|
||||||
|
erroInterno,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
|
||||||
|
*/
|
||||||
|
naoEncontrado,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
||||||
|
*/
|
||||||
|
tempoEsgotado,
|
||||||
|
/**
|
||||||
|
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
||||||
|
*/
|
||||||
|
erroEspera
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const gerarRespostas = IniciarRespostas;
|
||||||
|
const respostaComuns = IniciarRespostas();
|
||||||
|
// Annotate the CommonJS export names for ESM import in node:
|
||||||
|
0 && (module.exports = {
|
||||||
|
IniciarRespostas,
|
||||||
|
codigosResposta,
|
||||||
|
gerarRespostas,
|
||||||
|
respostaComuns
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
import { codigosResposta } from "./respostas";
|
|
||||||
// ─── Tipagem ELicencie ──────────────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Mapa de códigos HTTP de erro usados pelo sistema ELicencie.
|
|
||||||
*
|
|
||||||
* Single source of truth para derivar `codigoErroELicencie`.
|
|
||||||
*/
|
|
||||||
export const codigosErros = {
|
|
||||||
400: "Erro de requisição",
|
|
||||||
403: "Não autenticado",
|
|
||||||
500: "Erro interno",
|
|
||||||
504: "Tempo de resposta excedido",
|
|
||||||
};
|
|
||||||
// ─── Mapeamento bidirecional de códigos ─────────────────────────────
|
|
||||||
/** ELicencie → P-Resposta (403 → 401) */
|
|
||||||
const mapaCodigoELicencieParaPResposta = {
|
|
||||||
400: codigosResposta.erroConhecido,
|
|
||||||
403: codigosResposta.erroPermissao,
|
|
||||||
500: codigosResposta.erroDesconhecido,
|
|
||||||
504: codigosResposta.tempoEsgotado,
|
|
||||||
};
|
|
||||||
/** P-Resposta → ELicencie (401 → 403, 404 → 400) */
|
|
||||||
const mapaCodigoPRespostaParaELicencie = {
|
|
||||||
[codigosResposta.erroConhecido]: 400,
|
|
||||||
[codigosResposta.erroPermissao]: 403,
|
|
||||||
[codigosResposta.erroDesconhecido]: 500,
|
|
||||||
[codigosResposta.erroNaoEncontrado]: 400,
|
|
||||||
[codigosResposta.tempoEsgotado]: 504,
|
|
||||||
};
|
|
||||||
// ─── Type guard ─────────────────────────────────────────────────────
|
|
||||||
/** Detecta se a entrada já está no formato P-Resposta (possui campo `cod`). */
|
|
||||||
function eRespostaPadrao(entrada) {
|
|
||||||
return "cod" in entrada;
|
|
||||||
}
|
|
||||||
// ─── Conversores de detalhes ────────────────────────────────────────
|
|
||||||
/** `Record<string, any>` → `string[]` (passthrough se já for array). */
|
|
||||||
function detalhesParaArray(detalhes) {
|
|
||||||
if (!detalhes)
|
|
||||||
return undefined;
|
|
||||||
if (Array.isArray(detalhes))
|
|
||||||
return detalhes;
|
|
||||||
const entries = Object.entries(detalhes);
|
|
||||||
if (entries.length === 0)
|
|
||||||
return undefined;
|
|
||||||
return entries.map(([chave, valor]) => {
|
|
||||||
const valorStr = typeof valor === "string" ? valor : JSON.stringify(valor);
|
|
||||||
return `${chave}: ${valorStr}`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// ─── Builder de resposta dual ───────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Monta um objeto compatível com **ambos** os formatos em runtime.
|
|
||||||
*
|
|
||||||
* Tipado como `tipoResposta<T>`, mas em runtime também contém
|
|
||||||
* `codigo`, `erro` e `detalhes` (Record) do formato ELicencie.
|
|
||||||
*/
|
|
||||||
function montarRespostaDual(op) {
|
|
||||||
const detalhesArray = detalhesParaArray(op.detalhesOriginal);
|
|
||||||
const detalhesRecord = op.detalhesOriginal && !Array.isArray(op.detalhesOriginal) ? op.detalhesOriginal : undefined;
|
|
||||||
return {
|
|
||||||
// P-Resposta
|
|
||||||
cod: op.cod,
|
|
||||||
valor: op.valor,
|
|
||||||
mensagem: op.mensagem,
|
|
||||||
eErro: op.eErro,
|
|
||||||
eCerto: !op.eErro,
|
|
||||||
detalhes: detalhesArray,
|
|
||||||
// ELicencie (runtime)
|
|
||||||
codigo: op.codigoELicencie,
|
|
||||||
erro: op.erroELicencie,
|
|
||||||
...(detalhesRecord ? { detalhes: detalhesRecord } : {}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// ─── Conversor principal ────────────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Converte uma resposta para o formato **P-Resposta** (padrão do pacote),
|
|
||||||
* mantendo em runtime os campos de **ambos** os formatos para
|
|
||||||
* compatibilidade durante a transição de sistema.
|
|
||||||
*
|
|
||||||
* **Tipo de retorno:** `tipoResposta<T>`
|
|
||||||
*
|
|
||||||
* **Conteúdo em runtime:** campos P-Resposta + campos ELicencie
|
|
||||||
*
|
|
||||||
* | P-Resposta | ELicencie | Relação |
|
|
||||||
* |-------------|-------------|----------------------|
|
|
||||||
* | `cod` | `codigo` | mapeamento de código |
|
|
||||||
* | `mensagem` | `erro` | mesmo conteúdo |
|
|
||||||
* | `valor` | `valor` | direto |
|
|
||||||
* | `eErro` | `eErro` | direto |
|
|
||||||
* | `eCerto` | — | derivado |
|
|
||||||
* | `detalhes` | `detalhes` | string[] / Record |
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* const res = converterRespostaELicencieParaPResposta(respostaQualquer)
|
|
||||||
*
|
|
||||||
* // Consumidor P-Resposta
|
|
||||||
* if (res.eCerto) console.log(res.valor)
|
|
||||||
*
|
|
||||||
* // Consumidor ELicencie (lê campo extra em runtime)
|
|
||||||
* const resAny = res as any
|
|
||||||
* if (!resAny.eErro) console.log(resAny.valor)
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const converterRespostaELicencieParaPResposta = (entrada) => {
|
|
||||||
// ── Entrada já é P-Resposta: enriquecer com campos ELicencie ──
|
|
||||||
if (eRespostaPadrao(entrada)) {
|
|
||||||
if (!entrada.eErro) {
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor: entrada.valor,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
codigoELicencie: 200,
|
|
||||||
erroELicencie: undefined,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: entrada.cod,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: entrada.mensagem,
|
|
||||||
eErro: true,
|
|
||||||
codigoELicencie: mapaCodigoPRespostaParaELicencie[entrada.cod],
|
|
||||||
erroELicencie: entrada.mensagem,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// ── Entrada é ELicencie: construir P-Resposta + preservar campos ──
|
|
||||||
if (!entrada.eErro) {
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor: entrada.valor,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
codigoELicencie: entrada.codigo,
|
|
||||||
erroELicencie: undefined,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return montarRespostaDual({
|
|
||||||
cod: mapaCodigoELicencieParaPResposta[entrada.codigo],
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: entrada.erro,
|
|
||||||
eErro: true,
|
|
||||||
codigoELicencie: entrada.codigo,
|
|
||||||
erroELicencie: entrada.erro,
|
|
||||||
detalhesOriginal: entrada.detalhes,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
136
dist-front/index.d.mts
Normal file
136
dist-front/index.d.mts
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
/**
|
||||||
|
* Códigos padrão usados pelo contrato de respostas.
|
||||||
|
*
|
||||||
|
* Observação: este enum é parte da API pública do pacote.
|
||||||
|
*/
|
||||||
|
declare enum codigosResposta {
|
||||||
|
sucesso = 200,
|
||||||
|
erroConhecido = 400,
|
||||||
|
erroPermissao = 401,
|
||||||
|
erroNaoEncontrado = 404,
|
||||||
|
erroDesconhecido = 500,
|
||||||
|
tempoEsgotado = 504
|
||||||
|
}
|
||||||
|
type tipoRespostaSucesso<T> = {
|
||||||
|
cod: codigosResposta.sucesso;
|
||||||
|
valor: T;
|
||||||
|
mensagem: undefined;
|
||||||
|
eErro: false;
|
||||||
|
eCerto: true;
|
||||||
|
detalhes?: string[];
|
||||||
|
};
|
||||||
|
type tipoRespostaErro = {
|
||||||
|
cod: codigosResposta.erroConhecido | codigosResposta.erroDesconhecido | codigosResposta.erroPermissao | codigosResposta.erroNaoEncontrado | codigosResposta.tempoEsgotado;
|
||||||
|
valor: undefined;
|
||||||
|
mensagem: string;
|
||||||
|
eErro: true;
|
||||||
|
eCerto: false;
|
||||||
|
detalhes?: string[];
|
||||||
|
};
|
||||||
|
type tipoResposta<T> = tipoRespostaSucesso<T> | tipoRespostaErro;
|
||||||
|
type tipoPrErroInterno = {
|
||||||
|
erro: any;
|
||||||
|
mensagem?: string;
|
||||||
|
local: string;
|
||||||
|
__filename?: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Tipo do callback opcional de interceptação de respostas.
|
||||||
|
*
|
||||||
|
* Quando fornecido, é invocado após a construção de toda resposta,
|
||||||
|
* permitindo side-effects (ex.: logging, telemetria) sem alterar o tipo.
|
||||||
|
*/
|
||||||
|
type tipoCallbackResposta = <X>(resposta: tipoResposta<X>) => tipoResposta<X>;
|
||||||
|
/**
|
||||||
|
* Cria um conjunto de geradores de respostas.
|
||||||
|
*
|
||||||
|
* @param registrarErroInterno callback para registrar/normalizar erros internos.
|
||||||
|
*/
|
||||||
|
interface InterfaceRespostas {
|
||||||
|
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>;
|
||||||
|
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>;
|
||||||
|
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro;
|
||||||
|
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
|
||||||
|
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro;
|
||||||
|
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
|
||||||
|
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
|
||||||
|
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
|
||||||
|
}
|
||||||
|
declare const IniciarRespostas: (
|
||||||
|
/** Callback opcional de interceptação — invocado após a construção de cada resposta */
|
||||||
|
callback?: tipoCallbackResposta) => InterfaceRespostas;
|
||||||
|
/**
|
||||||
|
* @deprecated Use IniciarRespostas em seu lugar
|
||||||
|
*/
|
||||||
|
declare const gerarRespostas: (callback?: tipoCallbackResposta) => InterfaceRespostas;
|
||||||
|
/**
|
||||||
|
* Instância default (sem handler de interceptação).
|
||||||
|
*/
|
||||||
|
declare const respostaComuns: InterfaceRespostas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapa de códigos HTTP de erro usados pelo sistema ELicencie.
|
||||||
|
*
|
||||||
|
* Single source of truth para derivar `codigoErroELicencie`.
|
||||||
|
*/
|
||||||
|
declare const codigosErros: {
|
||||||
|
readonly 400: "Erro de requisição";
|
||||||
|
readonly 403: "Não autenticado";
|
||||||
|
readonly 500: "Erro interno";
|
||||||
|
readonly 504: "Tempo de resposta excedido";
|
||||||
|
};
|
||||||
|
/** Códigos HTTP de erro reconhecidos pelo ELicencie. */
|
||||||
|
type codigoErroELicencie = keyof typeof codigosErros;
|
||||||
|
interface tipoRespostaSucessoELicencie<T> {
|
||||||
|
codigo: 200;
|
||||||
|
eErro: false;
|
||||||
|
valor: T;
|
||||||
|
erro: undefined;
|
||||||
|
detalhes?: Record<string, any>;
|
||||||
|
}
|
||||||
|
interface tipoRespostaErroELicencie {
|
||||||
|
codigo: codigoErroELicencie;
|
||||||
|
eErro: true;
|
||||||
|
erro: string;
|
||||||
|
valor: undefined;
|
||||||
|
detalhes?: Record<string, any>;
|
||||||
|
}
|
||||||
|
type tipoRespostaELicencie<T> = tipoRespostaSucessoELicencie<T> | tipoRespostaErroELicencie;
|
||||||
|
/**
|
||||||
|
* Durante a transição de sistema, a entrada pode chegar em qualquer um
|
||||||
|
* dos dois formatos. O conversor detecta e normaliza para P-Resposta.
|
||||||
|
*/
|
||||||
|
type tipoEntradaTransicao<T> = tipoRespostaELicencie<T> | tipoResposta<T>;
|
||||||
|
/**
|
||||||
|
* Converte uma resposta para o formato **P-Resposta** (padrão do pacote),
|
||||||
|
* mantendo em runtime os campos de **ambos** os formatos para
|
||||||
|
* compatibilidade durante a transição de sistema.
|
||||||
|
*
|
||||||
|
* **Tipo de retorno:** `tipoResposta<T>`
|
||||||
|
*
|
||||||
|
* **Conteúdo em runtime:** campos P-Resposta + campos ELicencie
|
||||||
|
*
|
||||||
|
* | P-Resposta | ELicencie | Relação |
|
||||||
|
* |-------------|-------------|----------------------|
|
||||||
|
* | `cod` | `codigo` | mapeamento de código |
|
||||||
|
* | `mensagem` | `erro` | mesmo conteúdo |
|
||||||
|
* | `valor` | `valor` | direto |
|
||||||
|
* | `eErro` | `eErro` | direto |
|
||||||
|
* | `eCerto` | — | derivado |
|
||||||
|
* | `detalhes` | `detalhes` | string[] / Record |
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const res = converterRespostaELicencieParaPResposta(respostaQualquer)
|
||||||
|
*
|
||||||
|
* // Consumidor P-Resposta
|
||||||
|
* if (res.eCerto) console.log(res.valor)
|
||||||
|
*
|
||||||
|
* // Consumidor ELicencie (lê campo extra em runtime)
|
||||||
|
* const resAny = res as any
|
||||||
|
* if (!resAny.eErro) console.log(resAny.valor)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
declare const converterRespostaELicencieParaPResposta: <T>(entrada: tipoEntradaTransicao<T>) => tipoResposta<T>;
|
||||||
|
|
||||||
|
export { IniciarRespostas, type InterfaceRespostas, type codigoErroELicencie, codigosErros, codigosResposta, converterRespostaELicencieParaPResposta, gerarRespostas, respostaComuns, type tipoCallbackResposta, type tipoEntradaTransicao, type tipoPrErroInterno, type tipoResposta, type tipoRespostaELicencie, type tipoRespostaErro, type tipoRespostaErroELicencie, type tipoRespostaSucesso, type tipoRespostaSucessoELicencie };
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
// Re-export da API pública do pacote.
|
|
||||||
export * from "./converter-resposta-e-licencie-para-p-resposta";
|
|
||||||
export * from "./respostas";
|
|
||||||
1
dist-front/index.mjs
Normal file
1
dist-front/index.mjs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
var l=(o=>(o[o.sucesso=200]="sucesso",o[o.erroConhecido=400]="erroConhecido",o[o.erroPermissao=401]="erroPermissao",o[o.erroNaoEncontrado=404]="erroNaoEncontrado",o[o.erroDesconhecido=500]="erroDesconhecido",o[o.tempoEsgotado=504]="tempoEsgotado",o))(l||{});function n(e,t){return t?t(e):e}var u=e=>{let t=(r,s)=>n({cod:200,valor:r,mensagem:void 0,eErro:!1,eCerto:!0,detalhes:s},e),i=r=>n({cod:200,valor:!0,mensagem:void 0,eErro:!1,eCerto:!0,detalhes:r},e),c=(r,s)=>n({cod:400,valor:void 0,mensagem:r,eErro:!0,eCerto:!1,detalhes:s},e),d=(r,s)=>n({cod:401,valor:void 0,mensagem:r||"Sem permiss\xE3o para esse recurso.",eErro:!0,eCerto:!1,detalhes:s},e),E=(r,s)=>n({cod:404,valor:void 0,mensagem:r||"Registro n\xE3o encontrado ou a execu\xE7\xE3o dessa a\xE7\xE3o depende de um registro existente.",eErro:!0,eCerto:!1,detalhes:s},e),o=r=>{let a={cod:500,valor:void 0,mensagem:`${r.mensagem||"Erro interno"}`,eErro:!0,eCerto:!1};return n(a,e)},g=(r,s)=>n({cod:504,valor:void 0,mensagem:r||"Tempo de resposta esgotado ao tentar acessar o recurso.",eErro:!0,eCerto:!1,detalhes:s},e);return{valor:t,valorTrue:i,erro:c,erroPermissao:d,erroInterno:o,naoEncontrado:E,tempoEsgotado:g,erroEspera:g}},L=u,y=u();var x={400:"Erro de requisi\xE7\xE3o",403:"N\xE3o autenticado",500:"Erro interno",504:"Tempo de resposta excedido"},m={400:400,403:401,500:500,504:504},R={400:400,401:403,500:500,404:400,504:504};function f(e){return"cod"in e}function T(e){if(!e)return;if(Array.isArray(e))return e;let t=Object.entries(e);if(t.length!==0)return t.map(([i,c])=>{let d=typeof c=="string"?c:JSON.stringify(c);return`${i}: ${d}`})}function p(e){let t=T(e.detalhesOriginal),i=e.detalhesOriginal&&!Array.isArray(e.detalhesOriginal)?e.detalhesOriginal:void 0;return{cod:e.cod,valor:e.valor,mensagem:e.mensagem,eErro:e.eErro,eCerto:!e.eErro,detalhes:t,codigo:e.codigoELicencie,erro:e.erroELicencie,...i?{detalhes:i}:{}}}var C=e=>f(e)?e.eErro?p({cod:e.cod,valor:void 0,mensagem:e.mensagem,eErro:!0,codigoELicencie:R[e.cod],erroELicencie:e.mensagem,detalhesOriginal:e.detalhes}):p({cod:200,valor:e.valor,mensagem:void 0,eErro:!1,codigoELicencie:200,erroELicencie:void 0,detalhesOriginal:e.detalhes}):e.eErro?p({cod:m[e.codigo],valor:void 0,mensagem:e.erro,eErro:!0,codigoELicencie:e.codigo,erroELicencie:e.erro,detalhesOriginal:e.detalhes}):p({cod:200,valor:e.valor,mensagem:void 0,eErro:!1,codigoELicencie:e.codigo,erroELicencie:void 0,detalhesOriginal:e.detalhes});export{u as IniciarRespostas,x as codigosErros,l as codigosResposta,C as converterRespostaELicencieParaPResposta,L as gerarRespostas,y as respostaComuns};
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
/**
|
|
||||||
* Códigos padrão usados pelo contrato de respostas.
|
|
||||||
*
|
|
||||||
* Observação: este enum é parte da API pública do pacote.
|
|
||||||
*/
|
|
||||||
export var codigosResposta;
|
|
||||||
(function (codigosResposta) {
|
|
||||||
codigosResposta[codigosResposta["sucesso"] = 200] = "sucesso";
|
|
||||||
codigosResposta[codigosResposta["erroConhecido"] = 400] = "erroConhecido";
|
|
||||||
codigosResposta[codigosResposta["erroPermissao"] = 401] = "erroPermissao";
|
|
||||||
codigosResposta[codigosResposta["erroNaoEncontrado"] = 404] = "erroNaoEncontrado";
|
|
||||||
codigosResposta[codigosResposta["erroDesconhecido"] = 500] = "erroDesconhecido";
|
|
||||||
codigosResposta[codigosResposta["tempoEsgotado"] = 504] = "tempoEsgotado";
|
|
||||||
})(codigosResposta || (codigosResposta = {}));
|
|
||||||
// ─── Helper interno ─────────────────────────────────────────────────
|
|
||||||
/**
|
|
||||||
* Aplica o callback de interceptação quando fornecido.
|
|
||||||
* Retorno com cast seguro: o callback preserva a forma da resposta,
|
|
||||||
* mas o TypeScript não consegue estreitar o genérico <X> ao subtipo
|
|
||||||
* concreto (ex.: tipoRespostaSucesso<T>), então o cast é inevitável
|
|
||||||
* e está isolado neste único ponto.
|
|
||||||
*/
|
|
||||||
function aplicarCallback(resposta, callback) {
|
|
||||||
if (!callback)
|
|
||||||
return resposta;
|
|
||||||
return callback(resposta);
|
|
||||||
}
|
|
||||||
export const IniciarRespostas = (
|
|
||||||
/** Callback opcional de interceptação — invocado após a construção de cada resposta */
|
|
||||||
callback) => {
|
|
||||||
const valor = (valor, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
eCerto: true,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const valorTrue = (detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
valor: true,
|
|
||||||
mensagem: undefined,
|
|
||||||
eErro: false,
|
|
||||||
eCerto: true,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erro = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroConhecido,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem,
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroPermissao = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroPermissao,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem || "Sem permissão para esse recurso.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const naoEncontrado = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroNaoEncontrado,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem ||
|
|
||||||
"Registro não encontrado ou a execução dessa ação depende de um registro existente.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroInterno = (op) => {
|
|
||||||
const mensagemFim = `${op.mensagem || "Erro interno"}`;
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.erroDesconhecido,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagemFim,
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const tempoEsgotado = (mensagem, detalhes) => {
|
|
||||||
const resposta = {
|
|
||||||
cod: codigosResposta.tempoEsgotado,
|
|
||||||
valor: undefined,
|
|
||||||
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
|
|
||||||
eErro: true,
|
|
||||||
eCerto: false,
|
|
||||||
detalhes,
|
|
||||||
};
|
|
||||||
return aplicarCallback(resposta, callback);
|
|
||||||
};
|
|
||||||
const erroEspera = tempoEsgotado;
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de sucesso
|
|
||||||
*/
|
|
||||||
valor,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de sucesso com valor true
|
|
||||||
*/
|
|
||||||
valorTrue,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro conhecido
|
|
||||||
*/
|
|
||||||
erro,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
|
|
||||||
*/
|
|
||||||
erroPermissao,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
|
|
||||||
*/
|
|
||||||
erroInterno,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
|
|
||||||
*/
|
|
||||||
naoEncontrado,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
|
||||||
*/
|
|
||||||
tempoEsgotado,
|
|
||||||
/**
|
|
||||||
* Gera uma resposta de erro quando o tempo de resposta é esgotado
|
|
||||||
*/
|
|
||||||
erroEspera,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* @deprecated Use IniciarRespostas em seu lugar
|
|
||||||
*/
|
|
||||||
export const gerarRespostas = IniciarRespostas;
|
|
||||||
/**
|
|
||||||
* Instância default (sem handler de interceptação).
|
|
||||||
*/
|
|
||||||
export const respostaComuns = IniciarRespostas();
|
|
||||||
30
package.json
30
package.json
|
|
@ -1,38 +1,38 @@
|
||||||
{
|
{
|
||||||
"name": "p-respostas",
|
"name": "p-respostas",
|
||||||
"version": "0.70.0",
|
"version": "0.69.0",
|
||||||
"description": "Contrato simples de respostas (sucesso/erro) para APIs e serviços.",
|
"description": "Contrato simples de respostas (sucesso/erro) para APIs e serviços.",
|
||||||
"main": "./dist-back/index.js",
|
"main": "./dist-back/index.js",
|
||||||
"module": "./dist-front/index.js",
|
"module": "./dist-front/index.mjs",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"types": "./src/index.ts",
|
"types": "./dist-front/index.d.mts",
|
||||||
"import": "./dist-front/index.js",
|
"import": "./dist-front/index.mjs",
|
||||||
"require": "./dist-back/index.js"
|
"require": "./dist-back/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"types": "./src/index.ts",
|
"types": "./dist-front/index.d.mts",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"biome": "biome check --write ./src",
|
"biome": "npx @biomejs/biome check --write ./src",
|
||||||
"build": "npm --no-git-tag-version version minor && bun run biome && bun x tsc -p tsconfig-back.json && bun x tsc -p tsconfig-front.json",
|
"build": "npm --no-git-tag-version version minor && pnpm run biome && tsup --config ./node_modules/p-comuns/tsup/tsup.config.ts && pnpm run pacote",
|
||||||
"check": "bun run biome && bun x tsc --noEmit",
|
"nodev": "check-node-version --node '= 22'",
|
||||||
"test": "bun test tests/",
|
"pacote": "npm pack && npm pack && mv $(npm pack --silent) pacote.tgz"
|
||||||
"teste": "bun test tests/"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git#bun",
|
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git",
|
||||||
"zod": "4.4.3"
|
"zod": "4.4.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2",
|
"@biomejs/biome": "2.4.12",
|
||||||
"@types/bun": "^1.4.2",
|
|
||||||
"@types/node": "^22.19.15",
|
"@types/node": "^22.19.15",
|
||||||
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git#bun",
|
"check-node-version": "^4.2.1",
|
||||||
"typescript": "^7",
|
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git",
|
||||||
|
"tsup": "^8.5.1",
|
||||||
|
"typescript": "^6",
|
||||||
"zod": "4.4.3"
|
"zod": "4.4.3"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
||||||
BIN
pacote.tgz
Normal file
BIN
pacote.tgz
Normal file
Binary file not shown.
1175
pnpm-lock.yaml
generated
Normal file
1175
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,8 @@
|
||||||
import { codigosResposta, type tipoResposta, type tipoRespostaErro } from "./respostas"
|
import {
|
||||||
|
codigosResposta,
|
||||||
|
type tipoResposta,
|
||||||
|
type tipoRespostaErro,
|
||||||
|
} from "./respostas"
|
||||||
|
|
||||||
// ─── Tipagem ELicencie ──────────────────────────────────────────────
|
// ─── Tipagem ELicencie ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -33,7 +37,9 @@ export interface tipoRespostaErroELicencie {
|
||||||
detalhes?: Record<string, any>
|
detalhes?: Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type tipoRespostaELicencie<T> = tipoRespostaSucessoELicencie<T> | tipoRespostaErroELicencie
|
export type tipoRespostaELicencie<T> =
|
||||||
|
| tipoRespostaSucessoELicencie<T>
|
||||||
|
| tipoRespostaErroELicencie
|
||||||
|
|
||||||
// ─── Tipo de entrada (transição) ────────────────────────────────────
|
// ─── Tipo de entrada (transição) ────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -46,7 +52,10 @@ export type tipoEntradaTransicao<T> = tipoRespostaELicencie<T> | tipoResposta<T>
|
||||||
// ─── Mapeamento bidirecional de códigos ─────────────────────────────
|
// ─── Mapeamento bidirecional de códigos ─────────────────────────────
|
||||||
|
|
||||||
/** ELicencie → P-Resposta (403 → 401) */
|
/** ELicencie → P-Resposta (403 → 401) */
|
||||||
const mapaCodigoELicencieParaPResposta: Record<codigoErroELicencie, tipoRespostaErro["cod"]> = {
|
const mapaCodigoELicencieParaPResposta: Record<
|
||||||
|
codigoErroELicencie,
|
||||||
|
tipoRespostaErro["cod"]
|
||||||
|
> = {
|
||||||
400: codigosResposta.erroConhecido,
|
400: codigosResposta.erroConhecido,
|
||||||
403: codigosResposta.erroPermissao,
|
403: codigosResposta.erroPermissao,
|
||||||
500: codigosResposta.erroDesconhecido,
|
500: codigosResposta.erroDesconhecido,
|
||||||
|
|
@ -54,7 +63,10 @@ const mapaCodigoELicencieParaPResposta: Record<codigoErroELicencie, tipoResposta
|
||||||
}
|
}
|
||||||
|
|
||||||
/** P-Resposta → ELicencie (401 → 403, 404 → 400) */
|
/** P-Resposta → ELicencie (401 → 403, 404 → 400) */
|
||||||
const mapaCodigoPRespostaParaELicencie: Record<tipoRespostaErro["cod"], codigoErroELicencie> = {
|
const mapaCodigoPRespostaParaELicencie: Record<
|
||||||
|
tipoRespostaErro["cod"],
|
||||||
|
codigoErroELicencie
|
||||||
|
> = {
|
||||||
[codigosResposta.erroConhecido]: 400,
|
[codigosResposta.erroConhecido]: 400,
|
||||||
[codigosResposta.erroPermissao]: 403,
|
[codigosResposta.erroPermissao]: 403,
|
||||||
[codigosResposta.erroDesconhecido]: 500,
|
[codigosResposta.erroDesconhecido]: 500,
|
||||||
|
|
@ -65,14 +77,18 @@ const mapaCodigoPRespostaParaELicencie: Record<tipoRespostaErro["cod"], codigoEr
|
||||||
// ─── Type guard ─────────────────────────────────────────────────────
|
// ─── Type guard ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
/** Detecta se a entrada já está no formato P-Resposta (possui campo `cod`). */
|
/** Detecta se a entrada já está no formato P-Resposta (possui campo `cod`). */
|
||||||
function eRespostaPadrao<T>(entrada: tipoEntradaTransicao<T>): entrada is tipoResposta<T> {
|
function eRespostaPadrao<T>(
|
||||||
|
entrada: tipoEntradaTransicao<T>,
|
||||||
|
): entrada is tipoResposta<T> {
|
||||||
return "cod" in entrada
|
return "cod" in entrada
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Conversores de detalhes ────────────────────────────────────────
|
// ─── Conversores de detalhes ────────────────────────────────────────
|
||||||
|
|
||||||
/** `Record<string, any>` → `string[]` (passthrough se já for array). */
|
/** `Record<string, any>` → `string[]` (passthrough se já for array). */
|
||||||
function detalhesParaArray(detalhes?: Record<string, any> | string[]): string[] | undefined {
|
function detalhesParaArray(
|
||||||
|
detalhes?: Record<string, any> | string[],
|
||||||
|
): string[] | undefined {
|
||||||
if (!detalhes) return undefined
|
if (!detalhes) return undefined
|
||||||
if (Array.isArray(detalhes)) return detalhes
|
if (Array.isArray(detalhes)) return detalhes
|
||||||
|
|
||||||
|
|
@ -104,7 +120,9 @@ function montarRespostaDual<T>(op: {
|
||||||
}): tipoResposta<T> {
|
}): tipoResposta<T> {
|
||||||
const detalhesArray = detalhesParaArray(op.detalhesOriginal)
|
const detalhesArray = detalhesParaArray(op.detalhesOriginal)
|
||||||
const detalhesRecord =
|
const detalhesRecord =
|
||||||
op.detalhesOriginal && !Array.isArray(op.detalhesOriginal) ? op.detalhesOriginal : undefined
|
op.detalhesOriginal && !Array.isArray(op.detalhesOriginal)
|
||||||
|
? op.detalhesOriginal
|
||||||
|
: undefined
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// P-Resposta
|
// P-Resposta
|
||||||
|
|
|
||||||
102
src/respostas.ts
102
src/respostas.ts
|
|
@ -1,5 +1,3 @@
|
||||||
import z from "zod"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Códigos padrão usados pelo contrato de respostas.
|
* Códigos padrão usados pelo contrato de respostas.
|
||||||
*
|
*
|
||||||
|
|
@ -52,7 +50,9 @@ export type tipoPrErroInterno = {
|
||||||
* Quando fornecido, é invocado após a construção de toda resposta,
|
* Quando fornecido, é invocado após a construção de toda resposta,
|
||||||
* permitindo side-effects (ex.: logging, telemetria) sem alterar o tipo.
|
* permitindo side-effects (ex.: logging, telemetria) sem alterar o tipo.
|
||||||
*/
|
*/
|
||||||
export type tipoCallbackResposta = <X>(resposta: tipoResposta<X>) => tipoResposta<X>
|
export type tipoCallbackResposta = <X>(
|
||||||
|
resposta: tipoResposta<X>,
|
||||||
|
) => tipoResposta<X>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cria um conjunto de geradores de respostas.
|
* Cria um conjunto de geradores de respostas.
|
||||||
|
|
@ -63,11 +63,23 @@ export interface InterfaceRespostas {
|
||||||
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>
|
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>
|
||||||
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>
|
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>
|
||||||
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro
|
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro
|
||||||
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro
|
erroPermissao: (
|
||||||
|
mensagem?: string | undefined | null,
|
||||||
|
detalhes?: string[],
|
||||||
|
) => tipoRespostaErro
|
||||||
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro
|
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro
|
||||||
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro
|
naoEncontrado: (
|
||||||
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro
|
mensagem?: string | undefined | null,
|
||||||
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro
|
detalhes?: string[],
|
||||||
|
) => tipoRespostaErro
|
||||||
|
tempoEsgotado: (
|
||||||
|
mensagem?: string | undefined | null,
|
||||||
|
detalhes?: string[],
|
||||||
|
) => tipoRespostaErro
|
||||||
|
erroEspera: (
|
||||||
|
mensagem?: string | undefined | null,
|
||||||
|
detalhes?: string[],
|
||||||
|
) => tipoRespostaErro
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Helper interno ─────────────────────────────────────────────────
|
// ─── Helper interno ─────────────────────────────────────────────────
|
||||||
|
|
@ -178,7 +190,8 @@ export const IniciarRespostas = (
|
||||||
const resposta: tipoRespostaErro = {
|
const resposta: tipoRespostaErro = {
|
||||||
cod: codigosResposta.tempoEsgotado,
|
cod: codigosResposta.tempoEsgotado,
|
||||||
valor: undefined,
|
valor: undefined,
|
||||||
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
|
mensagem:
|
||||||
|
mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
|
||||||
eErro: true,
|
eErro: true,
|
||||||
eCerto: false,
|
eCerto: false,
|
||||||
detalhes,
|
detalhes,
|
||||||
|
|
@ -234,76 +247,3 @@ export const gerarRespostas = IniciarRespostas
|
||||||
* Instância default (sem handler de interceptação).
|
* Instância default (sem handler de interceptação).
|
||||||
*/
|
*/
|
||||||
export const respostaComuns = IniciarRespostas()
|
export const respostaComuns = IniciarRespostas()
|
||||||
|
|
||||||
// ─── Schemas Zod ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validador para os códigos HTTP de erro aceitos pelo contrato p-respostas.
|
|
||||||
*/
|
|
||||||
export const zCodigosRespostaErro = z.union([
|
|
||||||
z.literal(codigosResposta.erroConhecido),
|
|
||||||
z.literal(codigosResposta.erroPermissao),
|
|
||||||
z.literal(codigosResposta.erroNaoEncontrado),
|
|
||||||
z.literal(codigosResposta.erroDesconhecido),
|
|
||||||
z.literal(codigosResposta.tempoEsgotado),
|
|
||||||
])
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema Zod para respostas de sucesso do contrato p-respostas.
|
|
||||||
*/
|
|
||||||
export const zRespostaSucesso = <T extends z.ZodTypeAny = z.ZodTypeAny>(zValor?: T) =>
|
|
||||||
z.object({
|
|
||||||
cod: z.literal(codigosResposta.sucesso),
|
|
||||||
eCerto: z.literal(true),
|
|
||||||
eErro: z.literal(false),
|
|
||||||
valor: zValor ?? (z.any() as unknown as T),
|
|
||||||
detalhes: z.array(z.string()).nullish(),
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema Zod para respostas de erro do contrato p-respostas.
|
|
||||||
*/
|
|
||||||
export const zRespostaErro = z.object({
|
|
||||||
cod: zCodigosRespostaErro,
|
|
||||||
eCerto: z.literal(false),
|
|
||||||
eErro: z.literal(true),
|
|
||||||
mensagem: z.string(),
|
|
||||||
detalhes: z.array(z.string()).nullish(),
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema Zod completo para o contrato p-respostas (sucesso ou erro).
|
|
||||||
*
|
|
||||||
* @param zValor Schema Zod para validar o campo `valor` em caso de sucesso.
|
|
||||||
* Se omitido, aceita qualquer valor (`z.any()`).
|
|
||||||
*/
|
|
||||||
export const zRespostas = <T extends z.ZodTypeAny = z.ZodTypeAny>(zValor?: T) =>
|
|
||||||
z
|
|
||||||
.object({
|
|
||||||
cod: z.literal(codigosResposta.sucesso),
|
|
||||||
eCerto: z.literal(true),
|
|
||||||
eErro: z.literal(false),
|
|
||||||
valor: zValor ?? (z.any() as unknown as T),
|
|
||||||
detalhes: z.array(z.string()).nullish(),
|
|
||||||
})
|
|
||||||
.or(
|
|
||||||
z.object({
|
|
||||||
cod: zCodigosRespostaErro,
|
|
||||||
eCerto: z.literal(false),
|
|
||||||
eErro: z.literal(true),
|
|
||||||
mensagem: z.string(),
|
|
||||||
detalhes: z.array(z.string()).nullish(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alias singular para `zRespostas`.
|
|
||||||
*/
|
|
||||||
export const zResposta = zRespostas
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tipo inferido a partir de `zRespostas`.
|
|
||||||
*/
|
|
||||||
export type tipoZResposta<T extends z.ZodTypeAny = z.ZodTypeAny> = z.infer<
|
|
||||||
ReturnType<typeof zRespostas<T>>
|
|
||||||
>
|
|
||||||
|
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
import { describe, expect, it } from "bun:test"
|
|
||||||
import z from "zod"
|
|
||||||
import {
|
|
||||||
codigosResposta,
|
|
||||||
respostaComuns,
|
|
||||||
zCodigosRespostaErro,
|
|
||||||
zResposta,
|
|
||||||
zRespostaErro,
|
|
||||||
zRespostaSucesso,
|
|
||||||
zRespostas,
|
|
||||||
type tipoZResposta,
|
|
||||||
} from "../src/respostas"
|
|
||||||
|
|
||||||
describe("zRespostas - Sucesso", () => {
|
|
||||||
it("deve validar resposta de sucesso com schema específico (string)", () => {
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
const res = respostaComuns.valor("Operação realizada com sucesso")
|
|
||||||
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.sucesso)
|
|
||||||
expect(parsed.eCerto).toBe(true)
|
|
||||||
expect(parsed.eErro).toBe(false)
|
|
||||||
if (parsed.eCerto) {
|
|
||||||
expect(parsed.valor).toBe("Operação realizada com sucesso")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve validar resposta de sucesso com schema de objeto complexo", () => {
|
|
||||||
const zUsuario = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
nome: z.string(),
|
|
||||||
ativo: z.boolean(),
|
|
||||||
})
|
|
||||||
const schema = zRespostas(zUsuario)
|
|
||||||
const res = respostaComuns.valor({ id: 10, nome: "Maria", ativo: true }, [
|
|
||||||
"detalhe 1",
|
|
||||||
])
|
|
||||||
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
expect(parsed.eCerto).toBe(true)
|
|
||||||
if (parsed.eCerto) {
|
|
||||||
expect(parsed.valor.id).toBe(10)
|
|
||||||
expect(parsed.valor.nome).toBe("Maria")
|
|
||||||
expect(parsed.valor.ativo).toBe(true)
|
|
||||||
expect(parsed.detalhes).toEqual(["detalhe 1"])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve aceitar qualquer valor quando invocado sem parâmetros (default z.any())", () => {
|
|
||||||
const schema = zRespostas()
|
|
||||||
const resString = respostaComuns.valor("qualquer texto")
|
|
||||||
const resNumero = respostaComuns.valor(12345)
|
|
||||||
const resBool = respostaComuns.valorTrue()
|
|
||||||
|
|
||||||
expect(schema.parse(resString).eCerto).toBe(true)
|
|
||||||
expect(schema.parse(resNumero).eCerto).toBe(true)
|
|
||||||
expect(schema.parse(resBool).eCerto).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve funcionar com zRespostaSucesso isoladamente", () => {
|
|
||||||
const schema = zRespostaSucesso(z.number())
|
|
||||||
const res = respostaComuns.valor(99)
|
|
||||||
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
expect(parsed.cod).toBe(200)
|
|
||||||
expect(parsed.valor).toBe(99)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve rejeitar sucesso quando o tipo de valor for incompatível", () => {
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
const resInvalido = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
eCerto: true,
|
|
||||||
eErro: false,
|
|
||||||
valor: 12345, // número em vez de string
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(() => schema.parse(resInvalido)).toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve aceitar detalhes nullish (null, undefined ou ausente)", () => {
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
|
|
||||||
const resComNull = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
eCerto: true,
|
|
||||||
eErro: false,
|
|
||||||
valor: "ok",
|
|
||||||
detalhes: null,
|
|
||||||
}
|
|
||||||
const resSemDetalhes = {
|
|
||||||
cod: codigosResposta.sucesso,
|
|
||||||
eCerto: true,
|
|
||||||
eErro: false,
|
|
||||||
valor: "ok",
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(schema.parse(resComNull).detalhes).toBeNull()
|
|
||||||
expect(schema.parse(resSemDetalhes).detalhes).toBeUndefined()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("zRespostas - Erro", () => {
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
|
|
||||||
it("deve validar erroConhecido (400)", () => {
|
|
||||||
const res = respostaComuns.erro("Dados inválidos", ["campo X obrigatório"])
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.erroConhecido)
|
|
||||||
expect(parsed.eCerto).toBe(false)
|
|
||||||
expect(parsed.eErro).toBe(true)
|
|
||||||
if (parsed.eErro) {
|
|
||||||
expect(parsed.mensagem).toBe("Dados inválidos")
|
|
||||||
expect(parsed.detalhes).toEqual(["campo X obrigatório"])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve validar erroPermissao (401)", () => {
|
|
||||||
const res = respostaComuns.erroPermissao("Acesso negado")
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.erroPermissao)
|
|
||||||
expect(parsed.eErro).toBe(true)
|
|
||||||
if (parsed.eErro) {
|
|
||||||
expect(parsed.mensagem).toBe("Acesso negado")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve validar erroNaoEncontrado (404)", () => {
|
|
||||||
const res = respostaComuns.naoEncontrado("Usuário não encontrado")
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.erroNaoEncontrado)
|
|
||||||
expect(parsed.eErro).toBe(true)
|
|
||||||
if (parsed.eErro) {
|
|
||||||
expect(parsed.mensagem).toBe("Usuário não encontrado")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve validar erroDesconhecido (500)", () => {
|
|
||||||
const res = respostaComuns.erroInterno({
|
|
||||||
erro: new Error("Falha no banco"),
|
|
||||||
local: "usuario.service",
|
|
||||||
mensagem: "Erro inesperado",
|
|
||||||
})
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.erroDesconhecido)
|
|
||||||
expect(parsed.eErro).toBe(true)
|
|
||||||
if (parsed.eErro) {
|
|
||||||
expect(parsed.mensagem).toBe("Erro inesperado")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve validar tempoEsgotado (504)", () => {
|
|
||||||
const res = respostaComuns.tempoEsgotado("Gateway Timeout")
|
|
||||||
const parsed = schema.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(codigosResposta.tempoEsgotado)
|
|
||||||
expect(parsed.eErro).toBe(true)
|
|
||||||
if (parsed.eErro) {
|
|
||||||
expect(parsed.mensagem).toBe("Gateway Timeout")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve funcionar com zRespostaErro isoladamente", () => {
|
|
||||||
const res = respostaComuns.erro("Falha simples")
|
|
||||||
const parsed = zRespostaErro.parse(res)
|
|
||||||
|
|
||||||
expect(parsed.cod).toBe(400)
|
|
||||||
expect(parsed.mensagem).toBe("Falha simples")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve rejeitar códigos de erro não pertencentes a codigosResposta", () => {
|
|
||||||
const resInvalido = {
|
|
||||||
cod: 403, // 403 não é código do enum codigosResposta (p-respostas usa 401)
|
|
||||||
eCerto: false,
|
|
||||||
eErro: true,
|
|
||||||
mensagem: "Proibido",
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(() => schema.parse(resInvalido)).toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve rejeitar erro sem mensagem", () => {
|
|
||||||
const resSemMsg = {
|
|
||||||
cod: codigosResposta.erroConhecido,
|
|
||||||
eCerto: false,
|
|
||||||
eErro: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(() => schema.parse(resSemMsg)).toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("zRespostas - Consistência e Aliases", () => {
|
|
||||||
it("zResposta deve ser idêntico a zRespostas", () => {
|
|
||||||
expect(zResposta).toBe(zRespostas)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("zCodigosRespostaErro deve aceitar apenas os 5 códigos de erro", () => {
|
|
||||||
expect(zCodigosRespostaErro.parse(400)).toBe(400)
|
|
||||||
expect(zCodigosRespostaErro.parse(401)).toBe(401)
|
|
||||||
expect(zCodigosRespostaErro.parse(404)).toBe(404)
|
|
||||||
expect(zCodigosRespostaErro.parse(500)).toBe(500)
|
|
||||||
expect(zCodigosRespostaErro.parse(504)).toBe(504)
|
|
||||||
|
|
||||||
expect(() => zCodigosRespostaErro.parse(200)).toThrow()
|
|
||||||
expect(() => zCodigosRespostaErro.parse(403)).toThrow()
|
|
||||||
expect(() => zCodigosRespostaErro.parse(502)).toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deve permitir narrowing estático em TypeScript", () => {
|
|
||||||
const schema = zRespostas(z.string())
|
|
||||||
const res: tipoZResposta<z.ZodString> = schema.parse(
|
|
||||||
respostaComuns.valor("dados"),
|
|
||||||
)
|
|
||||||
|
|
||||||
if (res.eCerto) {
|
|
||||||
const v: string = res.valor
|
|
||||||
expect(v).toBe("dados")
|
|
||||||
} else {
|
|
||||||
const m: string = res.mensagem
|
|
||||||
expect(m).toBeDefined()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.cod === codigosResposta.sucesso) {
|
|
||||||
const v: string = res.valor
|
|
||||||
expect(v).toBe("dados")
|
|
||||||
} else {
|
|
||||||
const m: string = res.mensagem
|
|
||||||
expect(m).toBeDefined()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": "./tsconfig",
|
"extends": "./tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist-back",
|
"outDir": "./dist-require",
|
||||||
"module": "commonjs"
|
"module": "commonjs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
{
|
{
|
||||||
"extends": "./tsconfig",
|
"extends": "./tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist-front",
|
"outDir": "./dist-import",
|
||||||
"module": "ESNext",
|
"module": "ES6"
|
||||||
"moduleResolution": "bundler"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
"rootDir": "./src", /* Define a pasta raiz para os arquivos de origem. */
|
"rootDir": "./src", /* Define a pasta raiz para os arquivos de origem. */
|
||||||
|
|
||||||
/* Emissão */
|
/* Emissão */
|
||||||
"declaration": false, /* Não gera arquivos .d.ts. */
|
"declaration": true, /* Gera arquivos .d.ts para os arquivos TypeScript. */
|
||||||
|
|
||||||
/* Interoperabilidade de Módulos */
|
/* Interoperabilidade de Módulos */
|
||||||
"esModuleInterop": true, /* Habilita a compatibilidade com módulos CommonJS ao importar. */
|
"esModuleInterop": true, /* Habilita a compatibilidade com módulos CommonJS ao importar. */
|
||||||
|
|
@ -21,8 +21,7 @@
|
||||||
|
|
||||||
/* Verificação de Tipos */
|
/* Verificação de Tipos */
|
||||||
"strict": true, /* Habilita todas as opções de verificação estrita de tipos. */
|
"strict": true, /* Habilita todas as opções de verificação estrita de tipos. */
|
||||||
"skipLibCheck": true, /* Ignora a verificação de tipos em arquivos de declaração de bibliotecas. */
|
"skipLibCheck": true /* Ignora a verificação de tipos em arquivos de declaração de bibliotecas. */
|
||||||
"types": ["node", "bun"]
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"] /* Inclui todos os arquivos TypeScript dentro da pasta src. */
|
"include": ["src/**/*"] /* Inclui todos os arquivos TypeScript dentro da pasta src. */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue