@neetru/sdk 3.7.0 → 3.8.0
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 +55 -0
- package/README.md +66 -1
- package/dist/ai.cjs +221 -177
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/ai.mjs +221 -177
- package/dist/auth.cjs +1227 -1064
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +1224 -1061
- package/dist/catalog.cjs +164 -97
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs +164 -97
- package/dist/checkout.cjs +182 -115
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +181 -114
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +370 -298
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +362 -290
- package/dist/entitlements.cjs +17 -10
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/entitlements.mjs +17 -10
- package/dist/errors.cjs +15 -8
- package/dist/errors.d.cts +24 -3
- package/dist/errors.d.ts +24 -3
- package/dist/errors.mjs +14 -7
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/index.cjs +1409 -1075
- package/dist/index.d.cts +177 -3
- package/dist/index.d.ts +177 -3
- package/dist/index.mjs +1544 -1217
- package/dist/mobile.cjs +400 -181
- package/dist/mobile.d.cts +59 -4
- package/dist/mobile.d.ts +59 -4
- package/dist/mobile.mjs +400 -181
- package/dist/mocks.cjs +9 -2
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.mjs +9 -2
- package/dist/notifications.cjs +197 -130
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs +196 -129
- package/dist/react.cjs +303 -282
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +295 -274
- package/dist/support.cjs +299 -229
- package/dist/support.d.cts +8 -4
- package/dist/support.d.ts +8 -4
- package/dist/support.mjs +298 -228
- package/dist/telemetry.cjs +234 -167
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs +234 -167
- package/dist/{types-Bx4kTLmk.d.cts → types-D-9bjlM0.d.cts} +48 -1
- package/dist/{types-Dx0IrOSF.d.ts → types-bVztFQTI.d.ts} +48 -1
- package/dist/usage.cjs +183 -116
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs +183 -116
- package/dist/webhooks.cjs +215 -148
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs +212 -145
- package/package.json +2 -1
package/dist/mobile.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/errors.ts
|
|
4
|
-
var
|
|
4
|
+
var n = class t extends Error {
|
|
5
5
|
code;
|
|
6
6
|
status;
|
|
7
7
|
requestId;
|
|
@@ -14,61 +14,72 @@ var r = class t extends Error {
|
|
|
14
14
|
* para um `NeetruDbErrorCode` mais específico (recuperável vs não).
|
|
15
15
|
*/
|
|
16
16
|
reason;
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* 3.8.0: `x-correlation-id` da requisição que falhou. O SDK gera um UUID por
|
|
19
|
+
* chamada (ou usa o que o chamador passou) e manda no header; o Core grava o
|
|
20
|
+
* mesmo id nos logs/auditoria — cite-o ao abrir um ticket de suporte.
|
|
21
|
+
* `undefined` em erros que acontecem antes de qualquer requisição.
|
|
22
|
+
*/
|
|
23
|
+
correlationId;
|
|
24
|
+
constructor(e, o, s, i, p, m) {
|
|
25
|
+
super(o), this.name = "NeetruError", this.code = e, this.status = s, this.requestId = i, this.reason = p, this.correlationId = m, Object.setPrototypeOf(this, t.prototype);
|
|
26
|
+
}
|
|
27
|
+
}, v = class t extends n {
|
|
28
|
+
constructor(e, o, s, i, p) {
|
|
29
|
+
super("auth_required", e, s, i, o, p), this.name = "NeetruAuthRequiredError", Object.setPrototypeOf(this, t.prototype);
|
|
19
30
|
}
|
|
20
31
|
};
|
|
21
32
|
|
|
22
33
|
// src/types.ts
|
|
23
|
-
var
|
|
34
|
+
var H = "https://api.neetru.com";
|
|
24
35
|
|
|
25
36
|
// src/base-url-allowlist.ts
|
|
26
|
-
var
|
|
27
|
-
function
|
|
28
|
-
return
|
|
37
|
+
var B = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]), le = ".neetru.com", ue = "neetru.com", de = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?\.(test|localhost)$/;
|
|
38
|
+
function j(t) {
|
|
39
|
+
return de.test(t);
|
|
29
40
|
}
|
|
30
|
-
function
|
|
41
|
+
function pe(t) {
|
|
31
42
|
return t.toLowerCase().replace(/\.+$/, "");
|
|
32
43
|
}
|
|
33
|
-
function
|
|
44
|
+
function F(t, e = []) {
|
|
34
45
|
if (typeof t != "string" || t.length === 0)
|
|
35
|
-
throw new
|
|
36
|
-
let
|
|
46
|
+
throw new n("invalid_config", "baseUrl is required");
|
|
47
|
+
let o;
|
|
37
48
|
try {
|
|
38
|
-
|
|
49
|
+
o = new URL(t);
|
|
39
50
|
} catch {
|
|
40
|
-
throw new
|
|
51
|
+
throw new n("invalid_config", `baseUrl is not a valid URL: ${t}`);
|
|
41
52
|
}
|
|
42
|
-
let s =
|
|
43
|
-
if (
|
|
53
|
+
let s = o.protocol, i = pe(o.hostname);
|
|
54
|
+
if (fe())
|
|
44
55
|
return typeof console < "u" && console.warn(
|
|
45
56
|
`[neetru-sdk] NEETRU_ALLOW_INSECURE_BASEURL=1 ativo. baseUrl=${t} aceito sem valida\xE7\xE3o.`
|
|
46
57
|
), t.replace(/\/+$/, "");
|
|
47
58
|
if (s !== "https:" && s !== "http:")
|
|
48
|
-
throw new
|
|
59
|
+
throw new n(
|
|
49
60
|
"invalid_config",
|
|
50
61
|
`baseUrl protocol must be http: or https:, got ${s}`
|
|
51
62
|
);
|
|
52
63
|
if (s === "http:") {
|
|
53
|
-
if (!(
|
|
54
|
-
throw new
|
|
64
|
+
if (!(B.has(i) || j(i)))
|
|
65
|
+
throw new n(
|
|
55
66
|
"invalid_config",
|
|
56
|
-
`baseUrl with http: only allowed for localhost/127.0.0.1/*.test/*.localhost. Got: ${
|
|
67
|
+
`baseUrl with http: only allowed for localhost/127.0.0.1/*.test/*.localhost. Got: ${i}. Use https: or set NEETRU_ALLOW_INSECURE_BASEURL=1 to bypass.`
|
|
57
68
|
);
|
|
58
69
|
return t.replace(/\/+$/, "");
|
|
59
70
|
}
|
|
60
|
-
let
|
|
61
|
-
let
|
|
62
|
-
return
|
|
63
|
-
}),
|
|
64
|
-
if (!
|
|
65
|
-
throw new
|
|
71
|
+
let p = i === ue || i.endsWith(le), m = e.some((h) => {
|
|
72
|
+
let w = h.toLowerCase();
|
|
73
|
+
return i === w || i.endsWith(`.${w}`);
|
|
74
|
+
}), I = B.has(i) || j(i);
|
|
75
|
+
if (!p && !m && !I)
|
|
76
|
+
throw new n(
|
|
66
77
|
"invalid_config",
|
|
67
|
-
`baseUrl ${
|
|
78
|
+
`baseUrl ${i} is not in the allowlist. Allowed: *.neetru.com, localhost, or configure { allowedHosts: ['...'] }. Bypass: NEETRU_ALLOW_INSECURE_BASEURL=1.`
|
|
68
79
|
);
|
|
69
80
|
return t.replace(/\/+$/, "");
|
|
70
81
|
}
|
|
71
|
-
function
|
|
82
|
+
function fe() {
|
|
72
83
|
try {
|
|
73
84
|
let e = globalThis.process?.env?.NEETRU_ALLOW_INSECURE_BASEURL;
|
|
74
85
|
if (e === "1" || e === "true") return !0;
|
|
@@ -83,16 +94,16 @@ function Z() {
|
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
// src/api-key.ts
|
|
86
|
-
var
|
|
87
|
-
function
|
|
97
|
+
var ge = /^nrt_([A-Za-z0-9]+)_([A-Za-z0-9]+)$/;
|
|
98
|
+
function z(t) {
|
|
88
99
|
if (typeof t != "string" || t.length === 0)
|
|
89
|
-
throw new
|
|
100
|
+
throw new n(
|
|
90
101
|
"invalid_config",
|
|
91
102
|
"apiKey is required (formato nrt_<keyId>_<secret>)"
|
|
92
103
|
);
|
|
93
|
-
let e =
|
|
104
|
+
let e = ge.exec(t);
|
|
94
105
|
if (!e)
|
|
95
|
-
throw new
|
|
106
|
+
throw new n(
|
|
96
107
|
"invalid_config",
|
|
97
108
|
"apiKey malformado - esperado formato nrt_<keyId>_<secret>"
|
|
98
109
|
);
|
|
@@ -100,57 +111,57 @@ function K(t) {
|
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
// src/auth-pkce-shared.ts
|
|
103
|
-
function
|
|
114
|
+
function V() {
|
|
104
115
|
let t = globalThis.crypto;
|
|
105
116
|
if (!t || typeof t.getRandomValues != "function" || !t.subtle)
|
|
106
|
-
throw new
|
|
117
|
+
throw new n(
|
|
107
118
|
"runtime_unsupported",
|
|
108
119
|
"auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno, ou instale um polyfill WebCrypto (ex: react-native-quick-crypto) em React Native."
|
|
109
120
|
);
|
|
110
121
|
return t;
|
|
111
122
|
}
|
|
112
|
-
function
|
|
123
|
+
function W(t) {
|
|
113
124
|
let e = "";
|
|
114
125
|
for (let s of t) e += String.fromCharCode(s);
|
|
115
126
|
return (typeof btoa == "function" ? btoa(e) : Buffer.from(e, "binary").toString("base64")).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
116
127
|
}
|
|
117
|
-
function
|
|
118
|
-
let
|
|
119
|
-
return t.getRandomValues(
|
|
128
|
+
function x(t, e) {
|
|
129
|
+
let o = new Uint8Array(e);
|
|
130
|
+
return t.getRandomValues(o), W(o);
|
|
120
131
|
}
|
|
121
|
-
async function
|
|
122
|
-
let
|
|
123
|
-
return
|
|
132
|
+
async function J(t, e) {
|
|
133
|
+
let o = new TextEncoder().encode(e), s = await t.subtle.digest("SHA-256", o);
|
|
134
|
+
return W(new Uint8Array(s));
|
|
124
135
|
}
|
|
125
|
-
function
|
|
136
|
+
function S(t) {
|
|
126
137
|
return (typeof globalThis.NEETRU_AUTH_URL == "string" ? globalThis.NEETRU_AUTH_URL : null) ?? t.replace(/^https?:\/\/api\./, "https://auth.");
|
|
127
138
|
}
|
|
128
|
-
function
|
|
139
|
+
function L(t) {
|
|
129
140
|
let e = t.oidcClientId;
|
|
130
|
-
if (!e && t.apiKey && (e =
|
|
131
|
-
throw new
|
|
141
|
+
if (!e && t.apiKey && (e = z(t.apiKey).keyId), !e)
|
|
142
|
+
throw new n(
|
|
132
143
|
"invalid_config",
|
|
133
144
|
"auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
|
|
134
145
|
);
|
|
135
146
|
return e;
|
|
136
147
|
}
|
|
137
|
-
function
|
|
148
|
+
function G(t) {
|
|
138
149
|
let e = new URL("/api/v1/oauth/authorize", t.idpOrigin);
|
|
139
150
|
return e.searchParams.set("response_type", "code"), e.searchParams.set("client_id", t.clientId), e.searchParams.set("redirect_uri", t.redirectUri), e.searchParams.set("scope", t.scope), e.searchParams.set("state", t.state), e.searchParams.set("nonce", t.nonce), e.searchParams.set("code_challenge", t.codeChallenge), e.searchParams.set("code_challenge_method", "S256"), e;
|
|
140
151
|
}
|
|
141
|
-
var
|
|
142
|
-
function
|
|
152
|
+
var X = "/api/v1/oauth/token";
|
|
153
|
+
function O(t) {
|
|
143
154
|
let e = t.split(".");
|
|
144
155
|
if (e.length !== 3) return null;
|
|
145
156
|
try {
|
|
146
|
-
let
|
|
147
|
-
return JSON.parse(
|
|
157
|
+
let o = e[1].replace(/-/g, "+").replace(/_/g, "/"), s = "=".repeat((4 - o.length % 4) % 4), i = typeof atob == "function" ? atob(o + s) : Buffer.from(o + s, "base64").toString("utf-8");
|
|
158
|
+
return JSON.parse(i);
|
|
148
159
|
} catch {
|
|
149
160
|
return null;
|
|
150
161
|
}
|
|
151
162
|
}
|
|
152
|
-
function
|
|
153
|
-
let e =
|
|
163
|
+
function T(t) {
|
|
164
|
+
let e = O(t);
|
|
154
165
|
return !e || typeof e.sub != "string" || typeof e.exp == "number" && e.exp * 1e3 < Date.now() ? null : {
|
|
155
166
|
uid: e.sub,
|
|
156
167
|
email: typeof e.email == "string" ? e.email : "",
|
|
@@ -163,249 +174,457 @@ function _(t) {
|
|
|
163
174
|
...e
|
|
164
175
|
};
|
|
165
176
|
}
|
|
177
|
+
var me = "/api/v1/oauth/revoke";
|
|
178
|
+
async function Y(t, e, o, s) {
|
|
179
|
+
let i = `${e}${me}`, p = true;
|
|
180
|
+
for (let m of s) {
|
|
181
|
+
if (!m.token) continue;
|
|
182
|
+
let I = new URLSearchParams({
|
|
183
|
+
token: m.token,
|
|
184
|
+
token_type_hint: m.hint,
|
|
185
|
+
client_id: o
|
|
186
|
+
}).toString(), h = false;
|
|
187
|
+
for (let w = 0; w < 2 && !h; w++)
|
|
188
|
+
try {
|
|
189
|
+
if (h = (await t(i, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
192
|
+
body: I
|
|
193
|
+
})).ok, !h) break;
|
|
194
|
+
} catch {
|
|
195
|
+
w === 0 && await new Promise((_) => setTimeout(_, 500));
|
|
196
|
+
}
|
|
197
|
+
h || (p = false);
|
|
198
|
+
}
|
|
199
|
+
return p;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/server-only-key.ts
|
|
203
|
+
function Z(t) {
|
|
204
|
+
if (!(t == null || t === ""))
|
|
205
|
+
throw new n(
|
|
206
|
+
"server_only_key",
|
|
207
|
+
"[Neetru SDK] Recusado: @neetru/sdk/mobile n\xE3o aceita apiKey. A credencial nrt_ do produto \xE9 S\xD3 DE SERVIDOR \u2014 dentro do app ela \xE9 extra\xEDvel do pacote (.apk/.ipa). Remova a apiKey (e qualquer EXPO_PUBLIC_*_KEY com ela) do app: fa\xE7a login com oidcClientId (client OIDC p\xFAblico do app) e chame a API do seu produto com o access_token do usu\xE1rio; o backend do produto usa o SDK com a chave.",
|
|
208
|
+
void 0,
|
|
209
|
+
void 0,
|
|
210
|
+
"react-native"
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/correlation.ts
|
|
215
|
+
var Q = "x-correlation-id";
|
|
216
|
+
var he = /^[A-Za-z0-9._:\-]+$/;
|
|
217
|
+
function ee(t) {
|
|
218
|
+
return typeof t == "string" && t.length > 0 && t.length <= 128 && he.test(t);
|
|
219
|
+
}
|
|
220
|
+
function ye() {
|
|
221
|
+
let t = globalThis.crypto;
|
|
222
|
+
try {
|
|
223
|
+
if (t && typeof t.randomUUID == "function") return t.randomUUID();
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
let e = new Uint8Array(16), o = false;
|
|
227
|
+
try {
|
|
228
|
+
t && typeof t.getRandomValues == "function" && (t.getRandomValues(e), o = !0);
|
|
229
|
+
} catch {
|
|
230
|
+
o = false;
|
|
231
|
+
}
|
|
232
|
+
if (!o)
|
|
233
|
+
for (let i = 0; i < e.length; i++) e[i] = Math.floor(Math.random() * 256);
|
|
234
|
+
e[6] = e[6] & 15 | 64, e[8] = e[8] & 63 | 128;
|
|
235
|
+
let s = Array.from(e, (i) => i.toString(16).padStart(2, "0")).join("");
|
|
236
|
+
return `${s.slice(0, 8)}-${s.slice(8, 12)}-${s.slice(12, 16)}-${s.slice(16, 20)}-${s.slice(20)}`;
|
|
237
|
+
}
|
|
238
|
+
function K(t, e) {
|
|
239
|
+
let o, s = {};
|
|
240
|
+
for (let [p, m] of Object.entries(t)) {
|
|
241
|
+
if (p.toLowerCase() === Q) {
|
|
242
|
+
ee(m) && (o = m);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
s[p] = m;
|
|
246
|
+
}
|
|
247
|
+
let i = o ?? (ee(e) ? e : void 0) ?? ye();
|
|
248
|
+
return s[Q] = i, { headers: s, correlationId: i };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/http.ts
|
|
252
|
+
function te(t) {
|
|
253
|
+
return t === 401 ? "unauthorized" : t === 403 ? "forbidden" : t === 404 ? "not_found" : t === 409 ? "conflict" : t === 410 ? "gone" : t === 422 || t === 400 ? "validation_failed" : t === 429 ? "rate_limited" : t >= 500 ? "server_error" : "unknown";
|
|
254
|
+
}
|
|
166
255
|
|
|
167
256
|
// src/mobile.ts
|
|
168
|
-
var
|
|
169
|
-
function
|
|
170
|
-
if (
|
|
171
|
-
|
|
257
|
+
var k = "neetru_oauth_tx", U = "neetru_id_token", E = "neetru_refresh_token", C = "neetru_access_token", be = 3e4, we = "/api/v1/oauth/userinfo";
|
|
258
|
+
function _e(t) {
|
|
259
|
+
if (t === void 0 || t === "") return null;
|
|
260
|
+
let e;
|
|
261
|
+
try {
|
|
262
|
+
e = new URL(t);
|
|
263
|
+
} catch {
|
|
264
|
+
throw new n("invalid_config", `productApiUrl inv\xE1lida: ${t}`);
|
|
265
|
+
}
|
|
266
|
+
let o = e.hostname === "localhost" || e.hostname === "127.0.0.1";
|
|
267
|
+
if (e.protocol !== "https:" && !(e.protocol === "http:" && o))
|
|
268
|
+
throw new n(
|
|
269
|
+
"invalid_config",
|
|
270
|
+
"productApiUrl precisa ser https:// (http s\xF3 para localhost) \u2014 o access_token n\xE3o pode trafegar sem TLS."
|
|
271
|
+
);
|
|
272
|
+
return e;
|
|
273
|
+
}
|
|
274
|
+
function ke(t) {
|
|
275
|
+
if (Z(t.apiKey), !t.storage)
|
|
276
|
+
throw new n(
|
|
172
277
|
"invalid_config",
|
|
173
278
|
"createMobileAuthNamespace requer `storage` (MobileAuthStorage) \u2014 ver JSDoc de src/mobile.ts requisito 4."
|
|
174
279
|
);
|
|
175
280
|
if (typeof t.openAuthUrl != "function")
|
|
176
|
-
throw new
|
|
281
|
+
throw new n(
|
|
177
282
|
"invalid_config",
|
|
178
283
|
"createMobileAuthNamespace requer `openAuthUrl` (browser externo, NUNCA WebView embutida) \u2014 ver JSDoc de src/mobile.ts requisito 3."
|
|
179
284
|
);
|
|
180
285
|
let e = t.fetch ?? globalThis.fetch;
|
|
181
286
|
if (typeof e != "function")
|
|
182
|
-
throw new
|
|
287
|
+
throw new n(
|
|
183
288
|
"invalid_config",
|
|
184
289
|
"fetch is not available in this runtime. Pass `fetch` explicitly to createMobileAuthNamespace."
|
|
185
290
|
);
|
|
186
|
-
|
|
291
|
+
if (typeof t.oidcClientId != "string" || t.oidcClientId.length === 0)
|
|
292
|
+
throw new n(
|
|
293
|
+
"invalid_config",
|
|
294
|
+
"createMobileAuthNamespace requer `oidcClientId` \u2014 o client OIDC P\xDABLICO do app registrado no Core (a apiKey n\xE3o \xE9 aceita no app; ver requisito 6 no JSDoc de src/mobile.ts)."
|
|
295
|
+
);
|
|
296
|
+
let o = F(t.baseUrl ?? H, t.allowedHosts ?? []);
|
|
187
297
|
return {
|
|
188
298
|
fetchImpl: e.bind(globalThis),
|
|
189
|
-
baseUrl:
|
|
299
|
+
baseUrl: o,
|
|
190
300
|
oidcClientId: t.oidcClientId,
|
|
191
|
-
|
|
301
|
+
productApiUrl: _e(t.productApiUrl),
|
|
192
302
|
storage: t.storage,
|
|
193
303
|
openAuthUrl: t.openAuthUrl
|
|
194
304
|
};
|
|
195
305
|
}
|
|
196
|
-
|
|
306
|
+
function ve(t) {
|
|
307
|
+
let o = O(t)?.exp;
|
|
308
|
+
return typeof o == "number" ? o * 1e3 : null;
|
|
309
|
+
}
|
|
310
|
+
async function re(t, e, o) {
|
|
197
311
|
let s;
|
|
198
312
|
try {
|
|
199
313
|
s = await t(e, {
|
|
200
314
|
method: "POST",
|
|
201
315
|
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
202
|
-
body:
|
|
316
|
+
body: o.toString()
|
|
203
317
|
});
|
|
204
|
-
} catch (
|
|
205
|
-
throw new
|
|
318
|
+
} catch (p) {
|
|
319
|
+
throw new n(
|
|
206
320
|
"network_error",
|
|
207
|
-
`POST ${e} falhou (network): ${
|
|
321
|
+
`POST ${e} falhou (network): ${p?.message ?? String(p)}`
|
|
208
322
|
);
|
|
209
323
|
}
|
|
210
|
-
let
|
|
324
|
+
let i = null;
|
|
211
325
|
try {
|
|
212
|
-
|
|
326
|
+
i = await s.json();
|
|
213
327
|
} catch {
|
|
214
|
-
|
|
328
|
+
i = null;
|
|
215
329
|
}
|
|
216
|
-
if (!s.ok || typeof
|
|
217
|
-
let
|
|
218
|
-
throw new
|
|
330
|
+
if (!s.ok || typeof i?.error == "string") {
|
|
331
|
+
let p = typeof i?.error_description == "string" && i.error_description || typeof i?.error == "string" && i.error || `HTTP ${s.status}`;
|
|
332
|
+
throw new n(
|
|
219
333
|
"token_exchange_failed",
|
|
220
|
-
`Troca de tokens falhou no /token: ${
|
|
334
|
+
`Troca de tokens falhou no /token: ${p}`,
|
|
221
335
|
s.status
|
|
222
336
|
);
|
|
223
337
|
}
|
|
224
|
-
return
|
|
338
|
+
return i ?? {};
|
|
225
339
|
}
|
|
226
|
-
function
|
|
227
|
-
let e =
|
|
340
|
+
function je(t) {
|
|
341
|
+
let e = ke(t), o = /* @__PURE__ */ new Set();
|
|
228
342
|
function s() {
|
|
229
|
-
return `${
|
|
343
|
+
return `${S(e.baseUrl)}${X}`;
|
|
230
344
|
}
|
|
231
|
-
async function
|
|
232
|
-
let
|
|
233
|
-
for (let a of
|
|
345
|
+
async function i() {
|
|
346
|
+
let r = await h();
|
|
347
|
+
for (let a of o)
|
|
234
348
|
try {
|
|
235
|
-
a(
|
|
349
|
+
a(r);
|
|
236
350
|
} catch {
|
|
237
351
|
}
|
|
238
352
|
}
|
|
239
|
-
async function
|
|
240
|
-
if (!
|
|
241
|
-
throw new
|
|
353
|
+
async function p(r) {
|
|
354
|
+
if (!r?.redirectUri)
|
|
355
|
+
throw new n(
|
|
242
356
|
"invalid_config",
|
|
243
357
|
"mobile auth.signIn requer `redirectUri` (Universal Link/App Link https://... registrado no Core) \u2014 n\xE3o h\xE1 location.origin impl\xEDcito em React Native."
|
|
244
358
|
);
|
|
245
|
-
let a =
|
|
359
|
+
let a = V(), c = r.scope ?? "openid profile email", l = L(e), d = x(a, 16), u = x(a, 16), f = x(a, 32), g = await J(a, f), y = {
|
|
246
360
|
state: d,
|
|
247
|
-
nonce:
|
|
248
|
-
codeVerifier:
|
|
249
|
-
redirectUri:
|
|
250
|
-
postLoginRedirect:
|
|
361
|
+
nonce: u,
|
|
362
|
+
codeVerifier: f,
|
|
363
|
+
redirectUri: r.redirectUri,
|
|
364
|
+
postLoginRedirect: r.postLoginRedirect
|
|
251
365
|
};
|
|
252
|
-
await e.storage.setItem(
|
|
253
|
-
let
|
|
254
|
-
idpOrigin:
|
|
255
|
-
clientId:
|
|
256
|
-
redirectUri:
|
|
257
|
-
scope:
|
|
366
|
+
await e.storage.setItem(k, JSON.stringify(y));
|
|
367
|
+
let b = S(e.baseUrl), R = G({
|
|
368
|
+
idpOrigin: b,
|
|
369
|
+
clientId: l,
|
|
370
|
+
redirectUri: r.redirectUri,
|
|
371
|
+
scope: c,
|
|
258
372
|
state: d,
|
|
259
|
-
nonce:
|
|
260
|
-
codeChallenge:
|
|
373
|
+
nonce: u,
|
|
374
|
+
codeChallenge: g
|
|
261
375
|
});
|
|
262
|
-
await e.openAuthUrl(
|
|
376
|
+
await e.openAuthUrl(R.toString());
|
|
263
377
|
}
|
|
264
|
-
async function
|
|
265
|
-
if (!
|
|
266
|
-
throw new
|
|
378
|
+
async function m(r) {
|
|
379
|
+
if (!r || typeof r != "string")
|
|
380
|
+
throw new n(
|
|
267
381
|
"invalid_config",
|
|
268
382
|
"mobile auth.completeSignIn requer `callbackUrl` (a URL completa do deep link de retorno) \u2014 mobile n\xE3o tem location.href impl\xEDcito."
|
|
269
383
|
);
|
|
270
384
|
let a;
|
|
271
385
|
try {
|
|
272
|
-
a = new URL(
|
|
386
|
+
a = new URL(r);
|
|
273
387
|
} catch {
|
|
274
|
-
throw new
|
|
388
|
+
throw new n("invalid_config", `callbackUrl n\xE3o \xE9 uma URL v\xE1lida: ${r}`);
|
|
275
389
|
}
|
|
276
|
-
let
|
|
277
|
-
if (
|
|
278
|
-
let
|
|
279
|
-
throw await e.storage.removeItem(
|
|
390
|
+
let c = a.searchParams, l = c.get("error");
|
|
391
|
+
if (l) {
|
|
392
|
+
let ce = c.get("error_description") ?? l;
|
|
393
|
+
throw await e.storage.removeItem(k), new n(l, `OIDC authorize falhou: ${ce}`);
|
|
280
394
|
}
|
|
281
|
-
let d =
|
|
395
|
+
let d = c.get("code");
|
|
282
396
|
if (!d)
|
|
283
|
-
throw await e.storage.removeItem(
|
|
397
|
+
throw await e.storage.removeItem(k), new n(
|
|
284
398
|
"invalid_config",
|
|
285
399
|
"callbackUrl n\xE3o cont\xE9m `?code=` nem `?error=` \u2014 n\xE3o \xE9 um callback OIDC v\xE1lido."
|
|
286
400
|
);
|
|
287
|
-
let
|
|
288
|
-
if (
|
|
401
|
+
let u = c.get("state"), f = await e.storage.getItem(k), g = null;
|
|
402
|
+
if (f)
|
|
289
403
|
try {
|
|
290
|
-
|
|
404
|
+
g = JSON.parse(f);
|
|
291
405
|
} catch {
|
|
292
|
-
|
|
406
|
+
g = null;
|
|
293
407
|
}
|
|
294
|
-
if (!
|
|
295
|
-
throw new
|
|
408
|
+
if (!g)
|
|
409
|
+
throw new n(
|
|
296
410
|
"oidc_state_mismatch",
|
|
297
411
|
"Callback OIDC sem transa\xE7\xE3o pendente \u2014 `signIn` n\xE3o foi iniciado (ou j\xE1 consumido)."
|
|
298
412
|
);
|
|
299
|
-
if (!
|
|
300
|
-
throw await e.storage.removeItem(
|
|
413
|
+
if (!u || u !== g.state)
|
|
414
|
+
throw await e.storage.removeItem(k), new n(
|
|
301
415
|
"oidc_state_mismatch",
|
|
302
416
|
"state do callback OIDC n\xE3o confere com o da transa\xE7\xE3o (poss\xEDvel CSRF)."
|
|
303
417
|
);
|
|
304
|
-
await e.storage.removeItem(
|
|
305
|
-
let
|
|
418
|
+
await e.storage.removeItem(k);
|
|
419
|
+
let y = L(e), b = new URLSearchParams({
|
|
306
420
|
grant_type: "authorization_code",
|
|
307
421
|
code: d,
|
|
308
|
-
redirect_uri:
|
|
309
|
-
client_id:
|
|
310
|
-
code_verifier:
|
|
311
|
-
}),
|
|
312
|
-
if (typeof
|
|
313
|
-
throw new
|
|
422
|
+
redirect_uri: g.redirectUri,
|
|
423
|
+
client_id: y,
|
|
424
|
+
code_verifier: g.codeVerifier
|
|
425
|
+
}), R = await re(e.fetchImpl, s(), b), A = R.id_token;
|
|
426
|
+
if (typeof A != "string" || A.length === 0)
|
|
427
|
+
throw new n(
|
|
314
428
|
"token_exchange_failed",
|
|
315
429
|
"Resposta do /token sem `id_token` \u2014 o login n\xE3o pode ser completado."
|
|
316
430
|
);
|
|
317
|
-
let
|
|
318
|
-
if (
|
|
319
|
-
throw new
|
|
431
|
+
let $ = O(A);
|
|
432
|
+
if (!$)
|
|
433
|
+
throw new n(
|
|
320
434
|
"token_exchange_failed",
|
|
321
435
|
"id_token retornado pelo /token \xE9 malformado (payload indecodific\xE1vel)."
|
|
322
436
|
);
|
|
323
|
-
if (
|
|
324
|
-
throw new
|
|
437
|
+
if ($.nonce !== g.nonce)
|
|
438
|
+
throw new n(
|
|
325
439
|
"oidc_nonce_mismatch",
|
|
326
440
|
"nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
|
|
327
441
|
);
|
|
328
|
-
let
|
|
329
|
-
if (!
|
|
330
|
-
throw new
|
|
442
|
+
let q = T(A);
|
|
443
|
+
if (!q)
|
|
444
|
+
throw new n(
|
|
331
445
|
"token_exchange_failed",
|
|
332
446
|
"id_token retornado pelo /token n\xE3o tem `sub` ou j\xE1 est\xE1 expirado."
|
|
333
447
|
);
|
|
334
|
-
await e.storage.setItem(
|
|
335
|
-
let
|
|
336
|
-
return typeof
|
|
448
|
+
await e.storage.setItem(U, A);
|
|
449
|
+
let M = R.refresh_token;
|
|
450
|
+
return typeof M == "string" && M.length > 0 && await e.storage.setItem(E, M), await w(R.access_token), await i(), { user: q, postLoginRedirect: g.postLoginRedirect };
|
|
451
|
+
}
|
|
452
|
+
async function I() {
|
|
453
|
+
let r = await e.storage.getItem(U);
|
|
454
|
+
return r && T(r) ? r : null;
|
|
337
455
|
}
|
|
338
|
-
async function
|
|
339
|
-
let
|
|
340
|
-
return
|
|
456
|
+
async function h() {
|
|
457
|
+
let r = await e.storage.getItem(U);
|
|
458
|
+
return r ? T(r) : null;
|
|
341
459
|
}
|
|
342
|
-
async function
|
|
343
|
-
|
|
344
|
-
return n ? _(n) : null;
|
|
460
|
+
async function w(r) {
|
|
461
|
+
typeof r == "string" && r.length > 0 ? await e.storage.setItem(C, r) : await e.storage.removeItem(C);
|
|
345
462
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
463
|
+
let _ = null;
|
|
464
|
+
function N() {
|
|
465
|
+
return _ || (_ = ne().finally(() => {
|
|
466
|
+
_ = null;
|
|
467
|
+
}), _);
|
|
468
|
+
}
|
|
469
|
+
async function ne() {
|
|
470
|
+
let r = await e.storage.getItem(E);
|
|
471
|
+
if (!r) return false;
|
|
349
472
|
let a;
|
|
350
473
|
try {
|
|
351
|
-
a =
|
|
474
|
+
a = L(e);
|
|
352
475
|
} catch {
|
|
353
476
|
return false;
|
|
354
477
|
}
|
|
355
|
-
let
|
|
478
|
+
let c = new URLSearchParams({
|
|
356
479
|
grant_type: "refresh_token",
|
|
357
|
-
refresh_token:
|
|
480
|
+
refresh_token: r,
|
|
358
481
|
client_id: a
|
|
359
|
-
}),
|
|
482
|
+
}), l;
|
|
360
483
|
try {
|
|
361
|
-
|
|
484
|
+
l = await re(e.fetchImpl, s(), c);
|
|
362
485
|
} catch {
|
|
363
486
|
return false;
|
|
364
487
|
}
|
|
365
|
-
let d =
|
|
366
|
-
if (typeof d != "string" || d.length === 0 || !
|
|
367
|
-
await e.storage.setItem(
|
|
368
|
-
let
|
|
369
|
-
return typeof
|
|
488
|
+
let d = l.id_token;
|
|
489
|
+
if (typeof d != "string" || d.length === 0 || !T(d)) return false;
|
|
490
|
+
await e.storage.setItem(U, d);
|
|
491
|
+
let f = l.refresh_token;
|
|
492
|
+
return typeof f == "string" && f.length > 0 && await e.storage.setItem(E, f), await w(l.access_token), await i(), true;
|
|
493
|
+
}
|
|
494
|
+
async function P() {
|
|
495
|
+
let r = await e.storage.getItem(C);
|
|
496
|
+
if (!r) return null;
|
|
497
|
+
let a = ve(r);
|
|
498
|
+
return a === null || a - be <= Date.now() ? null : r;
|
|
370
499
|
}
|
|
371
|
-
async function
|
|
372
|
-
let
|
|
373
|
-
|
|
374
|
-
|
|
500
|
+
async function D() {
|
|
501
|
+
let r = await P();
|
|
502
|
+
return r || (await N() ? P() : null);
|
|
503
|
+
}
|
|
504
|
+
async function oe() {
|
|
505
|
+
let r = `${S(e.baseUrl)}${we}`, a = async (f) => {
|
|
506
|
+
let { headers: g, correlationId: y } = K({
|
|
507
|
+
accept: "application/json",
|
|
508
|
+
authorization: `Bearer ${f}`
|
|
509
|
+
});
|
|
375
510
|
try {
|
|
376
|
-
await e.fetchImpl(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
511
|
+
return { res: await e.fetchImpl(r, { method: "GET", headers: g }), correlationId: y };
|
|
512
|
+
} catch (b) {
|
|
513
|
+
throw new n(
|
|
514
|
+
"network_error",
|
|
515
|
+
`GET ${r} falhou (network): ${b?.message ?? String(b)}`,
|
|
516
|
+
void 0,
|
|
517
|
+
void 0,
|
|
518
|
+
void 0,
|
|
519
|
+
y
|
|
385
520
|
);
|
|
386
521
|
}
|
|
522
|
+
}, c = await D();
|
|
523
|
+
if (!c)
|
|
524
|
+
throw new v(
|
|
525
|
+
"Sem sess\xE3o: fa\xE7a login (auth.signIn) antes de consultar o userinfo.",
|
|
526
|
+
"no_signed_in_user"
|
|
527
|
+
);
|
|
528
|
+
let { res: l, correlationId: d } = await a(c);
|
|
529
|
+
if (l.status === 401 && await N() && (c = await P(), c && ({ res: l, correlationId: d } = await a(c))), l.status === 401)
|
|
530
|
+
throw new v(
|
|
531
|
+
"O Core recusou a sess\xE3o (token revogado/expirado ou usu\xE1rio inativo). Fa\xE7a login novamente.",
|
|
532
|
+
"invalid_access_token",
|
|
533
|
+
401,
|
|
534
|
+
void 0,
|
|
535
|
+
d
|
|
536
|
+
);
|
|
537
|
+
let u;
|
|
538
|
+
try {
|
|
539
|
+
u = await l.json();
|
|
540
|
+
} catch {
|
|
541
|
+
u = void 0;
|
|
542
|
+
}
|
|
543
|
+
if (!l.ok) {
|
|
544
|
+
let f = u && typeof u == "object" && typeof u.error_description == "string" ? u.error_description : `HTTP ${l.status}`;
|
|
545
|
+
throw new n(te(l.status), `userinfo falhou: ${f}`, l.status, void 0, void 0, d);
|
|
546
|
+
}
|
|
547
|
+
if (!u || typeof u != "object" || typeof u.sub != "string")
|
|
548
|
+
throw new n("invalid_response", "userinfo sem `sub`.", l.status, void 0, void 0, d);
|
|
549
|
+
return u;
|
|
550
|
+
}
|
|
551
|
+
function ie(r) {
|
|
552
|
+
let a = e.productApiUrl;
|
|
553
|
+
if (!a)
|
|
554
|
+
throw new n(
|
|
555
|
+
"invalid_config",
|
|
556
|
+
"auth.authFetch requer `productApiUrl` (URL da API do seu produto) no createMobileAuthNamespace."
|
|
557
|
+
);
|
|
558
|
+
let c;
|
|
559
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(r))
|
|
560
|
+
try {
|
|
561
|
+
c = new URL(r);
|
|
562
|
+
} catch {
|
|
563
|
+
throw new n("invalid_config", `URL inv\xE1lida: ${r}`);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
let l = a.pathname.replace(/\/+$/, ""), d = r.startsWith("/") ? r : `/${r}`;
|
|
567
|
+
c = new URL(`${a.origin}${l}${d}`);
|
|
387
568
|
}
|
|
388
|
-
|
|
569
|
+
if (c.origin !== a.origin)
|
|
570
|
+
throw new n(
|
|
571
|
+
"invalid_config",
|
|
572
|
+
`auth.authFetch s\xF3 envia o access_token para a API do produto (${a.origin}); recusado: ${c.origin}.`
|
|
573
|
+
);
|
|
574
|
+
return c.toString();
|
|
575
|
+
}
|
|
576
|
+
async function se(r, a = {}) {
|
|
577
|
+
let c = ie(r), l = {};
|
|
578
|
+
new Headers(a.headers ?? {}).forEach((y, b) => {
|
|
579
|
+
l[b] = y;
|
|
580
|
+
});
|
|
581
|
+
let d = (y) => {
|
|
582
|
+
let { headers: b } = K({ ...l, authorization: `Bearer ${y}` });
|
|
583
|
+
return e.fetchImpl(c, { ...a, headers: b });
|
|
584
|
+
}, u = await D();
|
|
585
|
+
if (!u)
|
|
586
|
+
throw new v(
|
|
587
|
+
"Sem sess\xE3o: fa\xE7a login (auth.signIn) antes de chamar a API do produto.",
|
|
588
|
+
"no_signed_in_user"
|
|
589
|
+
);
|
|
590
|
+
let f = await d(u), g = a.body === void 0 || a.body === null || typeof a.body == "string";
|
|
591
|
+
return f.status === 401 && g && await N() && (u = await P(), u && (f = await d(u))), f;
|
|
592
|
+
}
|
|
593
|
+
async function ae() {
|
|
594
|
+
let r = await e.storage.getItem(E), a = await e.storage.getItem(C);
|
|
595
|
+
await e.storage.removeItem(U), await e.storage.removeItem(E), await e.storage.removeItem(C), await e.storage.removeItem(k);
|
|
596
|
+
let c = [];
|
|
597
|
+
r && c.push({ token: r, hint: "refresh_token" }), a && c.push({ token: a, hint: "access_token" }), c.length > 0 && !await Y(
|
|
598
|
+
e.fetchImpl,
|
|
599
|
+
S(e.baseUrl),
|
|
600
|
+
e.oidcClientId,
|
|
601
|
+
c
|
|
602
|
+
) && typeof console < "u" && console.warn(
|
|
603
|
+
"[neetru-sdk] mobile signOut: a revoga\xE7\xE3o no servidor n\xE3o foi confirmada. A sess\xE3o local foi encerrada, mas o refresh_token pode seguir v\xE1lido at\xE9 expirar."
|
|
604
|
+
), await i();
|
|
389
605
|
}
|
|
390
606
|
return {
|
|
391
|
-
signIn:
|
|
392
|
-
completeSignIn:
|
|
393
|
-
getIdToken:
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
607
|
+
signIn: p,
|
|
608
|
+
completeSignIn: m,
|
|
609
|
+
getIdToken: I,
|
|
610
|
+
getAccessToken: D,
|
|
611
|
+
getUserInfo: oe,
|
|
612
|
+
authFetch: se,
|
|
613
|
+
getUser: h,
|
|
614
|
+
onAuthStateChanged(r) {
|
|
615
|
+
return o.add(r), h().then((a) => {
|
|
616
|
+
if (o.has(r))
|
|
398
617
|
try {
|
|
399
|
-
|
|
618
|
+
r(a);
|
|
400
619
|
} catch {
|
|
401
620
|
}
|
|
402
621
|
}), () => {
|
|
403
|
-
|
|
622
|
+
o.delete(r);
|
|
404
623
|
};
|
|
405
624
|
},
|
|
406
|
-
refreshTokens:
|
|
407
|
-
signOut:
|
|
625
|
+
refreshTokens: N,
|
|
626
|
+
signOut: ae
|
|
408
627
|
};
|
|
409
628
|
}
|
|
410
629
|
|
|
411
|
-
exports.createMobileAuthNamespace =
|
|
630
|
+
exports.createMobileAuthNamespace = je;
|