@neetru/sdk 3.4.7 → 3.6.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 +45 -0
- package/dist/ai.cjs +17 -13
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/ai.mjs +17 -13
- package/dist/ai.mjs.map +1 -1
- package/dist/auth.cjs +159 -107
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +2 -2
- package/dist/auth.d.ts +2 -2
- package/dist/auth.mjs +159 -107
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs +19 -4
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs +19 -4
- package/dist/catalog.mjs.map +1 -1
- package/dist/checkout.cjs +11 -3
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +11 -3
- package/dist/checkout.mjs.map +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +17 -7
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +17 -7
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/index.cjs +160 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.mjs +160 -108
- package/dist/index.mjs.map +1 -1
- package/dist/mobile.cjs +515 -0
- package/dist/mobile.cjs.map +1 -0
- package/dist/mobile.d.cts +89 -0
- package/dist/mobile.d.ts +89 -0
- package/dist/mobile.mjs +513 -0
- package/dist/mobile.mjs.map +1 -0
- package/dist/mocks.cjs +17 -0
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +5 -1
- package/dist/mocks.d.ts +5 -1
- package/dist/mocks.mjs +17 -0
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs +11 -3
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs +11 -3
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.cjs +36 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +36 -2
- package/dist/react.mjs.map +1 -1
- package/dist/support.cjs +15 -4
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/support.mjs +15 -4
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs +11 -3
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs +11 -3
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-nnztVk7G.d.ts → types-BPATkXYu.d.ts} +35 -7
- package/dist/{types-DIVZl7nO.d.cts → types-Du_iioJ7.d.cts} +35 -7
- package/dist/usage.cjs +11 -3
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs +11 -3
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs +17 -4
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs +17 -4
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +9 -1
package/dist/auth.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X as NeetruClientConfig, W as NeetruClient } from './types-
|
|
1
|
+
import { X as NeetruClientConfig, W as NeetruClient } from './types-Du_iioJ7.cjs';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.cjs';
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ declare function __resetJwksCacheForTests(): void;
|
|
|
18
18
|
* const { products } = await client.catalog.list();
|
|
19
19
|
* const can = await client.entitlements.check('neetru-pulse', 'export-pdf');
|
|
20
20
|
* await client.telemetry.event({ name: 'report_exported' });
|
|
21
|
-
* await client.usage.
|
|
21
|
+
* await client.usage.report('api_call', 1);
|
|
22
22
|
* await client.support.createTicket({ subject: 'help', message: '...' });
|
|
23
23
|
* ```
|
|
24
24
|
*
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X as NeetruClientConfig, W as NeetruClient } from './types-
|
|
1
|
+
import { X as NeetruClientConfig, W as NeetruClient } from './types-BPATkXYu.js';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.js';
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ declare function __resetJwksCacheForTests(): void;
|
|
|
18
18
|
* const { products } = await client.catalog.list();
|
|
19
19
|
* const can = await client.entitlements.check('neetru-pulse', 'export-pdf');
|
|
20
20
|
* await client.telemetry.event({ name: 'report_exported' });
|
|
21
|
-
* await client.usage.
|
|
21
|
+
* await client.usage.report('api_call', 1);
|
|
22
22
|
* await client.support.createTicket({ subject: 'help', message: '...' });
|
|
23
23
|
* ```
|
|
24
24
|
*
|
package/dist/auth.mjs
CHANGED
|
@@ -62,7 +62,8 @@ var init_idempotency = __esm({
|
|
|
62
62
|
var http_exports = {};
|
|
63
63
|
__export(http_exports, {
|
|
64
64
|
checkCoreVersionCompat: () => checkCoreVersionCompat,
|
|
65
|
-
httpRequest: () => httpRequest
|
|
65
|
+
httpRequest: () => httpRequest,
|
|
66
|
+
statusToCode: () => statusToCode
|
|
66
67
|
});
|
|
67
68
|
function stripRevision(v) {
|
|
68
69
|
return v.split("+")[0] ?? v;
|
|
@@ -78,12 +79,16 @@ function compareCalVer(a, b) {
|
|
|
78
79
|
}
|
|
79
80
|
return 0;
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
+
function readInjectedSdkVersion() {
|
|
82
83
|
try {
|
|
83
|
-
|
|
84
|
-
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
84
|
+
return "3.6.0";
|
|
85
85
|
} catch {
|
|
86
|
+
return void 0;
|
|
86
87
|
}
|
|
88
|
+
}
|
|
89
|
+
function getSdkMajor() {
|
|
90
|
+
const ver = readInjectedSdkVersion();
|
|
91
|
+
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
87
92
|
return 3;
|
|
88
93
|
}
|
|
89
94
|
function checkCoreVersionCompat(coreVersion) {
|
|
@@ -161,6 +166,10 @@ async function httpRequest(config, opts) {
|
|
|
161
166
|
accept: "application/json",
|
|
162
167
|
...opts.headers
|
|
163
168
|
};
|
|
169
|
+
const sdkVersion = readInjectedSdkVersion();
|
|
170
|
+
if (sdkVersion) {
|
|
171
|
+
headers["x-neetru-sdk-version"] = sdkVersion;
|
|
172
|
+
}
|
|
164
173
|
if (opts.requireAuth) {
|
|
165
174
|
if (!config.apiKey) {
|
|
166
175
|
throw new NeetruError(
|
|
@@ -525,7 +534,7 @@ var init_lease = __esm({
|
|
|
525
534
|
void this._doRenew();
|
|
526
535
|
}, MIN_RENEWAL_DELAY_MS);
|
|
527
536
|
console.warn(
|
|
528
|
-
`[SqlLeaseManager] renova\xE7\xE3o E emiss\xE3o de lease novo falharam; re-tentando em ${MIN_RENEWAL_DELAY_MS}ms (cert
|
|
537
|
+
`[SqlLeaseManager] renova\xE7\xE3o E emiss\xE3o de lease novo falharam; re-tentando em ${MIN_RENEWAL_DELAY_MS}ms (cert TLS ef\xEAmero do servidor expira ~15min ap\xF3s o \xFAltimo swap):`,
|
|
529
538
|
err instanceof Error ? err.message : err
|
|
530
539
|
);
|
|
531
540
|
return;
|
|
@@ -536,8 +545,9 @@ var init_lease = __esm({
|
|
|
536
545
|
/**
|
|
537
546
|
* Recuperação REATIVA: chamado pelo wrapper resiliente (`resilient-pool.ts`)
|
|
538
547
|
* quando uma query plana falha num erro de ESTABELECIMENTO de conexão (cert
|
|
539
|
-
*
|
|
540
|
-
* disparou). Emite um lease NOVO e faz o swap do pool interno
|
|
548
|
+
* TLS efêmero do servidor expirado no meio de uma request, ou timer de
|
|
549
|
+
* renovação que não disparou). Emite um lease NOVO e faz o swap do pool interno
|
|
550
|
+
* do wrapper com
|
|
541
551
|
* o certificado fresco; o wrapper então re-tenta a query 1x no pool novo.
|
|
542
552
|
*
|
|
543
553
|
* Vai DIRETO ao lease novo (sem `leaseId`) — a conexão falhou porque o
|
|
@@ -1137,7 +1147,14 @@ function toProduct(raw) {
|
|
|
1137
1147
|
if (Array.isArray(r.plans)) {
|
|
1138
1148
|
product.plans = r.plans.filter(
|
|
1139
1149
|
(p) => typeof p === "object" && p !== null && typeof p.id === "string" && typeof p.name === "string"
|
|
1140
|
-
)
|
|
1150
|
+
).map((p) => {
|
|
1151
|
+
const plan = { id: p.id, name: p.name };
|
|
1152
|
+
if (typeof p.amountCents === "number") plan.amountCents = p.amountCents;
|
|
1153
|
+
if (Array.isArray(p.features) && p.features.every((f) => typeof f === "string")) {
|
|
1154
|
+
plan.features = p.features;
|
|
1155
|
+
}
|
|
1156
|
+
return plan;
|
|
1157
|
+
});
|
|
1141
1158
|
}
|
|
1142
1159
|
return product;
|
|
1143
1160
|
}
|
|
@@ -1717,7 +1734,10 @@ function createSupportNamespace(config) {
|
|
|
1717
1734
|
await httpRequest(config, {
|
|
1718
1735
|
method: "POST",
|
|
1719
1736
|
path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/satisfaction-attempt`,
|
|
1720
|
-
requireAuth: true
|
|
1737
|
+
requireAuth: true,
|
|
1738
|
+
// Incrementa satisfactionAttempts += 1 no Core — sem idempotencyKey,
|
|
1739
|
+
// um retry de rede infla o contador (mesmo padrão de createTicket acima).
|
|
1740
|
+
idempotencyKey: true
|
|
1721
1741
|
});
|
|
1722
1742
|
},
|
|
1723
1743
|
/**
|
|
@@ -5822,7 +5842,12 @@ function createWebhooksNamespace(config) {
|
|
|
5822
5842
|
events: input.events,
|
|
5823
5843
|
...input.secret ? { secret: input.secret } : {}
|
|
5824
5844
|
},
|
|
5825
|
-
requireAuth: true
|
|
5845
|
+
requireAuth: true,
|
|
5846
|
+
// Sem isso, um retry de rede (app-level; SDK default é 0 retries em
|
|
5847
|
+
// POST) podia registrar o MESMO webhook duas vezes → entrega
|
|
5848
|
+
// duplicada de todo evento futuro pro endpoint do cliente. Core
|
|
5849
|
+
// dedup TTL 24h (mesmo padrão de usage.report/support.createTicket).
|
|
5850
|
+
idempotencyKey: true
|
|
5826
5851
|
});
|
|
5827
5852
|
return toEndpoint(raw);
|
|
5828
5853
|
},
|
|
@@ -6375,16 +6400,6 @@ async function safeJson2(res) {
|
|
|
6375
6400
|
return void 0;
|
|
6376
6401
|
}
|
|
6377
6402
|
}
|
|
6378
|
-
function statusToCode2(status) {
|
|
6379
|
-
if (status === 401) return "unauthorized";
|
|
6380
|
-
if (status === 403) return "forbidden";
|
|
6381
|
-
if (status === 404) return "not_found";
|
|
6382
|
-
if (status === 409) return "conflict";
|
|
6383
|
-
if (status === 422 || status === 400) return "validation_failed";
|
|
6384
|
-
if (status === 429) return "rate_limited";
|
|
6385
|
-
if (status >= 500) return "server_error";
|
|
6386
|
-
return "unknown";
|
|
6387
|
-
}
|
|
6388
6403
|
function joinUrl(baseUrl, path) {
|
|
6389
6404
|
const base = baseUrl.replace(/\/+$/, "");
|
|
6390
6405
|
const p = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -6419,7 +6434,7 @@ async function aiFetch(config, body, signal, stream) {
|
|
|
6419
6434
|
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
6420
6435
|
if (!res.ok) {
|
|
6421
6436
|
const parsed = await safeJson2(res);
|
|
6422
|
-
let code =
|
|
6437
|
+
let code = statusToCode(res.status);
|
|
6423
6438
|
let message = `HTTP ${res.status}`;
|
|
6424
6439
|
if (parsed && typeof parsed === "object" && "error" in parsed) {
|
|
6425
6440
|
const errField = parsed.error;
|
|
@@ -6537,6 +6552,19 @@ function createAiNamespace(config) {
|
|
|
6537
6552
|
|
|
6538
6553
|
// src/mocks.ts
|
|
6539
6554
|
init_errors();
|
|
6555
|
+
|
|
6556
|
+
// src/runtime-env.ts
|
|
6557
|
+
function isProductionRuntime() {
|
|
6558
|
+
try {
|
|
6559
|
+
if (typeof process !== "undefined" && process.env) {
|
|
6560
|
+
return process.env.NODE_ENV === "production";
|
|
6561
|
+
}
|
|
6562
|
+
} catch {
|
|
6563
|
+
}
|
|
6564
|
+
return false;
|
|
6565
|
+
}
|
|
6566
|
+
|
|
6567
|
+
// src/mocks.ts
|
|
6540
6568
|
var DEV_FIXTURE_USER = Object.freeze({
|
|
6541
6569
|
uid: "dev-fixture-uid-0001",
|
|
6542
6570
|
email: "dev@neetru.local",
|
|
@@ -6553,6 +6581,12 @@ var MockAuth = class {
|
|
|
6553
6581
|
this._user = initialUser;
|
|
6554
6582
|
this._listeners = /* @__PURE__ */ new Set();
|
|
6555
6583
|
this._allowUnsignedDecode = options?.allowUnsignedDecode ?? false;
|
|
6584
|
+
if (this._allowUnsignedDecode && isProductionRuntime()) {
|
|
6585
|
+
throw new NeetruError(
|
|
6586
|
+
"invalid_config",
|
|
6587
|
+
"MockAuth com allowUnsignedDecode=true \xE9 PROIBIDO em produ\xE7\xE3o (NODE_ENV=production): decodificar JWT sem verificar assinatura \xE9 bypass de autentica\xE7\xE3o. Este modo existe exclusivamente para testes."
|
|
6588
|
+
);
|
|
6589
|
+
}
|
|
6556
6590
|
if (this._allowUnsignedDecode) {
|
|
6557
6591
|
const isTestEnv = typeof process !== "undefined" && (process.env?.NODE_ENV === "test" || process.env?.VITEST === "true" || process.env?.VITEST != null);
|
|
6558
6592
|
if (!isTestEnv && typeof console !== "undefined") {
|
|
@@ -6954,6 +6988,94 @@ var MockAi = class {
|
|
|
6954
6988
|
}
|
|
6955
6989
|
};
|
|
6956
6990
|
|
|
6991
|
+
// src/auth-pkce-shared.ts
|
|
6992
|
+
init_errors();
|
|
6993
|
+
function getWebCrypto() {
|
|
6994
|
+
const c = globalThis.crypto;
|
|
6995
|
+
if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
|
|
6996
|
+
throw new NeetruError(
|
|
6997
|
+
"runtime_unsupported",
|
|
6998
|
+
"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."
|
|
6999
|
+
);
|
|
7000
|
+
}
|
|
7001
|
+
return c;
|
|
7002
|
+
}
|
|
7003
|
+
function base64UrlFromBytes(bytes) {
|
|
7004
|
+
let str = "";
|
|
7005
|
+
for (const b of bytes) str += String.fromCharCode(b);
|
|
7006
|
+
const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
|
|
7007
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
7008
|
+
}
|
|
7009
|
+
function randomUrlSafe(crypto2, byteLen) {
|
|
7010
|
+
const bytes = new Uint8Array(byteLen);
|
|
7011
|
+
crypto2.getRandomValues(bytes);
|
|
7012
|
+
return base64UrlFromBytes(bytes);
|
|
7013
|
+
}
|
|
7014
|
+
async function pkceChallengeS256(crypto2, verifier) {
|
|
7015
|
+
const data = new TextEncoder().encode(verifier);
|
|
7016
|
+
const digest = await crypto2.subtle.digest("SHA-256", data);
|
|
7017
|
+
return base64UrlFromBytes(new Uint8Array(digest));
|
|
7018
|
+
}
|
|
7019
|
+
function resolveIdpOrigin(baseUrl) {
|
|
7020
|
+
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
7021
|
+
return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
7022
|
+
}
|
|
7023
|
+
function resolveOidcClientId(config) {
|
|
7024
|
+
let clientId = config.oidcClientId;
|
|
7025
|
+
if (!clientId && config.apiKey) {
|
|
7026
|
+
clientId = parseApiKey(config.apiKey).keyId;
|
|
7027
|
+
}
|
|
7028
|
+
if (!clientId) {
|
|
7029
|
+
throw new NeetruError(
|
|
7030
|
+
"invalid_config",
|
|
7031
|
+
"auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
|
|
7032
|
+
);
|
|
7033
|
+
}
|
|
7034
|
+
return clientId;
|
|
7035
|
+
}
|
|
7036
|
+
function buildAuthorizeUrl(params) {
|
|
7037
|
+
const url = new URL("/api/v1/oauth/authorize", params.idpOrigin);
|
|
7038
|
+
url.searchParams.set("response_type", "code");
|
|
7039
|
+
url.searchParams.set("client_id", params.clientId);
|
|
7040
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
7041
|
+
url.searchParams.set("scope", params.scope);
|
|
7042
|
+
url.searchParams.set("state", params.state);
|
|
7043
|
+
url.searchParams.set("nonce", params.nonce);
|
|
7044
|
+
url.searchParams.set("code_challenge", params.codeChallenge);
|
|
7045
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
7046
|
+
return url;
|
|
7047
|
+
}
|
|
7048
|
+
function decodeJwtPayload(token) {
|
|
7049
|
+
const parts = token.split(".");
|
|
7050
|
+
if (parts.length !== 3) return null;
|
|
7051
|
+
try {
|
|
7052
|
+
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
7053
|
+
const pad = "=".repeat((4 - b64.length % 4) % 4);
|
|
7054
|
+
const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
|
|
7055
|
+
return JSON.parse(decoded);
|
|
7056
|
+
} catch {
|
|
7057
|
+
return null;
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7060
|
+
function jwtToNeetruUser(token) {
|
|
7061
|
+
const payload = decodeJwtPayload(token);
|
|
7062
|
+
if (!payload || typeof payload.sub !== "string") return null;
|
|
7063
|
+
if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
|
|
7064
|
+
return null;
|
|
7065
|
+
}
|
|
7066
|
+
return {
|
|
7067
|
+
uid: payload.sub,
|
|
7068
|
+
email: typeof payload.email === "string" ? payload.email : "",
|
|
7069
|
+
emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
|
|
7070
|
+
displayName: typeof payload.name === "string" ? payload.name : void 0,
|
|
7071
|
+
photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
|
|
7072
|
+
isStaff: payload.is_staff === true,
|
|
7073
|
+
isCustomer: payload.is_customer === true,
|
|
7074
|
+
tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
|
|
7075
|
+
...payload
|
|
7076
|
+
};
|
|
7077
|
+
}
|
|
7078
|
+
|
|
6957
7079
|
// src/auth.ts
|
|
6958
7080
|
function readEnvApiKey() {
|
|
6959
7081
|
try {
|
|
@@ -6974,7 +7096,7 @@ function resolveEnv(configEnv) {
|
|
|
6974
7096
|
}
|
|
6975
7097
|
try {
|
|
6976
7098
|
const g = globalThis.NEETRU_ENV;
|
|
6977
|
-
if (g === "
|
|
7099
|
+
if (g === "workspace" || g === "prod") return g;
|
|
6978
7100
|
} catch {
|
|
6979
7101
|
}
|
|
6980
7102
|
return "prod";
|
|
@@ -7011,36 +7133,6 @@ function _jwtPayloadToUser(payload) {
|
|
|
7011
7133
|
};
|
|
7012
7134
|
}
|
|
7013
7135
|
var OIDC_TX_KEY = "neetru_oauth_tx";
|
|
7014
|
-
function resolveIdpOrigin(baseUrl) {
|
|
7015
|
-
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
7016
|
-
return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
7017
|
-
}
|
|
7018
|
-
function getWebCrypto() {
|
|
7019
|
-
const c = globalThis.crypto;
|
|
7020
|
-
if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
|
|
7021
|
-
throw new NeetruError(
|
|
7022
|
-
"runtime_unsupported",
|
|
7023
|
-
"auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno."
|
|
7024
|
-
);
|
|
7025
|
-
}
|
|
7026
|
-
return c;
|
|
7027
|
-
}
|
|
7028
|
-
function base64UrlFromBytes(bytes) {
|
|
7029
|
-
let str = "";
|
|
7030
|
-
for (const b of bytes) str += String.fromCharCode(b);
|
|
7031
|
-
const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
|
|
7032
|
-
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
7033
|
-
}
|
|
7034
|
-
function randomUrlSafe(crypto2, byteLen) {
|
|
7035
|
-
const bytes = new Uint8Array(byteLen);
|
|
7036
|
-
crypto2.getRandomValues(bytes);
|
|
7037
|
-
return base64UrlFromBytes(bytes);
|
|
7038
|
-
}
|
|
7039
|
-
async function pkceChallengeS256(crypto2, verifier) {
|
|
7040
|
-
const data = new TextEncoder().encode(verifier);
|
|
7041
|
-
const digest = await crypto2.subtle.digest("SHA-256", data);
|
|
7042
|
-
return base64UrlFromBytes(new Uint8Array(digest));
|
|
7043
|
-
}
|
|
7044
7136
|
function cleanCallbackUrl(parsed) {
|
|
7045
7137
|
try {
|
|
7046
7138
|
const history = globalThis.history;
|
|
@@ -7074,36 +7166,6 @@ function createOidcAuthNamespace(config) {
|
|
|
7074
7166
|
return null;
|
|
7075
7167
|
}
|
|
7076
7168
|
}
|
|
7077
|
-
function decodeJwtPayload(token) {
|
|
7078
|
-
const parts = token.split(".");
|
|
7079
|
-
if (parts.length !== 3) return null;
|
|
7080
|
-
try {
|
|
7081
|
-
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
7082
|
-
const pad = "=".repeat((4 - b64.length % 4) % 4);
|
|
7083
|
-
const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
|
|
7084
|
-
return JSON.parse(decoded);
|
|
7085
|
-
} catch {
|
|
7086
|
-
return null;
|
|
7087
|
-
}
|
|
7088
|
-
}
|
|
7089
|
-
function tokenToUser(token) {
|
|
7090
|
-
const payload = decodeJwtPayload(token);
|
|
7091
|
-
if (!payload || typeof payload.sub !== "string") return null;
|
|
7092
|
-
if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
|
|
7093
|
-
return null;
|
|
7094
|
-
}
|
|
7095
|
-
return {
|
|
7096
|
-
uid: payload.sub,
|
|
7097
|
-
email: typeof payload.email === "string" ? payload.email : "",
|
|
7098
|
-
emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
|
|
7099
|
-
displayName: typeof payload.name === "string" ? payload.name : void 0,
|
|
7100
|
-
photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
|
|
7101
|
-
isStaff: payload.is_staff === true,
|
|
7102
|
-
isCustomer: payload.is_customer === true,
|
|
7103
|
-
tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
|
|
7104
|
-
...payload
|
|
7105
|
-
};
|
|
7106
|
-
}
|
|
7107
7169
|
function loadCachedUser() {
|
|
7108
7170
|
if (cachedUser) {
|
|
7109
7171
|
const exp = cachedUser.exp;
|
|
@@ -7124,7 +7186,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7124
7186
|
attemptSilentRefresh();
|
|
7125
7187
|
return null;
|
|
7126
7188
|
}
|
|
7127
|
-
const user =
|
|
7189
|
+
const user = jwtToNeetruUser(token);
|
|
7128
7190
|
if (!user) {
|
|
7129
7191
|
storage.removeItem(STORAGE_KEY);
|
|
7130
7192
|
attemptSilentRefresh();
|
|
@@ -7195,7 +7257,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7195
7257
|
if (!res.ok || typeof payload?.error === "string") return false;
|
|
7196
7258
|
const idToken = payload?.id_token;
|
|
7197
7259
|
if (typeof idToken !== "string" || idToken.length === 0) return false;
|
|
7198
|
-
const user =
|
|
7260
|
+
const user = jwtToNeetruUser(idToken);
|
|
7199
7261
|
if (!user) return false;
|
|
7200
7262
|
const storage = getStorage();
|
|
7201
7263
|
storage?.setItem(STORAGE_KEY, idToken);
|
|
@@ -7241,17 +7303,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7241
7303
|
}, msUntilExpiry + 1);
|
|
7242
7304
|
}
|
|
7243
7305
|
function resolveClientId() {
|
|
7244
|
-
|
|
7245
|
-
if (!clientId && config.apiKey) {
|
|
7246
|
-
clientId = parseApiKey(config.apiKey).keyId;
|
|
7247
|
-
}
|
|
7248
|
-
if (!clientId) {
|
|
7249
|
-
throw new NeetruError(
|
|
7250
|
-
"invalid_config",
|
|
7251
|
-
"auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
|
|
7252
|
-
);
|
|
7253
|
-
}
|
|
7254
|
-
return clientId;
|
|
7306
|
+
return resolveOidcClientId(config);
|
|
7255
7307
|
}
|
|
7256
7308
|
async function handleRedirectCallback(currentUrl) {
|
|
7257
7309
|
const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
|
|
@@ -7369,7 +7421,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7369
7421
|
"nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
|
|
7370
7422
|
);
|
|
7371
7423
|
}
|
|
7372
|
-
const user =
|
|
7424
|
+
const user = jwtToNeetruUser(idToken);
|
|
7373
7425
|
if (!user) {
|
|
7374
7426
|
throw new NeetruError(
|
|
7375
7427
|
"token_exchange_failed",
|
|
@@ -7414,15 +7466,15 @@ function createOidcAuthNamespace(config) {
|
|
|
7414
7466
|
};
|
|
7415
7467
|
session.setItem(OIDC_TX_KEY, JSON.stringify(tx));
|
|
7416
7468
|
const idpOrigin = resolveIdpOrigin(config.baseUrl);
|
|
7417
|
-
const url =
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7469
|
+
const url = buildAuthorizeUrl({
|
|
7470
|
+
idpOrigin,
|
|
7471
|
+
clientId,
|
|
7472
|
+
redirectUri,
|
|
7473
|
+
scope,
|
|
7474
|
+
state,
|
|
7475
|
+
nonce,
|
|
7476
|
+
codeChallenge
|
|
7477
|
+
});
|
|
7426
7478
|
globalThis.location.assign(url.toString());
|
|
7427
7479
|
return;
|
|
7428
7480
|
}
|
|
@@ -7437,7 +7489,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7437
7489
|
const storage = getStorage();
|
|
7438
7490
|
const token = storage?.getItem(STORAGE_KEY) ?? null;
|
|
7439
7491
|
if (!token) return null;
|
|
7440
|
-
return
|
|
7492
|
+
return jwtToNeetruUser(token) ? token : null;
|
|
7441
7493
|
},
|
|
7442
7494
|
async signOut() {
|
|
7443
7495
|
const storage = getStorage();
|
|
@@ -7562,7 +7614,7 @@ function createNeetruClient(config = {}) {
|
|
|
7562
7614
|
productId: config.productId,
|
|
7563
7615
|
tenantId: config.tenantId
|
|
7564
7616
|
});
|
|
7565
|
-
const isDev = env === "dev";
|
|
7617
|
+
const isDev = env === "dev" && !isProductionRuntime();
|
|
7566
7618
|
const auth = config.mocks?.auth ?? (isDev ? new MockAuth({ ...DEV_FIXTURE_USER }) : createOidcAuthNamespace(resolved));
|
|
7567
7619
|
const usage = config.mocks?.usage ?? (isDev ? new MockUsage() : createUsageNamespace(resolved));
|
|
7568
7620
|
const support = config.mocks?.support ?? (isDev ? new MockSupport() : createSupportNamespace(resolved));
|