diff --git a/dist-back/converter-resposta-e-licencie-para-p-resposta.js b/dist-back/converter-resposta-e-licencie-para-p-resposta.js new file mode 100644 index 0000000..f6f462d --- /dev/null +++ b/dist-back/converter-resposta-e-licencie-para-p-resposta.js @@ -0,0 +1,123 @@ +"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 +}); diff --git a/dist-back/index.js b/dist-back/index.js index 9a3bc08..5042b75 100644 --- a/dist-back/index.js +++ b/dist-back/index.js @@ -15,8 +15,10 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau 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") }); diff --git a/dist-front/index.d.mts b/dist-front/index.d.mts index decb983..b21d47f 100644 --- a/dist-front/index.d.mts +++ b/dist-front/index.d.mts @@ -68,4 +68,69 @@ declare const gerarRespostas: (callback?: tipoCallbackResposta) => InterfaceResp */ declare const respostaComuns: InterfaceRespostas; -export { IniciarRespostas, type InterfaceRespostas, codigosResposta, gerarRespostas, respostaComuns, type tipoCallbackResposta, type tipoPrErroInterno, type tipoResposta, type tipoRespostaErro, type tipoRespostaSucesso }; +/** + * 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 { + codigo: 200; + eErro: false; + valor: T; + erro: undefined; + detalhes?: Record; +} +interface tipoRespostaErroELicencie { + codigo: codigoErroELicencie; + eErro: true; + erro: string; + valor: undefined; + detalhes?: Record; +} +type tipoRespostaELicencie = tipoRespostaSucessoELicencie | 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 = tipoRespostaELicencie | tipoResposta; +/** + * 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` + * + * **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: (entrada: tipoEntradaTransicao) => tipoResposta; + +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 }; diff --git a/dist-front/index.mjs b/dist-front/index.mjs index d21de4d..985850d 100644 --- a/dist-front/index.mjs +++ b/dist-front/index.mjs @@ -1 +1 @@ -var m=(e=>(e[e.sucesso=200]="sucesso",e[e.erroConhecido=400]="erroConhecido",e[e.erroPermissao=401]="erroPermissao",e[e.erroNaoEncontrado=404]="erroNaoEncontrado",e[e.erroDesconhecido=500]="erroDesconhecido",e[e.tempoEsgotado=504]="tempoEsgotado",e))(m||{});function t(s,a){return a?a(s):s}var i=s=>{let a=(o,r)=>t({cod:200,valor:o,mensagem:void 0,eErro:!1,eCerto:!0,detalhes:r},s),d=o=>t({cod:200,valor:!0,mensagem:void 0,eErro:!1,eCerto:!0,detalhes:o},s),u=(o,r)=>t({cod:400,valor:void 0,mensagem:o,eErro:!0,eCerto:!1,detalhes:r},s),c=(o,r)=>t({cod:401,valor:void 0,mensagem:o||"Sem permiss\xE3o para esse recurso.",eErro:!0,eCerto:!1,detalhes:r},s),g=(o,r)=>t({cod:404,valor:void 0,mensagem:o||"Registro n\xE3o encontrado ou a execu\xE7\xE3o dessa a\xE7\xE3o depende de um registro existente.",eErro:!0,eCerto:!1,detalhes:r},s),e=o=>{let n={cod:500,valor:void 0,mensagem:`${o.mensagem||"Erro interno"}`,eErro:!0,eCerto:!1};return t(n,s)},p=(o,r)=>t({cod:504,valor:void 0,mensagem:o||"Tempo de resposta esgotado ao tentar acessar o recurso.",eErro:!0,eCerto:!1,detalhes:r},s);return{valor:a,valorTrue:d,erro:u,erroPermissao:c,erroInterno:e,naoEncontrado:g,tempoEsgotado:p,erroEspera:p}},l=i,R=i();export{i as IniciarRespostas,m as codigosResposta,l as gerarRespostas,R as respostaComuns}; +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}; diff --git a/package.json b/package.json index 7912523..adf2c5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "p-respostas", - "version": "0.67.0", + "version": "0.68.0", "description": "Contrato simples de respostas (sucesso/erro) para APIs e serviços.", "main": "./dist-back/index.js", "module": "./dist-front/index.mjs", diff --git a/pacote.tgz b/pacote.tgz index e8790ec..3251de6 100644 Binary files a/pacote.tgz and b/pacote.tgz differ diff --git a/src/converter-resposta-e-licencie-para-p-resposta.ts b/src/converter-resposta-e-licencie-para-p-resposta.ts new file mode 100644 index 0000000..7fffd02 --- /dev/null +++ b/src/converter-resposta-e-licencie-para-p-resposta.ts @@ -0,0 +1,225 @@ +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 { + codigo: 200 + eErro: false + valor: T + erro: undefined + detalhes?: Record +} + +export interface tipoRespostaErroELicencie { + codigo: codigoErroELicencie + eErro: true + erro: string + valor: undefined + detalhes?: Record +} + +export type tipoRespostaELicencie = + | tipoRespostaSucessoELicencie + | 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 = tipoRespostaELicencie | tipoResposta + +// ─── 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( + entrada: tipoEntradaTransicao, +): entrada is tipoResposta { + return "cod" in entrada +} + +// ─── Conversores de detalhes ──────────────────────────────────────── + +/** `Record` → `string[]` (passthrough se já for array). */ +function detalhesParaArray( + detalhes?: Record | 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`, mas em runtime também contém + * `codigo`, `erro` e `detalhes` (Record) do formato ELicencie. + */ +function montarRespostaDual(op: { + cod: tipoResposta["cod"] + valor: T | undefined + mensagem: string | undefined + eErro: boolean + codigoELicencie: 200 | codigoErroELicencie + erroELicencie: string | undefined + detalhesOriginal?: Record | string[] +}): tipoResposta { + 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 +} + +// ─── 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` + * + * **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: tipoEntradaTransicao, +): tipoResposta => { + // ── 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, + }) +} diff --git a/src/index.ts b/src/index.ts index 9f14c03..06a9396 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ // Re-export da API pública do pacote. + +export * from "./converter-resposta-e-licencie-para-p-resposta" export * from "./respostas"