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