@neetru/sdk 3.5.0 → 3.7.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/dist/ai.cjs +254 -391
  3. package/dist/ai.d.cts +1 -1
  4. package/dist/ai.d.ts +1 -1
  5. package/dist/ai.mjs +254 -391
  6. package/dist/auth.cjs +3560 -4993
  7. package/dist/auth.d.cts +1 -1
  8. package/dist/auth.d.ts +1 -1
  9. package/dist/auth.mjs +3557 -4990
  10. package/dist/build-guard.cjs +101 -119
  11. package/dist/build-guard.mjs +91 -109
  12. package/dist/catalog.cjs +152 -224
  13. package/dist/catalog.d.cts +1 -1
  14. package/dist/catalog.d.ts +1 -1
  15. package/dist/catalog.mjs +152 -224
  16. package/dist/checkout.cjs +237 -320
  17. package/dist/checkout.d.cts +1 -1
  18. package/dist/checkout.d.ts +1 -1
  19. package/dist/checkout.mjs +236 -319
  20. package/dist/db-react.cjs +59 -87
  21. package/dist/db-react.d.cts +1 -1
  22. package/dist/db-react.d.ts +1 -1
  23. package/dist/db-react.mjs +56 -84
  24. package/dist/db.cjs +2055 -3013
  25. package/dist/db.d.cts +1 -1
  26. package/dist/db.d.ts +1 -1
  27. package/dist/db.mjs +2068 -3026
  28. package/dist/entitlements.cjs +12 -20
  29. package/dist/entitlements.d.cts +1 -1
  30. package/dist/entitlements.d.ts +1 -1
  31. package/dist/entitlements.mjs +12 -20
  32. package/dist/errors.cjs +9 -12
  33. package/dist/errors.d.cts +37 -2
  34. package/dist/errors.d.ts +37 -2
  35. package/dist/errors.mjs +8 -12
  36. package/dist/firestore-compat.cjs +241 -297
  37. package/dist/firestore-compat.d.cts +1 -1
  38. package/dist/firestore-compat.d.ts +1 -1
  39. package/dist/firestore-compat.mjs +215 -271
  40. package/dist/index.cjs +3627 -5135
  41. package/dist/index.d.cts +6 -4
  42. package/dist/index.d.ts +6 -4
  43. package/dist/index.mjs +3731 -5239
  44. package/dist/mobile.cjs +411 -0
  45. package/dist/mobile.d.cts +89 -0
  46. package/dist/mobile.d.ts +89 -0
  47. package/dist/mobile.mjs +409 -0
  48. package/dist/mocks.cjs +312 -447
  49. package/dist/mocks.d.cts +1 -1
  50. package/dist/mocks.d.ts +1 -1
  51. package/dist/mocks.mjs +306 -441
  52. package/dist/notifications.cjs +226 -314
  53. package/dist/notifications.d.cts +1 -1
  54. package/dist/notifications.d.ts +1 -1
  55. package/dist/notifications.mjs +225 -313
  56. package/dist/react.cjs +522 -693
  57. package/dist/react.d.cts +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.mjs +512 -683
  60. package/dist/support.cjs +329 -325
  61. package/dist/support.d.cts +25 -3
  62. package/dist/support.d.ts +25 -3
  63. package/dist/support.mjs +328 -325
  64. package/dist/telemetry.cjs +197 -301
  65. package/dist/telemetry.d.cts +1 -1
  66. package/dist/telemetry.d.ts +1 -1
  67. package/dist/telemetry.mjs +197 -301
  68. package/dist/{types-Du_iioJ7.d.cts → types-Bx4kTLmk.d.cts} +26 -0
  69. package/dist/{types-BPATkXYu.d.ts → types-Dx0IrOSF.d.ts} +26 -0
  70. package/dist/usage.cjs +163 -227
  71. package/dist/usage.d.cts +1 -1
  72. package/dist/usage.d.ts +1 -1
  73. package/dist/usage.mjs +163 -227
  74. package/dist/webhooks.cjs +258 -359
  75. package/dist/webhooks.d.cts +1 -1
  76. package/dist/webhooks.d.ts +1 -1
  77. package/dist/webhooks.mjs +255 -356
  78. package/package.json +9 -3
  79. package/dist/ai.cjs.map +0 -1
  80. package/dist/ai.mjs.map +0 -1
  81. package/dist/auth.cjs.map +0 -1
  82. package/dist/auth.mjs.map +0 -1
  83. package/dist/build-guard.cjs.map +0 -1
  84. package/dist/build-guard.mjs.map +0 -1
  85. package/dist/catalog.cjs.map +0 -1
  86. package/dist/catalog.mjs.map +0 -1
  87. package/dist/checkout.cjs.map +0 -1
  88. package/dist/checkout.mjs.map +0 -1
  89. package/dist/db-react.cjs.map +0 -1
  90. package/dist/db-react.mjs.map +0 -1
  91. package/dist/db.cjs.map +0 -1
  92. package/dist/db.mjs.map +0 -1
  93. package/dist/entitlements.cjs.map +0 -1
  94. package/dist/entitlements.mjs.map +0 -1
  95. package/dist/errors.cjs.map +0 -1
  96. package/dist/errors.mjs.map +0 -1
  97. package/dist/firestore-compat.cjs.map +0 -1
  98. package/dist/firestore-compat.mjs.map +0 -1
  99. package/dist/index.cjs.map +0 -1
  100. package/dist/index.mjs.map +0 -1
  101. package/dist/mocks.cjs.map +0 -1
  102. package/dist/mocks.mjs.map +0 -1
  103. package/dist/notifications.cjs.map +0 -1
  104. package/dist/notifications.mjs.map +0 -1
  105. package/dist/react.cjs.map +0 -1
  106. package/dist/react.mjs.map +0 -1
  107. package/dist/support.cjs.map +0 -1
  108. package/dist/support.mjs.map +0 -1
  109. package/dist/telemetry.cjs.map +0 -1
  110. package/dist/telemetry.mjs.map +0 -1
  111. package/dist/usage.cjs.map +0 -1
  112. package/dist/usage.mjs.map +0 -1
  113. package/dist/webhooks.cjs.map +0 -1
  114. package/dist/webhooks.mjs.map +0 -1
@@ -0,0 +1,411 @@
1
+ 'use strict';
2
+
3
+ // src/errors.ts
4
+ var r = class t extends Error {
5
+ code;
6
+ status;
7
+ requestId;
8
+ /**
9
+ * Motivo semântico opcional propagado pelo Core no corpo do erro (campo
10
+ * `reason` no TOPO do body, fora de `error`). Usado principalmente pelo 503
11
+ * de lease de DB, onde `reason` discrimina o estado do ambiente
12
+ * (`suspended` | `archived` | `revoked` | `provisioning` | `degraded` |
13
+ * `no_route` | `expired`). Camadas superiores (ex.: `db/sql`) mapeiam isso
14
+ * para um `NeetruDbErrorCode` mais específico (recuperável vs não).
15
+ */
16
+ reason;
17
+ constructor(e, i, s, o, l) {
18
+ super(i), this.name = "NeetruError", this.code = e, this.status = s, this.requestId = o, this.reason = l, Object.setPrototypeOf(this, t.prototype);
19
+ }
20
+ };
21
+
22
+ // src/types.ts
23
+ var L = "https://api.neetru.com";
24
+
25
+ // src/base-url-allowlist.ts
26
+ var O = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]), F = ".neetru.com", J = "neetru.com", Y = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?\.(test|localhost)$/;
27
+ function D(t) {
28
+ return Y.test(t);
29
+ }
30
+ function X(t) {
31
+ return t.toLowerCase().replace(/\.+$/, "");
32
+ }
33
+ function M(t, e = []) {
34
+ if (typeof t != "string" || t.length === 0)
35
+ throw new r("invalid_config", "baseUrl is required");
36
+ let i;
37
+ try {
38
+ i = new URL(t);
39
+ } catch {
40
+ throw new r("invalid_config", `baseUrl is not a valid URL: ${t}`);
41
+ }
42
+ let s = i.protocol, o = X(i.hostname);
43
+ if (Z())
44
+ return typeof console < "u" && console.warn(
45
+ `[neetru-sdk] NEETRU_ALLOW_INSECURE_BASEURL=1 ativo. baseUrl=${t} aceito sem valida\xE7\xE3o.`
46
+ ), t.replace(/\/+$/, "");
47
+ if (s !== "https:" && s !== "http:")
48
+ throw new r(
49
+ "invalid_config",
50
+ `baseUrl protocol must be http: or https:, got ${s}`
51
+ );
52
+ if (s === "http:") {
53
+ if (!(O.has(o) || D(o)))
54
+ throw new r(
55
+ "invalid_config",
56
+ `baseUrl with http: only allowed for localhost/127.0.0.1/*.test/*.localhost. Got: ${o}. Use https: or set NEETRU_ALLOW_INSECURE_BASEURL=1 to bypass.`
57
+ );
58
+ return t.replace(/\/+$/, "");
59
+ }
60
+ let l = o === J || o.endsWith(F), A = e.some((m) => {
61
+ let k = m.toLowerCase();
62
+ return o === k || o.endsWith(`.${k}`);
63
+ }), R = O.has(o) || D(o);
64
+ if (!l && !A && !R)
65
+ throw new r(
66
+ "invalid_config",
67
+ `baseUrl ${o} is not in the allowlist. Allowed: *.neetru.com, localhost, or configure { allowedHosts: ['...'] }. Bypass: NEETRU_ALLOW_INSECURE_BASEURL=1.`
68
+ );
69
+ return t.replace(/\/+$/, "");
70
+ }
71
+ function Z() {
72
+ try {
73
+ let e = globalThis.process?.env?.NEETRU_ALLOW_INSECURE_BASEURL;
74
+ if (e === "1" || e === "true") return !0;
75
+ } catch {
76
+ }
77
+ try {
78
+ let t = globalThis.NEETRU_ALLOW_INSECURE_BASEURL;
79
+ if (t === "1" || t === "true" || t === !0) return !0;
80
+ } catch {
81
+ }
82
+ return false;
83
+ }
84
+
85
+ // src/api-key.ts
86
+ var G = /^nrt_([A-Za-z0-9]+)_([A-Za-z0-9]+)$/;
87
+ function K(t) {
88
+ if (typeof t != "string" || t.length === 0)
89
+ throw new r(
90
+ "invalid_config",
91
+ "apiKey is required (formato nrt_<keyId>_<secret>)"
92
+ );
93
+ let e = G.exec(t);
94
+ if (!e)
95
+ throw new r(
96
+ "invalid_config",
97
+ "apiKey malformado - esperado formato nrt_<keyId>_<secret>"
98
+ );
99
+ return { keyId: e[1], secret: e[2] };
100
+ }
101
+
102
+ // src/auth-pkce-shared.ts
103
+ function H() {
104
+ let t = globalThis.crypto;
105
+ if (!t || typeof t.getRandomValues != "function" || !t.subtle)
106
+ throw new r(
107
+ "runtime_unsupported",
108
+ "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
+ );
110
+ return t;
111
+ }
112
+ function $(t) {
113
+ let e = "";
114
+ for (let s of t) e += String.fromCharCode(s);
115
+ return (typeof btoa == "function" ? btoa(e) : Buffer.from(e, "binary").toString("base64")).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
116
+ }
117
+ function v(t, e) {
118
+ let i = new Uint8Array(e);
119
+ return t.getRandomValues(i), $(i);
120
+ }
121
+ async function B(t, e) {
122
+ let i = new TextEncoder().encode(e), s = await t.subtle.digest("SHA-256", i);
123
+ return $(new Uint8Array(s));
124
+ }
125
+ function U(t) {
126
+ return (typeof globalThis.NEETRU_AUTH_URL == "string" ? globalThis.NEETRU_AUTH_URL : null) ?? t.replace(/^https?:\/\/api\./, "https://auth.");
127
+ }
128
+ function I(t) {
129
+ let e = t.oidcClientId;
130
+ if (!e && t.apiKey && (e = K(t.apiKey).keyId), !e)
131
+ throw new r(
132
+ "invalid_config",
133
+ "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
134
+ );
135
+ return e;
136
+ }
137
+ function q(t) {
138
+ let e = new URL("/api/v1/oauth/authorize", t.idpOrigin);
139
+ 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
+ }
141
+ var W = "/api/v1/oauth/token";
142
+ function N(t) {
143
+ let e = t.split(".");
144
+ if (e.length !== 3) return null;
145
+ try {
146
+ let i = e[1].replace(/-/g, "+").replace(/_/g, "/"), s = "=".repeat((4 - i.length % 4) % 4), o = typeof atob == "function" ? atob(i + s) : Buffer.from(i + s, "base64").toString("utf-8");
147
+ return JSON.parse(o);
148
+ } catch {
149
+ return null;
150
+ }
151
+ }
152
+ function _(t) {
153
+ let e = N(t);
154
+ return !e || typeof e.sub != "string" || typeof e.exp == "number" && e.exp * 1e3 < Date.now() ? null : {
155
+ uid: e.sub,
156
+ email: typeof e.email == "string" ? e.email : "",
157
+ emailVerified: typeof e.email_verified == "boolean" ? e.email_verified : void 0,
158
+ displayName: typeof e.name == "string" ? e.name : void 0,
159
+ photoURL: typeof e.picture == "string" ? e.picture : void 0,
160
+ isStaff: e.is_staff === true,
161
+ isCustomer: e.is_customer === true,
162
+ tenantId: typeof e.tenant_id == "string" ? e.tenant_id : void 0,
163
+ ...e
164
+ };
165
+ }
166
+
167
+ // src/mobile.ts
168
+ var h = "neetru_oauth_tx", y = "neetru_id_token", S = "neetru_refresh_token";
169
+ function Q(t) {
170
+ if (!t.storage)
171
+ throw new r(
172
+ "invalid_config",
173
+ "createMobileAuthNamespace requer `storage` (MobileAuthStorage) \u2014 ver JSDoc de src/mobile.ts requisito 4."
174
+ );
175
+ if (typeof t.openAuthUrl != "function")
176
+ throw new r(
177
+ "invalid_config",
178
+ "createMobileAuthNamespace requer `openAuthUrl` (browser externo, NUNCA WebView embutida) \u2014 ver JSDoc de src/mobile.ts requisito 3."
179
+ );
180
+ let e = t.fetch ?? globalThis.fetch;
181
+ if (typeof e != "function")
182
+ throw new r(
183
+ "invalid_config",
184
+ "fetch is not available in this runtime. Pass `fetch` explicitly to createMobileAuthNamespace."
185
+ );
186
+ let i = M(t.baseUrl ?? L, t.allowedHosts ?? []);
187
+ return {
188
+ fetchImpl: e.bind(globalThis),
189
+ baseUrl: i,
190
+ oidcClientId: t.oidcClientId,
191
+ apiKey: t.apiKey,
192
+ storage: t.storage,
193
+ openAuthUrl: t.openAuthUrl
194
+ };
195
+ }
196
+ async function z(t, e, i) {
197
+ let s;
198
+ try {
199
+ s = await t(e, {
200
+ method: "POST",
201
+ headers: { "content-type": "application/x-www-form-urlencoded" },
202
+ body: i.toString()
203
+ });
204
+ } catch (l) {
205
+ throw new r(
206
+ "network_error",
207
+ `POST ${e} falhou (network): ${l?.message ?? String(l)}`
208
+ );
209
+ }
210
+ let o = null;
211
+ try {
212
+ o = await s.json();
213
+ } catch {
214
+ o = null;
215
+ }
216
+ if (!s.ok || typeof o?.error == "string") {
217
+ let l = typeof o?.error_description == "string" && o.error_description || typeof o?.error == "string" && o.error || `HTTP ${s.status}`;
218
+ throw new r(
219
+ "token_exchange_failed",
220
+ `Troca de tokens falhou no /token: ${l}`,
221
+ s.status
222
+ );
223
+ }
224
+ return o ?? {};
225
+ }
226
+ function ge(t) {
227
+ let e = Q(t), i = /* @__PURE__ */ new Set();
228
+ function s() {
229
+ return `${U(e.baseUrl)}${W}`;
230
+ }
231
+ async function o() {
232
+ let n = await m();
233
+ for (let a of i)
234
+ try {
235
+ a(n);
236
+ } catch {
237
+ }
238
+ }
239
+ async function l(n) {
240
+ if (!n?.redirectUri)
241
+ throw new r(
242
+ "invalid_config",
243
+ "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
+ );
245
+ let a = H(), u = n.scope ?? "openid profile email", c = I(e), d = v(a, 16), f = v(a, 16), g = v(a, 32), p = await B(a, g), T = {
246
+ state: d,
247
+ nonce: f,
248
+ codeVerifier: g,
249
+ redirectUri: n.redirectUri,
250
+ postLoginRedirect: n.postLoginRedirect
251
+ };
252
+ await e.storage.setItem(h, JSON.stringify(T));
253
+ let C = U(e.baseUrl), w = q({
254
+ idpOrigin: C,
255
+ clientId: c,
256
+ redirectUri: n.redirectUri,
257
+ scope: u,
258
+ state: d,
259
+ nonce: f,
260
+ codeChallenge: p
261
+ });
262
+ await e.openAuthUrl(w.toString());
263
+ }
264
+ async function A(n) {
265
+ if (!n || typeof n != "string")
266
+ throw new r(
267
+ "invalid_config",
268
+ "mobile auth.completeSignIn requer `callbackUrl` (a URL completa do deep link de retorno) \u2014 mobile n\xE3o tem location.href impl\xEDcito."
269
+ );
270
+ let a;
271
+ try {
272
+ a = new URL(n);
273
+ } catch {
274
+ throw new r("invalid_config", `callbackUrl n\xE3o \xE9 uma URL v\xE1lida: ${n}`);
275
+ }
276
+ let u = a.searchParams, c = u.get("error");
277
+ if (c) {
278
+ let j = u.get("error_description") ?? c;
279
+ throw await e.storage.removeItem(h), new r(c, `OIDC authorize falhou: ${j}`);
280
+ }
281
+ let d = u.get("code");
282
+ if (!d)
283
+ throw await e.storage.removeItem(h), new r(
284
+ "invalid_config",
285
+ "callbackUrl n\xE3o cont\xE9m `?code=` nem `?error=` \u2014 n\xE3o \xE9 um callback OIDC v\xE1lido."
286
+ );
287
+ let f = u.get("state"), g = await e.storage.getItem(h), p = null;
288
+ if (g)
289
+ try {
290
+ p = JSON.parse(g);
291
+ } catch {
292
+ p = null;
293
+ }
294
+ if (!p)
295
+ throw new r(
296
+ "oidc_state_mismatch",
297
+ "Callback OIDC sem transa\xE7\xE3o pendente \u2014 `signIn` n\xE3o foi iniciado (ou j\xE1 consumido)."
298
+ );
299
+ if (!f || f !== p.state)
300
+ throw await e.storage.removeItem(h), new r(
301
+ "oidc_state_mismatch",
302
+ "state do callback OIDC n\xE3o confere com o da transa\xE7\xE3o (poss\xEDvel CSRF)."
303
+ );
304
+ await e.storage.removeItem(h);
305
+ let T = I(e), C = new URLSearchParams({
306
+ grant_type: "authorization_code",
307
+ code: d,
308
+ redirect_uri: p.redirectUri,
309
+ client_id: T,
310
+ code_verifier: p.codeVerifier
311
+ }), w = await z(e.fetchImpl, s(), C), b = w.id_token;
312
+ if (typeof b != "string" || b.length === 0)
313
+ throw new r(
314
+ "token_exchange_failed",
315
+ "Resposta do /token sem `id_token` \u2014 o login n\xE3o pode ser completado."
316
+ );
317
+ let x = N(b);
318
+ if (!x)
319
+ throw new r(
320
+ "token_exchange_failed",
321
+ "id_token retornado pelo /token \xE9 malformado (payload indecodific\xE1vel)."
322
+ );
323
+ if (x.nonce !== p.nonce)
324
+ throw new r(
325
+ "oidc_nonce_mismatch",
326
+ "nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
327
+ );
328
+ let E = _(b);
329
+ if (!E)
330
+ throw new r(
331
+ "token_exchange_failed",
332
+ "id_token retornado pelo /token n\xE3o tem `sub` ou j\xE1 est\xE1 expirado."
333
+ );
334
+ await e.storage.setItem(y, b);
335
+ let P = w.refresh_token;
336
+ return typeof P == "string" && P.length > 0 && await e.storage.setItem(S, P), await o(), { user: E, postLoginRedirect: p.postLoginRedirect };
337
+ }
338
+ async function R() {
339
+ let n = await e.storage.getItem(y);
340
+ return n && _(n) ? n : null;
341
+ }
342
+ async function m() {
343
+ let n = await e.storage.getItem(y);
344
+ return n ? _(n) : null;
345
+ }
346
+ async function k() {
347
+ let n = await e.storage.getItem(S);
348
+ if (!n) return false;
349
+ let a;
350
+ try {
351
+ a = I(e);
352
+ } catch {
353
+ return false;
354
+ }
355
+ let u = new URLSearchParams({
356
+ grant_type: "refresh_token",
357
+ refresh_token: n,
358
+ client_id: a
359
+ }), c;
360
+ try {
361
+ c = await z(e.fetchImpl, s(), u);
362
+ } catch {
363
+ return false;
364
+ }
365
+ let d = c.id_token;
366
+ if (typeof d != "string" || d.length === 0 || !_(d)) return false;
367
+ await e.storage.setItem(y, d);
368
+ let g = c.refresh_token;
369
+ return typeof g == "string" && g.length > 0 && await e.storage.setItem(S, g), await o(), true;
370
+ }
371
+ async function V() {
372
+ let n = await e.storage.getItem(y);
373
+ if (await e.storage.removeItem(y), await e.storage.removeItem(S), n) {
374
+ let u = `${U(e.baseUrl)}/api/v1/oauth/revoke`;
375
+ try {
376
+ await e.fetchImpl(u, {
377
+ method: "POST",
378
+ headers: { "content-type": "application/json" },
379
+ body: JSON.stringify({ token: n })
380
+ });
381
+ } catch (c) {
382
+ typeof console < "u" && console.warn(
383
+ "[neetru-sdk] mobile signOut: server-side revoke falhou. Refresh token pode estar stale.",
384
+ c
385
+ );
386
+ }
387
+ }
388
+ await o();
389
+ }
390
+ return {
391
+ signIn: l,
392
+ completeSignIn: A,
393
+ getIdToken: R,
394
+ getUser: m,
395
+ onAuthStateChanged(n) {
396
+ return i.add(n), m().then((a) => {
397
+ if (i.has(n))
398
+ try {
399
+ n(a);
400
+ } catch {
401
+ }
402
+ }), () => {
403
+ i.delete(n);
404
+ };
405
+ },
406
+ refreshTokens: k,
407
+ signOut: V
408
+ };
409
+ }
410
+
411
+ exports.createMobileAuthNamespace = ge;
@@ -0,0 +1,89 @@
1
+ import { X as NeetruClientConfig, v as CompleteSignInResult, a5 as NeetruUser, m as AuthStateListener } from './types-Bx4kTLmk.cjs';
2
+ import 'drizzle-orm/node-postgres';
3
+ import './errors.cjs';
4
+
5
+ /**
6
+ * Storage assíncrono chave-valor que o app RN injeta — ex: um wrapper fino
7
+ * sobre `expo-secure-store` ou `@react-native-async-storage/async-storage`.
8
+ * O SDK não assume NENHUMA implementação concreta.
9
+ */
10
+ interface MobileAuthStorage {
11
+ getItem(key: string): Promise<string | null>;
12
+ setItem(key: string, value: string): Promise<void>;
13
+ removeItem(key: string): Promise<void>;
14
+ }
15
+ interface MobileAuthConfig extends NeetruClientConfig {
16
+ /** Storage persistente (idealmente seguro) — ver requisito 4 no JSDoc do módulo. */
17
+ storage: MobileAuthStorage;
18
+ /**
19
+ * Abre a URL de authorize num browser EXTERNO (nunca WebView embutida) —
20
+ * ver requisito 3 no JSDoc do módulo. Ex: `WebBrowser.openAuthSessionAsync`
21
+ * (expo-web-browser) ou `Linking.openURL`.
22
+ */
23
+ openAuthUrl: (url: string) => Promise<void>;
24
+ }
25
+ interface MobileSignInOptions {
26
+ /**
27
+ * Universal Link / App Link (`https://...`) registrado como `redirect_uri`
28
+ * do OIDC client mobile no Core. Obrigatório — diferente do namespace web,
29
+ * não há `location.origin` implícito pra usar como default.
30
+ */
31
+ redirectUri: string;
32
+ /** OIDC scope. Default `openid profile email`. */
33
+ scope?: string;
34
+ /** Destino pós-login que o app decide interpretar após `completeSignIn`. */
35
+ postLoginRedirect?: string;
36
+ }
37
+ interface MobileAuthNamespace {
38
+ /**
39
+ * Inicia o fluxo OIDC Authorization Code + PKCE: gera `state`/`nonce`/
40
+ * `code_verifier`/`code_challenge` (S256), persiste a transação via
41
+ * `config.storage`, e chama `config.openAuthUrl(url)` — NUNCA navega
42
+ * sozinho (sem `location` em RN).
43
+ *
44
+ * @throws {NeetruError} `runtime_unsupported` se `crypto.subtle` ausente.
45
+ */
46
+ signIn(options: MobileSignInOptions): Promise<void>;
47
+ /**
48
+ * Completa o login: recebe a URL COMPLETA do deep link de retorno (o app
49
+ * lê via `Linking.getInitialURL()` / listener `Linking.addEventListener`)
50
+ * e troca o `code` pelos tokens no mesmo `/api/v1/oauth/token` que o
51
+ * namespace web usa (POST x-www-form-urlencoded, PKCE puro, sem
52
+ * client_secret). Valida `state` (CSRF) e `nonce` (anti-replay), grava os
53
+ * tokens em `config.storage` e notifica `onAuthStateChanged`.
54
+ *
55
+ * `callbackUrl` é OBRIGATÓRIO — mobile não tem `location.href` implícito.
56
+ *
57
+ * @throws {NeetruError} `oidc_state_mismatch`, `oidc_nonce_mismatch`,
58
+ * `token_exchange_failed`, `network_error`, ou `invalid_config` se a URL
59
+ * não é um callback OIDC válido (sem `?code=`/`?error=`) ou não há
60
+ * transação pendente no storage.
61
+ */
62
+ completeSignIn(callbackUrl: string): Promise<CompleteSignInResult>;
63
+ /** `id_token` cru armazenado, ou `null` se ausente/expirado. */
64
+ getIdToken(): Promise<string | null>;
65
+ /** Usuário atual (claims do `id_token` armazenado), ou `null`. */
66
+ getUser(): Promise<NeetruUser | null>;
67
+ /**
68
+ * Subscreve a mudanças de estado de auth. Diferente do namespace web, o
69
+ * listener inicial é disparado de forma ASSÍNCRONA (a leitura do storage
70
+ * injetado é sempre `Promise`) — não confie em ordem síncrona de chamada.
71
+ * Retorna função de unsubscribe (síncrona).
72
+ */
73
+ onAuthStateChanged(listener: AuthStateListener): () => void;
74
+ /**
75
+ * Renova os tokens via `grant_type=refresh_token`, se houver refresh_token
76
+ * armazenado. `true` se renovou; `false` em qualquer falha (sem refresh
77
+ * token, `invalid_grant`, rede) — não lança.
78
+ */
79
+ refreshTokens(): Promise<boolean>;
80
+ /** Limpa a sessão local (storage) + melhor esforço de revoke no servidor. */
81
+ signOut(): Promise<void>;
82
+ }
83
+ /**
84
+ * Cria o namespace de auth mobile. Ver JSDoc do módulo pros requisitos do
85
+ * app consumidor (polyfill WebCrypto, browser externo, storage seguro).
86
+ */
87
+ declare function createMobileAuthNamespace(config: MobileAuthConfig): MobileAuthNamespace;
88
+
89
+ export { type MobileAuthConfig, type MobileAuthNamespace, type MobileAuthStorage, type MobileSignInOptions, createMobileAuthNamespace };
@@ -0,0 +1,89 @@
1
+ import { X as NeetruClientConfig, v as CompleteSignInResult, a5 as NeetruUser, m as AuthStateListener } from './types-Dx0IrOSF.js';
2
+ import 'drizzle-orm/node-postgres';
3
+ import './errors.js';
4
+
5
+ /**
6
+ * Storage assíncrono chave-valor que o app RN injeta — ex: um wrapper fino
7
+ * sobre `expo-secure-store` ou `@react-native-async-storage/async-storage`.
8
+ * O SDK não assume NENHUMA implementação concreta.
9
+ */
10
+ interface MobileAuthStorage {
11
+ getItem(key: string): Promise<string | null>;
12
+ setItem(key: string, value: string): Promise<void>;
13
+ removeItem(key: string): Promise<void>;
14
+ }
15
+ interface MobileAuthConfig extends NeetruClientConfig {
16
+ /** Storage persistente (idealmente seguro) — ver requisito 4 no JSDoc do módulo. */
17
+ storage: MobileAuthStorage;
18
+ /**
19
+ * Abre a URL de authorize num browser EXTERNO (nunca WebView embutida) —
20
+ * ver requisito 3 no JSDoc do módulo. Ex: `WebBrowser.openAuthSessionAsync`
21
+ * (expo-web-browser) ou `Linking.openURL`.
22
+ */
23
+ openAuthUrl: (url: string) => Promise<void>;
24
+ }
25
+ interface MobileSignInOptions {
26
+ /**
27
+ * Universal Link / App Link (`https://...`) registrado como `redirect_uri`
28
+ * do OIDC client mobile no Core. Obrigatório — diferente do namespace web,
29
+ * não há `location.origin` implícito pra usar como default.
30
+ */
31
+ redirectUri: string;
32
+ /** OIDC scope. Default `openid profile email`. */
33
+ scope?: string;
34
+ /** Destino pós-login que o app decide interpretar após `completeSignIn`. */
35
+ postLoginRedirect?: string;
36
+ }
37
+ interface MobileAuthNamespace {
38
+ /**
39
+ * Inicia o fluxo OIDC Authorization Code + PKCE: gera `state`/`nonce`/
40
+ * `code_verifier`/`code_challenge` (S256), persiste a transação via
41
+ * `config.storage`, e chama `config.openAuthUrl(url)` — NUNCA navega
42
+ * sozinho (sem `location` em RN).
43
+ *
44
+ * @throws {NeetruError} `runtime_unsupported` se `crypto.subtle` ausente.
45
+ */
46
+ signIn(options: MobileSignInOptions): Promise<void>;
47
+ /**
48
+ * Completa o login: recebe a URL COMPLETA do deep link de retorno (o app
49
+ * lê via `Linking.getInitialURL()` / listener `Linking.addEventListener`)
50
+ * e troca o `code` pelos tokens no mesmo `/api/v1/oauth/token` que o
51
+ * namespace web usa (POST x-www-form-urlencoded, PKCE puro, sem
52
+ * client_secret). Valida `state` (CSRF) e `nonce` (anti-replay), grava os
53
+ * tokens em `config.storage` e notifica `onAuthStateChanged`.
54
+ *
55
+ * `callbackUrl` é OBRIGATÓRIO — mobile não tem `location.href` implícito.
56
+ *
57
+ * @throws {NeetruError} `oidc_state_mismatch`, `oidc_nonce_mismatch`,
58
+ * `token_exchange_failed`, `network_error`, ou `invalid_config` se a URL
59
+ * não é um callback OIDC válido (sem `?code=`/`?error=`) ou não há
60
+ * transação pendente no storage.
61
+ */
62
+ completeSignIn(callbackUrl: string): Promise<CompleteSignInResult>;
63
+ /** `id_token` cru armazenado, ou `null` se ausente/expirado. */
64
+ getIdToken(): Promise<string | null>;
65
+ /** Usuário atual (claims do `id_token` armazenado), ou `null`. */
66
+ getUser(): Promise<NeetruUser | null>;
67
+ /**
68
+ * Subscreve a mudanças de estado de auth. Diferente do namespace web, o
69
+ * listener inicial é disparado de forma ASSÍNCRONA (a leitura do storage
70
+ * injetado é sempre `Promise`) — não confie em ordem síncrona de chamada.
71
+ * Retorna função de unsubscribe (síncrona).
72
+ */
73
+ onAuthStateChanged(listener: AuthStateListener): () => void;
74
+ /**
75
+ * Renova os tokens via `grant_type=refresh_token`, se houver refresh_token
76
+ * armazenado. `true` se renovou; `false` em qualquer falha (sem refresh
77
+ * token, `invalid_grant`, rede) — não lança.
78
+ */
79
+ refreshTokens(): Promise<boolean>;
80
+ /** Limpa a sessão local (storage) + melhor esforço de revoke no servidor. */
81
+ signOut(): Promise<void>;
82
+ }
83
+ /**
84
+ * Cria o namespace de auth mobile. Ver JSDoc do módulo pros requisitos do
85
+ * app consumidor (polyfill WebCrypto, browser externo, storage seguro).
86
+ */
87
+ declare function createMobileAuthNamespace(config: MobileAuthConfig): MobileAuthNamespace;
88
+
89
+ export { type MobileAuthConfig, type MobileAuthNamespace, type MobileAuthStorage, type MobileSignInOptions, createMobileAuthNamespace };