@eva_solutions/auth-sdk 0.0.0-stage → 3.0.0-dev-20261109133200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +290 -0
- package/LICENSE +21 -0
- package/README.md +481 -2
- package/dist/admin/index.cjs +4 -0
- package/dist/admin/index.d.cts +2 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/admin/index.js +1 -0
- package/dist/admin-DjvuvuI8.js +408 -0
- package/dist/admin-DjvuvuI8.js.map +1 -0
- package/dist/admin-Q6lbWqLM.cjs +419 -0
- package/dist/admin-Q6lbWqLM.cjs.map +1 -0
- package/dist/api-path-2Ulruz7R.cjs +34 -0
- package/dist/api-path-2Ulruz7R.cjs.map +1 -0
- package/dist/api-path-B-vSkL2H.js +29 -0
- package/dist/api-path-B-vSkL2H.js.map +1 -0
- package/dist/auth-19r-Q6X2.js +84 -0
- package/dist/auth-19r-Q6X2.js.map +1 -0
- package/dist/auth-DX1N5JA4.cjs +131 -0
- package/dist/auth-DX1N5JA4.cjs.map +1 -0
- package/dist/auth-handlers-B3iJaPln.js +343 -0
- package/dist/auth-handlers-B3iJaPln.js.map +1 -0
- package/dist/auth-handlers-BTbXKJms.d.ts +15 -0
- package/dist/auth-handlers-BTbXKJms.d.ts.map +1 -0
- package/dist/auth-handlers-CDzGFDTu.cjs +404 -0
- package/dist/auth-handlers-CDzGFDTu.cjs.map +1 -0
- package/dist/auth-handlers-DRUUTEtW.d.cts +15 -0
- package/dist/auth-handlers-DRUUTEtW.d.cts.map +1 -0
- package/dist/catalog-CHPqldcj.cjs +172 -0
- package/dist/catalog-CHPqldcj.cjs.map +1 -0
- package/dist/catalog-CIqpzgsM.d.cts +75 -0
- package/dist/catalog-CIqpzgsM.d.cts.map +1 -0
- package/dist/catalog-CIqpzgsM.d.ts +75 -0
- package/dist/catalog-CIqpzgsM.d.ts.map +1 -0
- package/dist/catalog-DqPhtCKZ.js +95 -0
- package/dist/catalog-DqPhtCKZ.js.map +1 -0
- package/dist/config-3avoUa9e.d.cts +95 -0
- package/dist/config-3avoUa9e.d.cts.map +1 -0
- package/dist/config-COX7rGAP.d.ts +95 -0
- package/dist/config-COX7rGAP.d.ts.map +1 -0
- package/dist/constants-BE1_9Tod.cjs +52 -0
- package/dist/constants-BE1_9Tod.cjs.map +1 -0
- package/dist/constants-BY7QZokc.js +29 -0
- package/dist/constants-BY7QZokc.js.map +1 -0
- package/dist/constants-CcbhOaAP.cjs +153 -0
- package/dist/constants-CcbhOaAP.cjs.map +1 -0
- package/dist/constants-rNuD5qJn.js +94 -0
- package/dist/constants-rNuD5qJn.js.map +1 -0
- package/dist/contracts/index.cjs +1006 -0
- package/dist/contracts/index.cjs.map +1 -0
- package/dist/contracts/index.d.cts +488 -0
- package/dist/contracts/index.d.cts.map +1 -0
- package/dist/contracts/index.d.ts +488 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +817 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/cookies-DCIcr7uy.cjs +94 -0
- package/dist/cookies-DCIcr7uy.cjs.map +1 -0
- package/dist/cookies-DKEC7AWv.js +71 -0
- package/dist/cookies-DKEC7AWv.js.map +1 -0
- package/dist/delegated-token-CVNbMNfy.js +426 -0
- package/dist/delegated-token-CVNbMNfy.js.map +1 -0
- package/dist/delegated-token-DHSK4rHI.cjs +461 -0
- package/dist/delegated-token-DHSK4rHI.cjs.map +1 -0
- package/dist/error-helpers-0woh13Wd.d.cts +105 -0
- package/dist/error-helpers-0woh13Wd.d.cts.map +1 -0
- package/dist/error-helpers-Ct3AUK1I.d.ts +105 -0
- package/dist/error-helpers-Ct3AUK1I.d.ts.map +1 -0
- package/dist/error-helpers-XCh4ZJ-g.cjs +282 -0
- package/dist/error-helpers-XCh4ZJ-g.cjs.map +1 -0
- package/dist/error-helpers-lnwgNOw9.js +145 -0
- package/dist/error-helpers-lnwgNOw9.js.map +1 -0
- package/dist/error-messages-CGpW1fsg.d.cts +48 -0
- package/dist/error-messages-CGpW1fsg.d.cts.map +1 -0
- package/dist/error-messages-CGpW1fsg.d.ts +48 -0
- package/dist/error-messages-CGpW1fsg.d.ts.map +1 -0
- package/dist/event-codes-BBJHon-I.cjs +48 -0
- package/dist/event-codes-BBJHon-I.cjs.map +1 -0
- package/dist/event-codes-BgcJWsov.d.cts +42 -0
- package/dist/event-codes-BgcJWsov.d.cts.map +1 -0
- package/dist/event-codes-BgcJWsov.d.ts +42 -0
- package/dist/event-codes-BgcJWsov.d.ts.map +1 -0
- package/dist/event-codes-DR5_VlaR.js +43 -0
- package/dist/event-codes-DR5_VlaR.js.map +1 -0
- package/dist/generic/index.cjs +91 -0
- package/dist/generic/index.cjs.map +1 -0
- package/dist/generic/index.d.cts +27 -0
- package/dist/generic/index.d.cts.map +1 -0
- package/dist/generic/index.d.ts +27 -0
- package/dist/generic/index.d.ts.map +1 -0
- package/dist/generic/index.js +80 -0
- package/dist/generic/index.js.map +1 -0
- package/dist/hono/index.cjs +309 -0
- package/dist/hono/index.cjs.map +1 -0
- package/dist/hono/index.d.cts +272 -0
- package/dist/hono/index.d.cts.map +1 -0
- package/dist/hono/index.d.ts +272 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +290 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/hono-openapi/index.cjs +326 -0
- package/dist/hono-openapi/index.cjs.map +1 -0
- package/dist/hono-openapi/index.d.cts +14 -0
- package/dist/hono-openapi/index.d.cts.map +1 -0
- package/dist/hono-openapi/index.d.ts +14 -0
- package/dist/hono-openapi/index.d.ts.map +1 -0
- package/dist/hono-openapi/index.js +307 -0
- package/dist/hono-openapi/index.js.map +1 -0
- package/dist/http-client-BVF3iktR.cjs +211 -0
- package/dist/http-client-BVF3iktR.cjs.map +1 -0
- package/dist/http-client-Da0-OMfc.js +206 -0
- package/dist/http-client-Da0-OMfc.js.map +1 -0
- package/dist/index-CIH_2t7Y.d.ts +240 -0
- package/dist/index-CIH_2t7Y.d.ts.map +1 -0
- package/dist/index-CZru7c5T.d.cts +1711 -0
- package/dist/index-CZru7c5T.d.cts.map +1 -0
- package/dist/index-CZru7c5T.d.ts +1711 -0
- package/dist/index-CZru7c5T.d.ts.map +1 -0
- package/dist/index-DMVe5IJA.d.cts +240 -0
- package/dist/index-DMVe5IJA.d.cts.map +1 -0
- package/dist/index-DRWKobSp.d.ts +312 -0
- package/dist/index-DRWKobSp.d.ts.map +1 -0
- package/dist/index-DU9wJ-P2.d.cts +312 -0
- package/dist/index-DU9wJ-P2.d.cts.map +1 -0
- package/dist/index-DbiXllNy.d.cts +66 -0
- package/dist/index-DbiXllNy.d.cts.map +1 -0
- package/dist/index-z9r98qlk.d.ts +66 -0
- package/dist/index-z9r98qlk.d.ts.map +1 -0
- package/dist/index.cjs +89 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +114 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt-BBNqk0TV.cjs +155 -0
- package/dist/jwt-BBNqk0TV.cjs.map +1 -0
- package/dist/jwt-DhqgH94B.js +150 -0
- package/dist/jwt-DhqgH94B.js.map +1 -0
- package/dist/key-resolver-CESqj4-P.cjs +45 -0
- package/dist/key-resolver-CESqj4-P.cjs.map +1 -0
- package/dist/key-resolver-D56I2Zpz.js +34 -0
- package/dist/key-resolver-D56I2Zpz.js.map +1 -0
- package/dist/parse-error-response-6qOQS5y9.cjs +316 -0
- package/dist/parse-error-response-6qOQS5y9.cjs.map +1 -0
- package/dist/parse-error-response-BM9-kjs0.js +239 -0
- package/dist/parse-error-response-BM9-kjs0.js.map +1 -0
- package/dist/path-segment-C25i6aaH.cjs +29 -0
- package/dist/path-segment-C25i6aaH.cjs.map +1 -0
- package/dist/path-segment-CyqnaFrP.js +24 -0
- package/dist/path-segment-CyqnaFrP.js.map +1 -0
- package/dist/react/index.cjs +336 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +151 -0
- package/dist/react/index.d.cts.map +1 -0
- package/dist/react/index.d.ts +151 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +300 -0
- package/dist/react/index.js.map +1 -0
- package/dist/refresh-dedup-CKaHHe7m.js +14 -0
- package/dist/refresh-dedup-CKaHHe7m.js.map +1 -0
- package/dist/refresh-dedup-CLdACQXR.cjs +19 -0
- package/dist/refresh-dedup-CLdACQXR.cjs.map +1 -0
- package/dist/rolldown-runtime-CmQyd0Gu.cjs +27 -0
- package/dist/routes-DpAzgY1V.cjs +424 -0
- package/dist/routes-DpAzgY1V.cjs.map +1 -0
- package/dist/routes-F1g5aVqP.js +347 -0
- package/dist/routes-F1g5aVqP.js.map +1 -0
- package/dist/s2s/index.cjs +24 -0
- package/dist/s2s/index.d.cts +5 -0
- package/dist/s2s/index.d.ts +5 -0
- package/dist/s2s/index.js +5 -0
- package/dist/s2s-6wbotr78.cjs +926 -0
- package/dist/s2s-6wbotr78.cjs.map +1 -0
- package/dist/s2s-B_0SIQzn.js +897 -0
- package/dist/s2s-B_0SIQzn.js.map +1 -0
- package/dist/sign-C7y6xdvT.cjs +324 -0
- package/dist/sign-C7y6xdvT.cjs.map +1 -0
- package/dist/sign-HFtcYwa-.js +259 -0
- package/dist/sign-HFtcYwa-.js.map +1 -0
- package/dist/tokens-C1nzkn21.cjs +232 -0
- package/dist/tokens-C1nzkn21.cjs.map +1 -0
- package/dist/tokens-C3Z40qd7.js +107 -0
- package/dist/tokens-C3Z40qd7.js.map +1 -0
- package/dist/types-Ai3iIFlB.d.cts +538 -0
- package/dist/types-Ai3iIFlB.d.cts.map +1 -0
- package/dist/types-Bxg4hCMc.d.cts +52 -0
- package/dist/types-Bxg4hCMc.d.cts.map +1 -0
- package/dist/types-CEABh1Zf.d.ts +96 -0
- package/dist/types-CEABh1Zf.d.ts.map +1 -0
- package/dist/types-Ci0Jq0xB.d.cts +96 -0
- package/dist/types-Ci0Jq0xB.d.cts.map +1 -0
- package/dist/types-DXg8BvEh.d.ts +52 -0
- package/dist/types-DXg8BvEh.d.ts.map +1 -0
- package/dist/types-_zY7QbM5.d.ts +538 -0
- package/dist/types-_zY7QbM5.d.ts.map +1 -0
- package/dist/webhooks/index.cjs +8 -0
- package/dist/webhooks/index.d.cts +5 -0
- package/dist/webhooks/index.d.ts +5 -0
- package/dist/webhooks/index.js +4 -0
- package/dist/webhooks-B5sAWC9W.js +74 -0
- package/dist/webhooks-B5sAWC9W.js.map +1 -0
- package/dist/webhooks-Cx11psg1.cjs +79 -0
- package/dist/webhooks-Cx11psg1.cjs.map +1 -0
- package/package.json +192 -3
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// src/error-messages.ts
|
|
3
|
+
/**
|
|
4
|
+
* Defaults regression-locked: strings exactos que el SDK escribe hoy.
|
|
5
|
+
* Frozen para prevenir mutación accidental entre tests/requests.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_ERROR_MESSAGES = Object.freeze({
|
|
8
|
+
authRequired: "Autenticación requerida",
|
|
9
|
+
tokenInvalid: "Tokens no válidos",
|
|
10
|
+
tokenExpired: "Token expirado",
|
|
11
|
+
tokenClaimsInvalid: "Claims del token inválidas",
|
|
12
|
+
tokenNotFound: "Token de acceso no encontrado",
|
|
13
|
+
verifyFailedAfterRefresh: "Verificación fallida tras refresh: {0}",
|
|
14
|
+
refreshNoNewTokens: "El refresco no retornó nuevos tokens",
|
|
15
|
+
refreshFailed: "Falló el refresco de tokens",
|
|
16
|
+
loginFailed: "Teléfono o código inválido",
|
|
17
|
+
registrationFailed: "Registro fallido",
|
|
18
|
+
logoutFailed: "Logout fallido",
|
|
19
|
+
invalidJsonBody: "JSON inválido en el body",
|
|
20
|
+
invalidPhone: "Teléfono inválido",
|
|
21
|
+
invalidUpdateBody: "Cuerpo de actualización vacío",
|
|
22
|
+
sessionInvalid: "ID de sesión inválido",
|
|
23
|
+
originNotAllowed: "Origen no permitido",
|
|
24
|
+
internalError: "Error interno"
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Resuelve los mensajes de error con precedencia: local > global > default.
|
|
28
|
+
* El merge es shallow string-por-string.
|
|
29
|
+
* `""` (string vacío) se respeta como override explícito (≠ undefined).
|
|
30
|
+
*/
|
|
31
|
+
function resolveErrorMessages(local, global) {
|
|
32
|
+
return {
|
|
33
|
+
...DEFAULT_ERROR_MESSAGES,
|
|
34
|
+
...global,
|
|
35
|
+
...local
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reemplaza placeholders `{N}` en un template string.
|
|
40
|
+
* Ejemplo: formatMessage('Error: {0}', 'detalle') → 'Error: detalle'
|
|
41
|
+
*/
|
|
42
|
+
function formatMessage(template, ...args) {
|
|
43
|
+
return template.replace(/\{(\d+)\}/g, (_, idx) => args[Number(idx)] ?? "");
|
|
44
|
+
}
|
|
45
|
+
// src/config.ts
|
|
46
|
+
const ErrorMessagesSchema = z.object(Object.fromEntries(Object.keys(DEFAULT_ERROR_MESSAGES).map((k) => [k, z.string()]))).partial().strict();
|
|
47
|
+
let _runtimeConfig = {};
|
|
48
|
+
/**
|
|
49
|
+
* Valida que `value` sea una URL https (o http con host loopback para tests/dev local).
|
|
50
|
+
* Lanza Error síncrono si la URL es malformada, usa protocolo no soportado,
|
|
51
|
+
* o usa http con host no-loopback.
|
|
52
|
+
* Exportada para uso interno del SDK (createS2SClient, createAdminClient).
|
|
53
|
+
* NO re-exportada desde los barrels públicos (src/index.ts, etc.) — REQ-HTTPS-10.
|
|
54
|
+
*/
|
|
55
|
+
function validateHttpsUrl(value, label) {
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = new URL(value);
|
|
59
|
+
} catch {
|
|
60
|
+
throw new Error(`${label} inválida: URL malformada: ${value}`);
|
|
61
|
+
}
|
|
62
|
+
if (parsed.protocol === "http:") {
|
|
63
|
+
const hostname = parsed.hostname;
|
|
64
|
+
if (hostname === "localhost" || hostname === "::1" || hostname === "[::1]" || /^127(?:\.\d{1,3}){3}$/.test(hostname)) return;
|
|
65
|
+
throw new Error(`${label} inválida: se requiere https (o loopback http): ${value}`);
|
|
66
|
+
}
|
|
67
|
+
if (parsed.protocol !== "https:") throw new Error(`${label} inválida: protocolo no soportado (${parsed.protocol}): ${value}`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Valida y normaliza `authUrl`: https (o loopback http), con path permitido, sin userinfo,
|
|
71
|
+
* query ni fragmento. Ningún mensaje incluye el valor recibido: puede traer credenciales.
|
|
72
|
+
* Lo único que se ve en un mensaje es el href ya normalizado (esquema, host, puerto, path),
|
|
73
|
+
* que llegado a ese punto no puede contener userinfo, query ni fragmento.
|
|
74
|
+
* Retorna el href normalizado sin una única `/` final.
|
|
75
|
+
*/
|
|
76
|
+
function validateAuthUrl(value) {
|
|
77
|
+
if (typeof value !== "string") throw new Error("[eva-auth-sdk] authUrl inválida: debe ser string");
|
|
78
|
+
if (value.includes("?") || value.includes("#")) throw new Error("[eva-auth-sdk] authUrl inválida: no puede contener query (?) ni fragmento (#)");
|
|
79
|
+
let parsed;
|
|
80
|
+
try {
|
|
81
|
+
parsed = new URL(value);
|
|
82
|
+
} catch {
|
|
83
|
+
throw new Error("[eva-auth-sdk] authUrl inválida: URL malformada");
|
|
84
|
+
}
|
|
85
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error("[eva-auth-sdk] authUrl inválida: protocolo no soportado (solo https, o http en loopback)");
|
|
86
|
+
if (parsed.username !== "" || parsed.password !== "") throw new Error("[eva-auth-sdk] authUrl inválida: no puede incluir credenciales (usuario/contraseña)");
|
|
87
|
+
validateHttpsUrl(parsed.href, "[eva-auth-sdk] authUrl");
|
|
88
|
+
return parsed.href.replace(/\/$/, "");
|
|
89
|
+
}
|
|
90
|
+
const PRODUCT_SLUG = /^[a-z][a-z0-9-]{2,63}$/;
|
|
91
|
+
function validateProduct(value) {
|
|
92
|
+
if (typeof value !== "string" || !PRODUCT_SLUG.test(value)) throw new Error("[eva-auth-sdk] product inválido: debe ser un slug ^[a-z][a-z0-9-]{2,63}$");
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
function validateCookieDomain(value) {
|
|
96
|
+
if (/[;\r\n]/.test(value)) throw new Error("cookieDomain inválido: caracteres prohibidos (;, \\r, \\n)");
|
|
97
|
+
}
|
|
98
|
+
const CONFIG_ERROR_NAME = "EvaAuthConfigError";
|
|
99
|
+
function createEvaAuthConfigError(message) {
|
|
100
|
+
const err = new Error(message);
|
|
101
|
+
err.name = CONFIG_ERROR_NAME;
|
|
102
|
+
return err;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Indica si `err` es un error de configuración del SDK (falta `authUrl`).
|
|
106
|
+
* Uso interno: `authFetch` y `verifyAccessToken` lo relanzan en vez de mapearlo a
|
|
107
|
+
* red / token inválido. NO re-exportada desde los barrels públicos.
|
|
108
|
+
*/
|
|
109
|
+
function isEvaAuthConfigError(err) {
|
|
110
|
+
return err instanceof Error && err.name === CONFIG_ERROR_NAME;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Fase de validación de `configureEvaAuth`: pura, lanza sin mutar nada.
|
|
114
|
+
* Si cualquier campo es inválido (o `authUrl` cambia), no se confirma ningún campo.
|
|
115
|
+
*/
|
|
116
|
+
function buildConfigPatch(opts, current) {
|
|
117
|
+
const patch = {};
|
|
118
|
+
if (opts.authUrl !== void 0) {
|
|
119
|
+
const normalized = validateAuthUrl(opts.authUrl);
|
|
120
|
+
if (current.authUrl !== void 0 && current.authUrl !== normalized) throw new Error("[eva-auth-sdk] authUrl ya fue configurada y no puede cambiar en runtime");
|
|
121
|
+
patch.authUrl = normalized;
|
|
122
|
+
}
|
|
123
|
+
if (opts.product !== void 0) {
|
|
124
|
+
const product = validateProduct(opts.product);
|
|
125
|
+
if (current.product !== void 0 && current.product !== product) throw new Error("[eva-auth-sdk] product ya fue configurado y no puede cambiar en runtime");
|
|
126
|
+
patch.product = product;
|
|
127
|
+
}
|
|
128
|
+
if (opts.cookieDomain !== void 0) {
|
|
129
|
+
validateCookieDomain(opts.cookieDomain);
|
|
130
|
+
patch.cookieDomain = opts.cookieDomain;
|
|
131
|
+
}
|
|
132
|
+
if (opts.errorMessages !== void 0) patch.errorMessages = validateErrorMessagesInput(opts.errorMessages);
|
|
133
|
+
if (opts.errorWire !== void 0) {
|
|
134
|
+
if (opts.errorWire !== "api" && opts.errorWire !== "string") throw new Error(`[eva-auth-sdk] errorWire inválido: "${opts.errorWire}". Valores válidos: 'api' | 'string'`);
|
|
135
|
+
patch.errorWire = opts.errorWire;
|
|
136
|
+
}
|
|
137
|
+
return patch;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Configura el SDK en runtime. Llamar al boot del consumidor, antes del primer request;
|
|
141
|
+
* importar el SDK o crear `evaAuth()` no lee la configuración ni lanza.
|
|
142
|
+
*
|
|
143
|
+
* Es atómica: valida todos los campos y recién entonces los confirma; si uno falla, ninguno cambia.
|
|
144
|
+
* `authUrl` es inmutable (re-configurar el mismo valor normalizado es no-op). El resto de los
|
|
145
|
+
* campos provistos sobrescriben el valor previo; los omitidos (undefined) no lo resetean.
|
|
146
|
+
*
|
|
147
|
+
* @throws Error si `authUrl` o `product` son inválidos o distintos de los ya configurados, si cookieDomain contiene
|
|
148
|
+
* caracteres de header injection (;, \r, \n), o si errorMessages / errorWire son inválidos.
|
|
149
|
+
*/
|
|
150
|
+
function configureEvaAuth(opts) {
|
|
151
|
+
const patch = buildConfigPatch(opts, _runtimeConfig);
|
|
152
|
+
_runtimeConfig = {
|
|
153
|
+
..._runtimeConfig,
|
|
154
|
+
...patch
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Retorna la URL del Auth Service configurada vía `configureEvaAuth({ authUrl })`
|
|
159
|
+
* (normalizada, sin `/` final).
|
|
160
|
+
* @throws Error de configuración (`name === 'EvaAuthConfigError'`) si aún no se configuró.
|
|
161
|
+
* `authFetch` y `verifyAccessToken` lo propagan: el consumidor ve un 500, nunca un 401 o un error de red.
|
|
162
|
+
*/
|
|
163
|
+
function getAuthUrl() {
|
|
164
|
+
if (_runtimeConfig.authUrl === void 0) throw createEvaAuthConfigError("[eva-auth-sdk] authUrl no configurada: llama configureEvaAuth({ authUrl }) al arrancar");
|
|
165
|
+
return _runtimeConfig.authUrl;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Retorna el producto configurado vía `configureEvaAuth({ product })`.
|
|
169
|
+
* @throws Error de configuración (`name === 'EvaAuthConfigError'`) si aún no se configuró: lo
|
|
170
|
+
* propagan las cookies, el login y `verifyAccessToken` (el consumidor ve un 500, nunca un 401).
|
|
171
|
+
*/
|
|
172
|
+
function getProduct() {
|
|
173
|
+
if (_runtimeConfig.product === void 0) throw createEvaAuthConfigError("[eva-auth-sdk] product no configurado: llama configureEvaAuth({ product }) al arrancar");
|
|
174
|
+
return _runtimeConfig.product;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Retorna el cookieDomain configurado vía configureEvaAuth, o undefined si no se configuró.
|
|
178
|
+
*/
|
|
179
|
+
function getCookieDomain() {
|
|
180
|
+
return _runtimeConfig.cookieDomain;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Retorna los errorMessages globales configurados vía configureEvaAuth (sin merge con defaults).
|
|
184
|
+
* Retorna undefined si no se configuraron.
|
|
185
|
+
*/
|
|
186
|
+
function getErrorMessages() {
|
|
187
|
+
return _runtimeConfig.errorMessages;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Retorna el shape del wire HTTP para respuestas de error.
|
|
191
|
+
* Default: 'api' — sin configureEvaAuth el SDK emite { error: { code, message } }.
|
|
192
|
+
* D-13 v2 LOCKED.
|
|
193
|
+
*/
|
|
194
|
+
function getErrorWire() {
|
|
195
|
+
return _runtimeConfig.errorWire ?? "api";
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Valida un objeto Partial<EvaErrorMessages> con Zod.
|
|
199
|
+
* Lanza Error con path y mensaje de Zod si alguna key es desconocida o algún valor no es string.
|
|
200
|
+
* Usado internamente por configureEvaAuth, evaAuth y verifyRequest para validación temprana.
|
|
201
|
+
*/
|
|
202
|
+
function validateErrorMessagesInput(input) {
|
|
203
|
+
const result = ErrorMessagesSchema.safeParse(input);
|
|
204
|
+
if (!result.success) throw new Error(`[eva-auth-sdk] errorMessages inválido: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
|
|
205
|
+
return result.data;
|
|
206
|
+
}
|
|
207
|
+
// src/parse-error-response.ts
|
|
208
|
+
function parseErrorResponse(status, body) {
|
|
209
|
+
if (status === 0) return {
|
|
210
|
+
kind: "sdk",
|
|
211
|
+
reason: "network",
|
|
212
|
+
message: "Network error",
|
|
213
|
+
status: 0
|
|
214
|
+
};
|
|
215
|
+
if (body === null || body === void 0) return {
|
|
216
|
+
kind: "sdk",
|
|
217
|
+
reason: "malformed",
|
|
218
|
+
message: "Malformed response",
|
|
219
|
+
status
|
|
220
|
+
};
|
|
221
|
+
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "object" && body.error !== null && typeof body.error.code === "string" && typeof body.error.message === "string") {
|
|
222
|
+
const err = body.error;
|
|
223
|
+
return {
|
|
224
|
+
kind: "api",
|
|
225
|
+
code: err.code,
|
|
226
|
+
message: err.message,
|
|
227
|
+
status
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
kind: "sdk",
|
|
232
|
+
reason: "malformed",
|
|
233
|
+
message: "Malformed error response",
|
|
234
|
+
status
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
export { getErrorMessages as a, isEvaAuthConfigError as c, DEFAULT_ERROR_MESSAGES as d, formatMessage as f, getCookieDomain as i, validateErrorMessagesInput as l, configureEvaAuth as n, getErrorWire as o, resolveErrorMessages as p, getAuthUrl as r, getProduct as s, parseErrorResponse as t, validateHttpsUrl as u };
|
|
238
|
+
|
|
239
|
+
//# sourceMappingURL=parse-error-response-BM9-kjs0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-error-response-BM9-kjs0.js","names":[],"sources":["../src/error-messages.ts","../src/config.ts","../src/parse-error-response.ts"],"sourcesContent":["/**\n * Mensajes de error del SDK — fuente de verdad centralizada.\n * Standalone: NO importa de config.ts (evita ciclo de dependencias).\n * La validación runtime de overrides vive en config.ts (usa Zod).\n */\n\nexport interface EvaErrorMessages {\n // === Middleware / verify ===\n /** Auth requerida (middleware 401 sin token). */\n authRequired: string\n /** Token inválido (signature/format). */\n tokenInvalid: string\n /** Token expirado. */\n tokenExpired: string\n /** Claims del token no cumplen schema extra. */\n tokenClaimsInvalid: string\n /** Token de acceso/refresh no presente en cookies. */\n tokenNotFound: string\n /** Verify falló después de refresh exitoso. Soporta placeholder {0} para el inner error. */\n verifyFailedAfterRefresh: string\n /** Refresh OK pero servidor no devolvió tokens. */\n refreshNoNewTokens: string\n /** Refresh token falló. */\n refreshFailed: string\n // === Auth routes ===\n /** Login con credenciales inválidas. */\n loginFailed: string\n /** Registro falló. */\n registrationFailed: string\n /** Logout falló. */\n logoutFailed: string\n /** JSON malformado en body. */\n invalidJsonBody: string\n /** Schema validation falló sobre teléfono. */\n invalidPhone: string\n /** Body de PATCH /me vacío o inválido. */\n invalidUpdateBody: string\n /** sessionId malformado en /sessions/:id. */\n sessionInvalid: string\n /** Mutación con `Origin` fuera de los orígenes permitidos (403). */\n originNotAllowed: string\n // === Generic ===\n /** Error interno (500) cuando se expone al cliente. */\n internalError: string\n}\n\n/**\n * Defaults regression-locked: strings exactos que el SDK escribe hoy.\n * Frozen para prevenir mutación accidental entre tests/requests.\n */\nexport const DEFAULT_ERROR_MESSAGES: Readonly<EvaErrorMessages> = Object.freeze(\n {\n authRequired: 'Autenticación requerida',\n tokenInvalid: 'Tokens no válidos',\n tokenExpired: 'Token expirado',\n tokenClaimsInvalid: 'Claims del token inválidas',\n tokenNotFound: 'Token de acceso no encontrado',\n verifyFailedAfterRefresh: 'Verificación fallida tras refresh: {0}',\n refreshNoNewTokens: 'El refresco no retornó nuevos tokens',\n refreshFailed: 'Falló el refresco de tokens',\n loginFailed: 'Teléfono o código inválido',\n registrationFailed: 'Registro fallido',\n logoutFailed: 'Logout fallido',\n invalidJsonBody: 'JSON inválido en el body',\n invalidPhone: 'Teléfono inválido',\n invalidUpdateBody: 'Cuerpo de actualización vacío',\n sessionInvalid: 'ID de sesión inválido',\n originNotAllowed: 'Origen no permitido',\n internalError: 'Error interno',\n },\n)\n\n/**\n * Resuelve los mensajes de error con precedencia: local > global > default.\n * El merge es shallow string-por-string.\n * `\"\"` (string vacío) se respeta como override explícito (≠ undefined).\n */\nexport function resolveErrorMessages(\n local?: Partial<EvaErrorMessages>,\n global?: Partial<EvaErrorMessages>,\n): EvaErrorMessages {\n return { ...DEFAULT_ERROR_MESSAGES, ...global, ...local }\n}\n\n/**\n * Reemplaza placeholders `{N}` en un template string.\n * Ejemplo: formatMessage('Error: {0}', 'detalle') → 'Error: detalle'\n */\nexport function formatMessage(template: string, ...args: string[]): string {\n return template.replace(/\\{(\\d+)\\}/g, (_, idx) => args[Number(idx)] ?? '')\n}\n","import { z } from 'zod'\nimport { DEFAULT_ERROR_MESSAGES, type EvaErrorMessages } from './error-messages'\n\n// Schema generado dinámicamente desde DEFAULT_ERROR_MESSAGES → keys siempre sincronizadas.\n// .partial() → todas las keys son opcionales. .strict() → rechaza keys desconocidas.\nconst ErrorMessagesSchema = z\n .object(\n Object.fromEntries(\n (Object.keys(DEFAULT_ERROR_MESSAGES) as (keyof EvaErrorMessages)[]).map(\n (k) => [k, z.string()],\n ),\n ) as Record<keyof EvaErrorMessages, z.ZodString>,\n )\n .partial()\n .strict()\n\n// === Estado runtime mutable (NO exportado directamente) ===\ntype RuntimeConfig = {\n authUrl?: string\n product?: string\n cookieDomain?: string\n errorMessages?: Partial<EvaErrorMessages>\n errorWire?: 'api' | 'string'\n}\n\nlet _runtimeConfig: RuntimeConfig = {}\n\n// === Validators ===\n\n/**\n * Valida que `value` sea una URL https (o http con host loopback para tests/dev local).\n * Lanza Error síncrono si la URL es malformada, usa protocolo no soportado,\n * o usa http con host no-loopback.\n * Exportada para uso interno del SDK (createS2SClient, createAdminClient).\n * NO re-exportada desde los barrels públicos (src/index.ts, etc.) — REQ-HTTPS-10.\n */\nexport function validateHttpsUrl(value: string, label: string): void {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error(`${label} inválida: URL malformada: ${value}`)\n }\n\n if (parsed.protocol === 'http:') {\n // NOTA: en Node.js, new URL('http://[::1]:4000').hostname devuelve '[::1]' (con corchetes).\n // El WHATWG URL spec permite ambas representaciones según el runtime.\n // Este SDK se ejecuta en Node.js/Edge runtimes que mantienen los corchetes en .hostname para IPv6.\n const hostname = parsed.hostname\n // oxlint-disable-next-line prefer-string-starts-ends-with -- regex anclada requerida para seguridad (CWE-319): startsWith('127.') aceptaría '127.evil.com'\n if (\n hostname === 'localhost' ||\n hostname === '::1' || // defensa: dead-code en Node 20+ (Ada 2.0 retorna '[::1]' con corchetes)\n hostname === '[::1]' || // Node.js 20+ (WHATWG Ada 2.0): .hostname de IPv6 literal incluye corchetes\n /^127(?:\\.\\d{1,3}){3}$/.test(hostname) // forma IPv4 completa anclada — bloquea '127.evil.com'\n ) {\n return // loopback http: permitido (tests + desarrollo local)\n }\n throw new Error(\n `${label} inválida: se requiere https (o loopback http): ${value}`,\n )\n }\n\n if (parsed.protocol !== 'https:') {\n throw new Error(\n `${label} inválida: protocolo no soportado (${parsed.protocol}): ${value}`,\n )\n }\n // https: → válido, void\n}\n\n/**\n * Valida y normaliza `authUrl`: https (o loopback http), con path permitido, sin userinfo,\n * query ni fragmento. Ningún mensaje incluye el valor recibido: puede traer credenciales.\n * Lo único que se ve en un mensaje es el href ya normalizado (esquema, host, puerto, path),\n * que llegado a ese punto no puede contener userinfo, query ni fragmento.\n * Retorna el href normalizado sin una única `/` final.\n */\nfunction validateAuthUrl(value: unknown): string {\n // Entrada de JS sin tipar (as any / JSON): sin esto `value.includes` lanzaría un TypeError ajeno.\n if (typeof value !== 'string') {\n throw new Error('[eva-auth-sdk] authUrl inválida: debe ser string')\n }\n // Chequeo sobre el string crudo: `URL.search`/`URL.hash` valen '' para un `?` o `#` solitario.\n if (value.includes('?') || value.includes('#')) {\n throw new Error(\n '[eva-auth-sdk] authUrl inválida: no puede contener query (?) ni fragmento (#)',\n )\n }\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n throw new Error('[eva-auth-sdk] authUrl inválida: URL malformada')\n }\n // Esquemas con path opaco (mailto:, redis:, data:) no exponen userinfo en URL.username y\n // validateHttpsUrl ecoaría el valor crudo: se rechazan aquí, sin incluir el input.\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n throw new Error(\n '[eva-auth-sdk] authUrl inválida: protocolo no soportado (solo https, o http en loopback)',\n )\n }\n if (parsed.username !== '' || parsed.password !== '') {\n throw new Error(\n '[eva-auth-sdk] authUrl inválida: no puede incluir credenciales (usuario/contraseña)',\n )\n }\n validateHttpsUrl(parsed.href, '[eva-auth-sdk] authUrl')\n return parsed.href.replace(/\\/$/, '')\n}\n\n// Mismo formato que el slug de producto del contrato (`productoSlugSchema`). Se repite aquí porque\n// config.ts es alcanzable desde `react` y no puede importar módulos de schemas (regla D-35).\n// Que un producto no coincida con una audiencia de servicio lo valida Auth (`isServiceAudience`):\n// un token de usuario nunca lleva una audiencia de servicio, así que aquí no cambiaría nada.\nconst PRODUCT_SLUG = /^[a-z][a-z0-9-]{2,63}$/\n\nfunction validateProduct(value: unknown): string {\n if (typeof value !== 'string' || !PRODUCT_SLUG.test(value)) {\n throw new Error(\n '[eva-auth-sdk] product inválido: debe ser un slug ^[a-z][a-z0-9-]{2,63}$',\n )\n }\n return value\n}\n\nfunction validateCookieDomain(value: string): void {\n if (/[;\\r\\n]/.test(value)) {\n throw new Error(\n 'cookieDomain inválido: caracteres prohibidos (;, \\\\r, \\\\n)',\n )\n }\n}\n\n// === API pública ===\n\nexport interface ConfigureEvaAuthOptions {\n /**\n * URL base del Auth Service. Obligatoria antes del primer uso que la necesite\n * (`authFetch`, JWKS): si falta, esos usos lanzan `EvaAuthConfigError`.\n * Acepta https, o http solo en loopback (localhost, 127.0.0.1, [::1]); admite path\n * (`https://host/auth`). Rechaza userinfo, query y fragmento (incluidos `?` y `#` solitarios).\n * Se normaliza (host en minúsculas, sin `/` final) y es inmutable: reconfigurar con el mismo\n * valor normalizado es no-op; con otro valor lanza Error.\n * Si se omite (undefined), no valida ni modifica el valor previo.\n * @throws Error si la URL es inválida o difiere de la ya configurada.\n */\n authUrl?: string\n /**\n * Slug del producto de este consumidor (`whatsapp-panel`). Obligatorio **solo** si se usan las\n * rutas de login, las cookies de sesión o `verifyAccessToken`: da el nombre de las cookies\n * (`eva_<producto>_access_token`), la audiencia (`aud`) que exige `verifyAccessToken` y el\n * `producto` que viaja en el login. Un servicio que solo verifica tokens de servicio no lo necesita.\n * Debe ser un slug (`^[a-z][a-z0-9-]{2,63}$`).\n * Es inmutable: reconfigurar el mismo valor es no-op; con otro valor lanza Error.\n * Si se omite (undefined), no valida ni modifica el valor previo.\n * @throws Error si el slug es inválido o difiere del ya configurado.\n */\n product?: string\n /**\n * Domain para Set-Cookie. Validada contra header injection (;, \\r, \\n).\n * Si se omite (undefined), NO resetea el valor previo.\n * Recomendado: '.miempresa.com' para compartir entre subdominios.\n */\n cookieDomain?: string\n /**\n * Mensajes de error que el SDK escribe en respuestas 4xx.\n * Override granular: keys no provistas mantienen el default.\n * Si se omite (undefined), NO resetea el valor previo.\n * `\"\"` se respeta como override explícito (no cae al default).\n * @throws Error si alguna key es desconocida o si algún valor no es string.\n */\n errorMessages?: Partial<EvaErrorMessages>\n /**\n * Shape del wire HTTP que el SDK Hono emite cuando rechaza un request.\n * - 'api' (default): { error: { code: string, message: string } } — consistente con el API.\n * - 'string': { error: string } — legacy, para consumers que esperan mensaje plano.\n * D-13 v2 LOCKED: default='api', configurable para compat con consumers 0.x.\n * @throws Error si se pasa un valor distinto de 'api' o 'string'.\n */\n errorWire?: 'api' | 'string'\n}\n\nconst CONFIG_ERROR_NAME = 'EvaAuthConfigError'\n\nfunction createEvaAuthConfigError(message: string): Error {\n const err = new Error(message)\n err.name = CONFIG_ERROR_NAME\n return err\n}\n\n/**\n * Indica si `err` es un error de configuración del SDK (falta `authUrl`).\n * Uso interno: `authFetch` y `verifyAccessToken` lo relanzan en vez de mapearlo a\n * red / token inválido. NO re-exportada desde los barrels públicos.\n */\nexport function isEvaAuthConfigError(err: unknown): boolean {\n return err instanceof Error && err.name === CONFIG_ERROR_NAME\n}\n\n/**\n * Fase de validación de `configureEvaAuth`: pura, lanza sin mutar nada.\n * Si cualquier campo es inválido (o `authUrl` cambia), no se confirma ningún campo.\n */\nfunction buildConfigPatch(\n opts: ConfigureEvaAuthOptions,\n current: RuntimeConfig,\n): Partial<RuntimeConfig> {\n const patch: Partial<RuntimeConfig> = {}\n if (opts.authUrl !== undefined) {\n const normalized = validateAuthUrl(opts.authUrl)\n if (current.authUrl !== undefined && current.authUrl !== normalized) {\n throw new Error(\n '[eva-auth-sdk] authUrl ya fue configurada y no puede cambiar en runtime',\n )\n }\n patch.authUrl = normalized\n }\n if (opts.product !== undefined) {\n const product = validateProduct(opts.product)\n if (current.product !== undefined && current.product !== product) {\n throw new Error(\n '[eva-auth-sdk] product ya fue configurado y no puede cambiar en runtime',\n )\n }\n patch.product = product\n }\n if (opts.cookieDomain !== undefined) {\n validateCookieDomain(opts.cookieDomain)\n patch.cookieDomain = opts.cookieDomain\n }\n if (opts.errorMessages !== undefined) {\n patch.errorMessages = validateErrorMessagesInput(opts.errorMessages)\n }\n if (opts.errorWire !== undefined) {\n if (opts.errorWire !== 'api' && opts.errorWire !== 'string') {\n throw new Error(\n `[eva-auth-sdk] errorWire inválido: \"${opts.errorWire}\". Valores válidos: 'api' | 'string'`,\n )\n }\n patch.errorWire = opts.errorWire\n }\n return patch\n}\n\n/**\n * Configura el SDK en runtime. Llamar al boot del consumidor, antes del primer request;\n * importar el SDK o crear `evaAuth()` no lee la configuración ni lanza.\n *\n * Es atómica: valida todos los campos y recién entonces los confirma; si uno falla, ninguno cambia.\n * `authUrl` es inmutable (re-configurar el mismo valor normalizado es no-op). El resto de los\n * campos provistos sobrescriben el valor previo; los omitidos (undefined) no lo resetean.\n *\n * @throws Error si `authUrl` o `product` son inválidos o distintos de los ya configurados, si cookieDomain contiene\n * caracteres de header injection (;, \\r, \\n), o si errorMessages / errorWire son inválidos.\n */\nexport function configureEvaAuth(opts: ConfigureEvaAuthOptions): void {\n const patch = buildConfigPatch(opts, _runtimeConfig)\n _runtimeConfig = { ..._runtimeConfig, ...patch }\n}\n\n/**\n * Retorna la URL del Auth Service configurada vía `configureEvaAuth({ authUrl })`\n * (normalizada, sin `/` final).\n * @throws Error de configuración (`name === 'EvaAuthConfigError'`) si aún no se configuró.\n * `authFetch` y `verifyAccessToken` lo propagan: el consumidor ve un 500, nunca un 401 o un error de red.\n */\nexport function getAuthUrl(): string {\n if (_runtimeConfig.authUrl === undefined) {\n throw createEvaAuthConfigError(\n '[eva-auth-sdk] authUrl no configurada: llama configureEvaAuth({ authUrl }) al arrancar',\n )\n }\n return _runtimeConfig.authUrl\n}\n\n/**\n * Retorna el producto configurado vía `configureEvaAuth({ product })`.\n * @throws Error de configuración (`name === 'EvaAuthConfigError'`) si aún no se configuró: lo\n * propagan las cookies, el login y `verifyAccessToken` (el consumidor ve un 500, nunca un 401).\n */\nexport function getProduct(): string {\n if (_runtimeConfig.product === undefined) {\n throw createEvaAuthConfigError(\n '[eva-auth-sdk] product no configurado: llama configureEvaAuth({ product }) al arrancar',\n )\n }\n return _runtimeConfig.product\n}\n\n/**\n * Retorna el cookieDomain configurado vía configureEvaAuth, o undefined si no se configuró.\n */\nexport function getCookieDomain(): string | undefined {\n return _runtimeConfig.cookieDomain\n}\n\n/**\n * Retorna los errorMessages globales configurados vía configureEvaAuth (sin merge con defaults).\n * Retorna undefined si no se configuraron.\n */\nexport function getErrorMessages(): Partial<EvaErrorMessages> | undefined {\n return _runtimeConfig.errorMessages\n}\n\n/**\n * Retorna el shape del wire HTTP para respuestas de error.\n * Default: 'api' — sin configureEvaAuth el SDK emite { error: { code, message } }.\n * D-13 v2 LOCKED.\n */\nexport function getErrorWire(): 'api' | 'string' {\n return _runtimeConfig.errorWire ?? 'api'\n}\n\n/**\n * Valida un objeto Partial<EvaErrorMessages> con Zod.\n * Lanza Error con path y mensaje de Zod si alguna key es desconocida o algún valor no es string.\n * Usado internamente por configureEvaAuth, evaAuth y verifyRequest para validación temprana.\n */\nexport function validateErrorMessagesInput(\n input: Partial<EvaErrorMessages>,\n): Partial<EvaErrorMessages> {\n const result = ErrorMessagesSchema.safeParse(input)\n if (!result.success) {\n throw new Error(\n `[eva-auth-sdk] errorMessages inválido: ${result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`,\n )\n }\n return result.data\n}\n\n// NOTA: NO se exporta __resetEvaAuthConfig.\n// Los tests que necesiten resetear estado usan vi.resetModules() + re-import dinámico.\n","/**\n * Parsea el body de una respuesta HTTP de error a EvaError.\n * Sync — el caller debe haber hecho `await res.json().catch(() => null)` antes de llamar.\n *\n * Módulo PURO (D-35): solo `import type`, sin zod ni schemas del contrato. Lo importa código\n * alcanzable desde `src/react/index.ts`; si importara un módulo SCHEMA, el closure de react\n * arrastraría sus `.meta()` (no puros) y rompería el tope de tamaño.\n *\n * Algoritmo (D-14 LOCKED):\n * - status === 0 → EvaSdkError reason:'network'\n * - body null/undefined → EvaSdkError reason:'malformed'\n * - body.error.{code,message} presentes → EvaApiError\n * - cualquier otro caso → EvaSdkError reason:'malformed'\n */\nimport type { EvaError, EvaApiError, EvaSdkError } from './types'\n\nexport function parseErrorResponse(status: number, body: unknown): EvaError {\n if (status === 0) {\n return {\n kind: 'sdk',\n reason: 'network',\n message: 'Network error',\n status: 0,\n } satisfies EvaSdkError\n }\n\n if (body === null || body === undefined) {\n return {\n kind: 'sdk',\n reason: 'malformed',\n message: 'Malformed response',\n status,\n } satisfies EvaSdkError\n }\n\n if (\n typeof body === 'object' &&\n body !== null &&\n 'error' in body &&\n typeof (body as Record<string, unknown>).error === 'object' &&\n (body as Record<string, unknown>).error !== null &&\n typeof ((body as Record<string, unknown>).error as Record<string, unknown>)\n .code === 'string' &&\n typeof ((body as Record<string, unknown>).error as Record<string, unknown>)\n .message === 'string'\n ) {\n const err = (body as Record<string, unknown>).error as {\n code: string\n message: string\n }\n return {\n kind: 'api',\n code: err.code,\n message: err.message,\n status,\n } satisfies EvaApiError\n }\n\n return {\n kind: 'sdk',\n reason: 'malformed',\n message: 'Malformed error response',\n status,\n } satisfies EvaSdkError\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/path-segment.ts
|
|
2
|
+
/**
|
|
3
|
+
* Valida y codifica un valor para usarlo como UN segmento del path. Retorna `null` si el valor no
|
|
4
|
+
* es un string, es vacío, `.` o `..` (crudo o percent-decodificado, `%2e` en cualquier caso): como
|
|
5
|
+
* los clientes insertan el segmento en la URL (el S2S además firma el pathname normalizado), un
|
|
6
|
+
* valor así redirigiría la request a otro endpoint. `encodeURIComponent` solo no basta: no
|
|
7
|
+
* codifica `.`.
|
|
8
|
+
*
|
|
9
|
+
* El resultado ya está codificado: pásalo tal cual a `apiPath`, que no codifica (codificarlo dos
|
|
10
|
+
* veces convertiría `%` en `%25`).
|
|
11
|
+
*/
|
|
12
|
+
function encodePathSegment(value) {
|
|
13
|
+
if (typeof value !== "string") return null;
|
|
14
|
+
const isDotSegment = (candidate) => candidate === "." || candidate === "..";
|
|
15
|
+
let decoded = value;
|
|
16
|
+
try {
|
|
17
|
+
decoded = decodeURIComponent(value);
|
|
18
|
+
} catch {}
|
|
19
|
+
if (value === "" || isDotSegment(value) || isDotSegment(decoded)) return null;
|
|
20
|
+
return encodeURIComponent(value);
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(exports, "encodePathSegment", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function() {
|
|
25
|
+
return encodePathSegment;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=path-segment-C25i6aaH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-segment-C25i6aaH.cjs","names":[],"sources":["../src/path-segment.ts"],"sourcesContent":["/**\n * Valida y codifica un valor para usarlo como UN segmento del path. Retorna `null` si el valor no\n * es un string, es vacío, `.` o `..` (crudo o percent-decodificado, `%2e` en cualquier caso): como\n * los clientes insertan el segmento en la URL (el S2S además firma el pathname normalizado), un\n * valor así redirigiría la request a otro endpoint. `encodeURIComponent` solo no basta: no\n * codifica `.`.\n *\n * El resultado ya está codificado: pásalo tal cual a `apiPath`, que no codifica (codificarlo dos\n * veces convertiría `%` en `%25`).\n */\nexport function encodePathSegment(value: string): string | null {\n if (typeof value !== 'string') return null\n const isDotSegment = (candidate: string) =>\n candidate === '.' || candidate === '..'\n let decoded = value\n try {\n decoded = decodeURIComponent(value)\n } catch {\n // percent-encoding malformado: no decodifica a nada peligroso; se codifica tal cual.\n }\n if (value === '' || isDotSegment(value) || isDotSegment(decoded)) return null\n return encodeURIComponent(value)\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,kBAAkB,OAA8B;CAC9D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,gBAAgB,cACpB,cAAc,OAAO,cAAc;CACrC,IAAI,UAAU;CACd,IAAI;EACF,UAAU,mBAAmB,KAAK;CACpC,QAAQ,CAER;CACA,IAAI,UAAU,MAAM,aAAa,KAAK,KAAK,aAAa,OAAO,GAAG,OAAO;CACzE,OAAO,mBAAmB,KAAK;AACjC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/path-segment.ts
|
|
2
|
+
/**
|
|
3
|
+
* Valida y codifica un valor para usarlo como UN segmento del path. Retorna `null` si el valor no
|
|
4
|
+
* es un string, es vacío, `.` o `..` (crudo o percent-decodificado, `%2e` en cualquier caso): como
|
|
5
|
+
* los clientes insertan el segmento en la URL (el S2S además firma el pathname normalizado), un
|
|
6
|
+
* valor así redirigiría la request a otro endpoint. `encodeURIComponent` solo no basta: no
|
|
7
|
+
* codifica `.`.
|
|
8
|
+
*
|
|
9
|
+
* El resultado ya está codificado: pásalo tal cual a `apiPath`, que no codifica (codificarlo dos
|
|
10
|
+
* veces convertiría `%` en `%25`).
|
|
11
|
+
*/
|
|
12
|
+
function encodePathSegment(value) {
|
|
13
|
+
if (typeof value !== "string") return null;
|
|
14
|
+
const isDotSegment = (candidate) => candidate === "." || candidate === "..";
|
|
15
|
+
let decoded = value;
|
|
16
|
+
try {
|
|
17
|
+
decoded = decodeURIComponent(value);
|
|
18
|
+
} catch {}
|
|
19
|
+
if (value === "" || isDotSegment(value) || isDotSegment(decoded)) return null;
|
|
20
|
+
return encodeURIComponent(value);
|
|
21
|
+
}
|
|
22
|
+
export { encodePathSegment as t };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=path-segment-CyqnaFrP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-segment-CyqnaFrP.js","names":[],"sources":["../src/path-segment.ts"],"sourcesContent":["/**\n * Valida y codifica un valor para usarlo como UN segmento del path. Retorna `null` si el valor no\n * es un string, es vacío, `.` o `..` (crudo o percent-decodificado, `%2e` en cualquier caso): como\n * los clientes insertan el segmento en la URL (el S2S además firma el pathname normalizado), un\n * valor así redirigiría la request a otro endpoint. `encodeURIComponent` solo no basta: no\n * codifica `.`.\n *\n * El resultado ya está codificado: pásalo tal cual a `apiPath`, que no codifica (codificarlo dos\n * veces convertiría `%` en `%25`).\n */\nexport function encodePathSegment(value: string): string | null {\n if (typeof value !== 'string') return null\n const isDotSegment = (candidate: string) =>\n candidate === '.' || candidate === '..'\n let decoded = value\n try {\n decoded = decodeURIComponent(value)\n } catch {\n // percent-encoding malformado: no decodifica a nada peligroso; se codifica tal cual.\n }\n if (value === '' || isDotSegment(value) || isDotSegment(decoded)) return null\n return encodeURIComponent(value)\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,kBAAkB,OAA8B;CAC9D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,gBAAgB,cACpB,cAAc,OAAO,cAAc;CACrC,IAAI,UAAU;CACd,IAAI;EACF,UAAU,mBAAmB,KAAK;CACpC,QAAQ,CAER;CACA,IAAI,UAAU,MAAM,aAAa,KAAK,KAAK,aAAa,OAAO,GAAG,OAAO;CACzE,OAAO,mBAAmB,KAAK;AACjC"}
|