Compare commits

..

No commits in common. "master" and "producao" have entirely different histories.

25 changed files with 602 additions and 1921 deletions

1
.agent

@ -1 +0,0 @@
Subproject commit 5503367656ec04508537df58064fdc1293fce956

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule ".agent"]
path = .agent
url = https://git2.idz.one/publico/.agent.git

View file

@ -1 +0,0 @@
*.tgz

86
AI.md
View file

@ -1,86 +0,0 @@
# AI / LLM usage notes (p-respostas)
Este pacote fornece um **contrato estável** de respostas para operações (principalmente APIs), representando:
- sucesso (`cod: 200`, `eCerto: true`, `eErro: false`, `mensagem: undefined`, `valor: T`)
- erro conhecido/permissão/não encontrado/timeout/erro interno (`cod` diferente de 200, `eErro: true`, `eCerto: false`, `valor: undefined`, `mensagem: string`)
## Imports
### TypeScript / ESM
```ts
import {
codigosResposta,
gerarRespostas,
respostaComuns,
type tipoResposta,
type tipoRespostaErro,
type tipoRespostaSucesso,
type tipoPrErroInterno,
} from "p-respostas"
```
### CommonJS
```js
const { respostaComuns, gerarRespostas, codigosResposta } = require("p-respostas")
```
## Como interpretar uma `tipoResposta<T>`
Regras úteis para checagem:
- Se `res.eCerto === true` então:
- `res.cod === codigosResposta.sucesso`
- `res.valor` existe (tipo `T`)
- `res.mensagem` é `undefined`
- Se `res.eErro === true` então:
- `res.valor` é sempre `undefined`
- `res.mensagem` é sempre `string`
- `res.cod` é um dos códigos de erro
### Exemplo (narrowing recomendado)
Para o TypeScript, o narrowing mais robusto costuma ser usando `cod`:
```ts
import { codigosResposta, type tipoResposta } from "p-respostas"
function handle<T>(res: tipoResposta<T>) {
if (res.cod !== codigosResposta.sucesso) {
// aqui o TS entende tipoRespostaErro (na maioria dos setups)
return { ok: false as const, status: res.cod, message: res.mensagem }
}
// aqui o TS entende tipoRespostaSucesso<T>
return { ok: true as const, value: res.valor }
}
```
> Nota: em alguns setups, checar somente `res.eErro` pode não eliminar completamente `undefined` em `res.valor`.
> Se isso acontecer, prefira checar `cod` como no exemplo acima.
## Como gerar respostas com log de erro interno
```ts
const respostas = gerarRespostas((op) => {
// op.erro: qualquer coisa lançada
// op.local: string (obrigatória)
// op.mensagem: string opcional
// op.__filename: opcional
console.error("Erro interno", op)
// Pode retornar complementos não-destrutivos
return { detalhes: ["id de rastreio: ..."] }
})
const r = respostas.erroInterno({ erro: new Error("boom"), local: "user.service" })
```
## Garantias / restrições
- Este pacote é amplamente importado por outros projetos.
- Os arquivos em `dist-*` são gerados automaticamente.
- Mudanças aqui devem focar em **melhorar o consumo (exports/tipos/docs)** sem alterar comportamento.

View file

@ -1,74 +1 @@
# p-respostas
Contrato simples e tipado de respostas para APIs e serviços (sucesso/erro), com suporte a:
- **ESM** (`import`) via `dist-front/index.mjs`
- **CommonJS** (`require`) via `dist-back/index.js`
- **TypeScript** com tipos publicados em `dist-front/index.d.mts`
> Importante: os diretórios `dist-*` são gerados automaticamente no build. Este repositório deve manter **compatibilidade** e **não alterar funcionalidades**.
## Instalação
```bash
pnpm add p-respostas
# ou
npm i p-respostas
```
## Uso rápido
```ts
import { respostaComuns, gerarRespostas, codigosResposta, type tipoResposta } from "p-respostas"
const r1 = respostaComuns.valor({ ok: true })
// r1.cod === 200
const r2 = respostaComuns.erro("Falha ao processar")
// r2.eErro === true
// Exemplo com logger/observabilidade
const respostas = gerarRespostas(({ erro, mensagem, local }) => {
console.error("erroInterno:", { erro, mensagem, local })
// pode sobrescrever parcialmente a resposta final
return { detalhes: ["contate o suporte" as const] }
})
const r3: tipoResposta<string> = respostas.valor("ok")
const r4: tipoResposta<string> = respostas.erroInterno({ erro: new Error("boom"), local: "serviceX" })
```
## API
### `codigosResposta`
Enum com os códigos HTTP usados pelo contrato:
- `sucesso = 200`
- `erroConhecido = 400`
- `erroPermissao = 401`
- `erroNaoEncontrado = 404`
- `erroDesconhecido = 500`
- `tempoEsgotado = 504`
### Tipos
- `tipoRespostaSucesso<T>`
- `tipoRespostaErro`
- `tipoResposta<T> = tipoRespostaSucesso<T> | tipoRespostaErro`
- `tipoPrErroInterno`
### `gerarRespostas(registrarErroInterno)`
Cria um conjunto de funções padronizadas para gerar respostas.
`registrarErroInterno(op)` recebe `{ erro, mensagem?, local, __filename? }` e pode retornar um `Partial<tipoRespostaErro>` para complementar a resposta final.
### `respostaComuns`
Instância default de `gerarRespostas(() => ({}))`.
## Compatibilidade
- Node: `>=20`
- Exporta ESM e CJS via `package.json#exports`
# drivers

View file

@ -1,123 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
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"
};
const mapaCodigoELicencieParaPResposta = {
400: import_respostas.codigosResposta.erroConhecido,
403: import_respostas.codigosResposta.erroPermissao,
500: import_respostas.codigosResposta.erroDesconhecido,
504: import_respostas.codigosResposta.tempoEsgotado
};
const mapaCodigoPRespostaParaELicencie = {
[import_respostas.codigosResposta.erroConhecido]: 400,
[import_respostas.codigosResposta.erroPermissao]: 403,
[import_respostas.codigosResposta.erroDesconhecido]: 500,
[import_respostas.codigosResposta.erroNaoEncontrado]: 400,
[import_respostas.codigosResposta.tempoEsgotado]: 504
};
function eRespostaPadrao(entrada) {
return "cod" in entrada;
}
function detalhesParaArray(detalhes) {
if (!detalhes) return void 0;
if (Array.isArray(detalhes)) return detalhes;
const entries = Object.entries(detalhes);
if (entries.length === 0) return void 0;
return entries.map(([chave, valor]) => {
const valorStr = typeof valor === "string" ? valor : JSON.stringify(valor);
return `${chave}: ${valorStr}`;
});
}
function montarRespostaDual(op) {
const detalhesArray = detalhesParaArray(op.detalhesOriginal);
const detalhesRecord = op.detalhesOriginal && !Array.isArray(op.detalhesOriginal) ? op.detalhesOriginal : void 0;
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 } : {}
};
}
const converterRespostaELicencieParaPResposta = (entrada) => {
if (eRespostaPadrao(entrada)) {
if (!entrada.eErro) {
return montarRespostaDual({
cod: import_respostas.codigosResposta.sucesso,
valor: entrada.valor,
mensagem: void 0,
eErro: false,
codigoELicencie: 200,
erroELicencie: void 0,
detalhesOriginal: entrada.detalhes
});
}
return montarRespostaDual({
cod: entrada.cod,
valor: void 0,
mensagem: entrada.mensagem,
eErro: true,
codigoELicencie: mapaCodigoPRespostaParaELicencie[entrada.cod],
erroELicencie: entrada.mensagem,
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
});
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
codigosErros,
converterRespostaELicencieParaPResposta
});

View file

@ -1,24 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
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")
});

View file

@ -1,162 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
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
});

View file

@ -1,136 +0,0 @@
/**
* 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 };

View file

@ -1 +0,0 @@
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
dist-import/index.d.ts vendored Normal file
View file

@ -0,0 +1 @@
export * from "./respostas";

1
dist-import/index.js Normal file
View file

@ -0,0 +1 @@
export * from "./respostas";

102
dist-import/respostas.d.ts vendored Normal file
View file

@ -0,0 +1,102 @@
export declare enum codigosResposta {
sucesso = 200,
erroConhecido = 400,
erroPermissao = 401,
erroNaoEncontrado = 404,
erroDesconhecido = 500,
tempoEsgotado = 504
}
export type tipoRespostaSucesso<T> = {
cod: codigosResposta.sucesso;
valor: T;
mensagem: undefined;
eErro: false;
eCerto: true;
detalhes?: string[];
};
export type tipoRespostaErro = {
cod: codigosResposta.erroConhecido | codigosResposta.erroDesconhecido | codigosResposta.erroPermissao | codigosResposta.erroNaoEncontrado | codigosResposta.tempoEsgotado;
valor: undefined;
mensagem: string;
eErro: true;
eCerto: false;
detalhes?: string[];
};
export type tipoResposta<T> = tipoRespostaSucesso<T> | tipoRespostaErro;
export type tipoPrErroInterno = {
erro: any;
mensagem?: string;
local: string;
__filename?: string;
};
export declare const gerarRespostas: (registrarErroInterno: (op: tipoPrErroInterno) => Partial<tipoRespostaErro>) => {
/**
* Gera uma resposta de sucesso
*/
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>;
/**
* Gera uma resposta de sucesso com valor true
*/
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>;
/**
* Gera uma resposta de erro conhecido
*/
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
*/
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
*/
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
*/
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
};
/**
* Uso de respostas em comuns
*/
export declare const respostaComuns: {
/**
* Gera uma resposta de sucesso
*/
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>;
/**
* Gera uma resposta de sucesso com valor true
*/
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>;
/**
* Gera uma resposta de erro conhecido
*/
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
*/
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
*/
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
*/
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
};

127
dist-import/respostas.js Normal file
View file

@ -0,0 +1,127 @@
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 = {}));
export const gerarRespostas = (
/** Faz um processamento quando erro interno
* Recebe o erro gerado, mensagem personalizada e detalhes
*/
registrarErroInterno) => {
const valor = (valor, detalhes) => {
return {
cod: codigosResposta.sucesso,
valor,
mensagem: undefined,
eErro: false,
eCerto: true,
detalhes,
};
};
const valorTrue = (detalhes) => {
return {
cod: codigosResposta.sucesso,
valor: true,
mensagem: undefined,
eErro: false,
eCerto: true,
detalhes,
};
};
const erro = (mensagem, detalhes) => {
return {
cod: codigosResposta.erroConhecido,
valor: undefined,
mensagem,
eErro: true,
eCerto: false,
detalhes,
};
};
const erroPermissao = (mensagem, detalhes) => {
return {
cod: codigosResposta.erroPermissao,
valor: undefined,
mensagem: mensagem || "Sem permissão para esse recurso.",
eErro: true,
eCerto: false,
detalhes,
};
};
const naoEncontrado = (mensagem, detalhes) => {
return {
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,
};
};
const erroInterno = (op) => {
const resRegistro = registrarErroInterno(op);
const mensagemFim = `${op.mensagem || "Erro interno"}`;
return {
cod: codigosResposta.erroDesconhecido,
valor: undefined,
mensagem: mensagemFim,
eErro: true,
eCerto: false,
...resRegistro,
};
};
const tempoEsgotado = (mensagem, detalhes) => {
return {
cod: codigosResposta.tempoEsgotado,
valor: undefined,
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
eErro: true,
eCerto: false,
detalhes,
};
};
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,
};
};
/**
* Uso de respostas em comuns
*/
export const respostaComuns = gerarRespostas(() => ({}));

1
dist-require/index.d.ts vendored Normal file
View file

@ -0,0 +1 @@
export * from "./respostas";

17
dist-require/index.js Normal file
View file

@ -0,0 +1,17 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
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 });
__exportStar(require("./respostas"), exports);

102
dist-require/respostas.d.ts vendored Normal file
View file

@ -0,0 +1,102 @@
export declare enum codigosResposta {
sucesso = 200,
erroConhecido = 400,
erroPermissao = 401,
erroNaoEncontrado = 404,
erroDesconhecido = 500,
tempoEsgotado = 504
}
export type tipoRespostaSucesso<T> = {
cod: codigosResposta.sucesso;
valor: T;
mensagem: undefined;
eErro: false;
eCerto: true;
detalhes?: string[];
};
export type tipoRespostaErro = {
cod: codigosResposta.erroConhecido | codigosResposta.erroDesconhecido | codigosResposta.erroPermissao | codigosResposta.erroNaoEncontrado | codigosResposta.tempoEsgotado;
valor: undefined;
mensagem: string;
eErro: true;
eCerto: false;
detalhes?: string[];
};
export type tipoResposta<T> = tipoRespostaSucesso<T> | tipoRespostaErro;
export type tipoPrErroInterno = {
erro: any;
mensagem?: string;
local: string;
__filename?: string;
};
export declare const gerarRespostas: (registrarErroInterno: (op: tipoPrErroInterno) => Partial<tipoRespostaErro>) => {
/**
* Gera uma resposta de sucesso
*/
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>;
/**
* Gera uma resposta de sucesso com valor true
*/
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>;
/**
* Gera uma resposta de erro conhecido
*/
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
*/
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
*/
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
*/
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
};
/**
* Uso de respostas em comuns
*/
export declare const respostaComuns: {
/**
* Gera uma resposta de sucesso
*/
valor: <T>(valor: T, detalhes?: string[]) => tipoRespostaSucesso<T>;
/**
* Gera uma resposta de sucesso com valor true
*/
valorTrue: (detalhes?: string[]) => tipoRespostaSucesso<true>;
/**
* Gera uma resposta de erro conhecido
*/
erro: (mensagem: string, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro de permissão,será necessário fazer o login novamente
*/
erroPermissao: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro desconhecido, geralmente tem origem de um exception
*/
erroInterno: (op: tipoPrErroInterno) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando um registro não é encontrado ou sua execução depende de um registro existente
*/
naoEncontrado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
tempoEsgotado: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
/**
* Gera uma resposta de erro quando o tempo de resposta é esgotado
*/
erroEspera: (mensagem?: string | undefined | null, detalhes?: string[]) => tipoRespostaErro;
};

131
dist-require/respostas.js Normal file
View file

@ -0,0 +1,131 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.respostaComuns = exports.gerarRespostas = exports.codigosResposta = void 0;
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 = {}));
const gerarRespostas = (
/** Faz um processamento quando erro interno
* Recebe o erro gerado, mensagem personalizada e detalhes
*/
registrarErroInterno) => {
const valor = (valor, detalhes) => {
return {
cod: codigosResposta.sucesso,
valor,
mensagem: undefined,
eErro: false,
eCerto: true,
detalhes,
};
};
const valorTrue = (detalhes) => {
return {
cod: codigosResposta.sucesso,
valor: true,
mensagem: undefined,
eErro: false,
eCerto: true,
detalhes,
};
};
const erro = (mensagem, detalhes) => {
return {
cod: codigosResposta.erroConhecido,
valor: undefined,
mensagem,
eErro: true,
eCerto: false,
detalhes,
};
};
const erroPermissao = (mensagem, detalhes) => {
return {
cod: codigosResposta.erroPermissao,
valor: undefined,
mensagem: mensagem || "Sem permissão para esse recurso.",
eErro: true,
eCerto: false,
detalhes,
};
};
const naoEncontrado = (mensagem, detalhes) => {
return {
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,
};
};
const erroInterno = (op) => {
const resRegistro = registrarErroInterno(op);
const mensagemFim = `${op.mensagem || "Erro interno"}`;
return {
cod: codigosResposta.erroDesconhecido,
valor: undefined,
mensagem: mensagemFim,
eErro: true,
eCerto: false,
...resRegistro,
};
};
const tempoEsgotado = (mensagem, detalhes) => {
return {
cod: codigosResposta.tempoEsgotado,
valor: undefined,
mensagem: mensagem || "Tempo de resposta esgotado ao tentar acessar o recurso.",
eErro: true,
eCerto: false,
detalhes,
};
};
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.gerarRespostas = gerarRespostas;
/**
* Uso de respostas em comuns
*/
exports.respostaComuns = (0, exports.gerarRespostas)(() => ({}));

View file

@ -1,39 +1,29 @@
{
"name": "p-respostas",
"version": "0.69.0",
"description": "Contrato simples de respostas (sucesso/erro) para APIs e serviços.",
"main": "./dist-back/index.js",
"module": "./dist-front/index.mjs",
"version": "0.32.0",
"description": "",
"main": "src/index.ts",
"exports": {
".": {
"types": "./dist-front/index.d.mts",
"import": "./dist-front/index.mjs",
"require": "./dist-back/index.js"
"import": "./dist-import/index.js",
"require": "./dist-require/index.js"
}
},
"types": "./dist-front/index.d.mts",
"engines": {
"node": ">=20"
},
"sideEffects": false,
"scripts": {
"postinstall": "pnpm up p-*",
"build-back": "rm -fr dist-require && tsc --project ./tsconfig-back.json",
"build-front": "rm -fr dist-import && tsc --project ./tsconfig-front.json",
"build": "npm --no-git-tag-version version minor && pnpm run biome && pnpm run build-back && pnpm run build-front",
"biome": "npx @biomejs/biome check --write ./src",
"build": "npm --no-git-tag-version version minor && pnpm run biome && tsup --config ./node_modules/p-comuns/tsup/tsup.config.ts && pnpm run pacote",
"nodev": "check-node-version --node '= 22'",
"pacote": "npm pack && npm pack && mv $(npm pack --silent) pacote.tgz"
},
"peerDependencies": {
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git",
"zod": "4.4.3"
"nodev": "check-node-version --node '>= 20'",
"at": "pnpm up p-*"
},
"devDependencies": {
"@biomejs/biome": "2.4.12",
"@types/node": "^22.19.15",
"p-comuns": "git+https://leitura:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MTQ3NTA1NzYsImlzcyI6IkdpdG5lc3MiLCJwaWQiOjgsInRrbiI6eyJ0eXAiOiJwYXQiLCJpZCI6MzJ9fQ.OYdExOVQm5UI3wfeTaWjmD0o65Y1hrjFz5EvMB1a__U@git.idz.one/git/multi-modulos-ambientais/_comuns.git#producao",
"@biomejs/biome": "^2.0.6",
"@types/node": "^20.14.1",
"check-node-version": "^4.2.1",
"p-comuns": "git+https://git2.idz.one/publico/_comuns.git",
"tsup": "^8.5.1",
"typescript": "^6",
"zod": "4.4.3"
"typescript": "5.5.4"
},
"keywords": [],
"author": {
@ -41,5 +31,8 @@
"email": "ti@e-licencie.com.br",
"url": "https://e-licencie.com.br"
},
"license": "ISC"
"license": "ISC",
"dependencies": {
"zod": "3.24.1"
}
}

Binary file not shown.

1014
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,225 +0,0 @@
import {
codigosResposta,
type tipoResposta,
type tipoRespostaErro,
} 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",
} as const
/** Códigos HTTP de erro reconhecidos pelo ELicencie. */
export type codigoErroELicencie = keyof typeof codigosErros
export interface tipoRespostaSucessoELicencie<T> {
codigo: 200
eErro: false
valor: T
erro: undefined
detalhes?: Record<string, any>
}
export interface tipoRespostaErroELicencie {
codigo: codigoErroELicencie
eErro: true
erro: string
valor: undefined
detalhes?: Record<string, any>
}
export type tipoRespostaELicencie<T> =
| tipoRespostaSucessoELicencie<T>
| tipoRespostaErroELicencie
// ─── Tipo de entrada (transição) ────────────────────────────────────
/**
* Durante a transição de sistema, a entrada pode chegar em qualquer um
* dos dois formatos. O conversor detecta e normaliza para P-Resposta.
*/
export type tipoEntradaTransicao<T> = tipoRespostaELicencie<T> | tipoResposta<T>
// ─── Mapeamento bidirecional de códigos ─────────────────────────────
/** ELicencie → P-Resposta (403 → 401) */
const mapaCodigoELicencieParaPResposta: Record<
codigoErroELicencie,
tipoRespostaErro["cod"]
> = {
400: codigosResposta.erroConhecido,
403: codigosResposta.erroPermissao,
500: codigosResposta.erroDesconhecido,
504: codigosResposta.tempoEsgotado,
}
/** P-Resposta → ELicencie (401 → 403, 404 → 400) */
const mapaCodigoPRespostaParaELicencie: Record<
tipoRespostaErro["cod"],
codigoErroELicencie
> = {
[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<T>(
entrada: tipoEntradaTransicao<T>,
): entrada is tipoResposta<T> {
return "cod" in entrada
}
// ─── Conversores de detalhes ────────────────────────────────────────
/** `Record<string, any>` → `string[]` (passthrough se já for array). */
function detalhesParaArray(
detalhes?: Record<string, any> | string[],
): string[] | undefined {
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<T>(op: {
cod: tipoResposta<T>["cod"]
valor: T | undefined
mensagem: string | undefined
eErro: boolean
codigoELicencie: 200 | codigoErroELicencie
erroELicencie: string | undefined
detalhesOriginal?: Record<string, any> | string[]
}): tipoResposta<T> {
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 } : {}),
} as tipoResposta<T>
}
// ─── 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 = <T>(
entrada: tipoEntradaTransicao<T>,
): tipoResposta<T> => {
// ── Entrada já é P-Resposta: enriquecer com campos ELicencie ──
if (eRespostaPadrao(entrada)) {
if (!entrada.eErro) {
return montarRespostaDual<T>({
cod: codigosResposta.sucesso,
valor: entrada.valor,
mensagem: undefined,
eErro: false,
codigoELicencie: 200,
erroELicencie: undefined,
detalhesOriginal: entrada.detalhes,
})
}
return montarRespostaDual<T>({
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<T>({
cod: codigosResposta.sucesso,
valor: entrada.valor,
mensagem: undefined,
eErro: false,
codigoELicencie: entrada.codigo,
erroELicencie: undefined,
detalhesOriginal: entrada.detalhes,
})
}
return montarRespostaDual<T>({
cod: mapaCodigoELicencieParaPResposta[entrada.codigo],
valor: undefined,
mensagem: entrada.erro,
eErro: true,
codigoELicencie: entrada.codigo,
erroELicencie: entrada.erro,
detalhesOriginal: entrada.detalhes,
})
}

View file

@ -1,4 +1 @@
// Re-export da API pública do pacote.
export * from "./converter-resposta-e-licencie-para-p-resposta"
export * from "./respostas"

View file

@ -1,8 +1,3 @@
/**
* Códigos padrão usados pelo contrato de respostas.
*
* Observação: este enum é parte da API pública do pacote.
*/
export enum codigosResposta {
sucesso = 200,
erroConhecido = 400,
@ -44,66 +39,14 @@ export type tipoPrErroInterno = {
__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.
export const gerarRespostas = (
/** Faz um processamento quando erro interno
* Recebe o erro gerado, mensagem personalizada e detalhes
*/
export type tipoCallbackResposta = <X>(
resposta: tipoResposta<X>,
) => tipoResposta<X>
/**
* Cria um conjunto de geradores de respostas.
*
* @param registrarErroInterno callback para registrar/normalizar erros internos.
*/
export 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
}
// ─── 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<R extends tipoResposta<unknown>>(
resposta: R,
callback?: tipoCallbackResposta,
): R {
if (!callback) return resposta
return callback(resposta) as R
}
export const IniciarRespostas = (
/** Callback opcional de interceptação — invocado após a construção de cada resposta */
callback?: tipoCallbackResposta,
): InterfaceRespostas => {
registrarErroInterno: (op: tipoPrErroInterno) => Partial<tipoRespostaErro>,
) => {
const valor = <T>(valor: T, detalhes?: string[]): tipoRespostaSucesso<T> => {
const resposta: tipoRespostaSucesso<T> = {
return {
cod: codigosResposta.sucesso,
valor,
mensagem: undefined,
@ -111,11 +54,10 @@ export const IniciarRespostas = (
eCerto: true,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const valorTrue = (detalhes?: string[]): tipoRespostaSucesso<true> => {
const resposta: tipoRespostaSucesso<true> = {
return {
cod: codigosResposta.sucesso,
valor: true,
mensagem: undefined,
@ -123,11 +65,10 @@ export const IniciarRespostas = (
eCerto: true,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const erro = (mensagem: string, detalhes?: string[]): tipoRespostaErro => {
const resposta: tipoRespostaErro = {
return {
cod: codigosResposta.erroConhecido,
valor: undefined,
mensagem,
@ -135,14 +76,13 @@ export const IniciarRespostas = (
eCerto: false,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const erroPermissao = (
mensagem?: string | undefined | null,
detalhes?: string[],
): tipoRespostaErro => {
const resposta: tipoRespostaErro = {
return {
cod: codigosResposta.erroPermissao,
valor: undefined,
mensagem: mensagem || "Sem permissão para esse recurso.",
@ -150,14 +90,13 @@ export const IniciarRespostas = (
eCerto: false,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const naoEncontrado = (
mensagem?: string | undefined | null,
detalhes?: string[],
): tipoRespostaErro => {
const resposta: tipoRespostaErro = {
return {
cod: codigosResposta.erroNaoEncontrado,
valor: undefined,
mensagem:
@ -167,27 +106,28 @@ export const IniciarRespostas = (
eCerto: false,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const erroInterno = (op: tipoPrErroInterno): tipoRespostaErro => {
const resRegistro = registrarErroInterno(op)
const mensagemFim = `${op.mensagem || "Erro interno"}`
const resposta: tipoRespostaErro = {
return {
cod: codigosResposta.erroDesconhecido,
valor: undefined,
mensagem: mensagemFim,
eErro: true,
eCerto: false,
...resRegistro,
}
return aplicarCallback(resposta, callback)
}
const tempoEsgotado = (
mensagem?: string | undefined | null,
detalhes?: string[],
): tipoRespostaErro => {
const resposta: tipoRespostaErro = {
return {
cod: codigosResposta.tempoEsgotado,
valor: undefined,
mensagem:
@ -196,7 +136,6 @@ export const IniciarRespostas = (
eCerto: false,
detalhes,
}
return aplicarCallback(resposta, callback)
}
const erroEspera = tempoEsgotado
@ -239,11 +178,6 @@ export const IniciarRespostas = (
}
/**
* @deprecated Use IniciarRespostas em seu lugar
* Uso de respostas em comuns
*/
export const gerarRespostas = IniciarRespostas
/**
* Instância default (sem handler de interceptação).
*/
export const respostaComuns = IniciarRespostas()
export const respostaComuns = gerarRespostas(() => ({}))

View file

@ -2,14 +2,12 @@
"compilerOptions": {
/* Linguagem e Ambiente */
"target": "ES2020", /* Define a versão do JavaScript para o código emitido. */
"lib": ["ES2022", "DOM", "DOM.Iterable"],/* Especifica as bibliotecas padrão a serem incluídas, como DOM para iteradores. */
// IA manter "ignoreDeprecations": "6.0",
"ignoreDeprecations": "6.0", /* Ignora erros de compatibilidade com depreciações TS 6.x */
"lib": ["dom.iterable"], /* Especifica as bibliotecas padrão a serem incluídas, como DOM para iteradores. */
"experimentalDecorators": true, /* Habilita o suporte experimental a decoradores. */
"emitDecoratorMetadata": true, /* Emite metadados de tipos de design para declarações decoradas. */
/* Módulos */
"moduleResolution": "bundler", /* Define como o TypeScript resolve módulos. */
"moduleResolution": "node", /* Define como o TypeScript resolve módulos. */
"rootDir": "./src", /* Define a pasta raiz para os arquivos de origem. */
/* Emissão */