@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.cjs
CHANGED
|
@@ -64,7 +64,8 @@ var init_idempotency = __esm({
|
|
|
64
64
|
var http_exports = {};
|
|
65
65
|
__export(http_exports, {
|
|
66
66
|
checkCoreVersionCompat: () => checkCoreVersionCompat,
|
|
67
|
-
httpRequest: () => httpRequest
|
|
67
|
+
httpRequest: () => httpRequest,
|
|
68
|
+
statusToCode: () => statusToCode
|
|
68
69
|
});
|
|
69
70
|
function stripRevision(v) {
|
|
70
71
|
return v.split("+")[0] ?? v;
|
|
@@ -80,12 +81,16 @@ function compareCalVer(a, b) {
|
|
|
80
81
|
}
|
|
81
82
|
return 0;
|
|
82
83
|
}
|
|
83
|
-
function
|
|
84
|
+
function readInjectedSdkVersion() {
|
|
84
85
|
try {
|
|
85
|
-
|
|
86
|
-
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
86
|
+
return "3.6.0";
|
|
87
87
|
} catch {
|
|
88
|
+
return void 0;
|
|
88
89
|
}
|
|
90
|
+
}
|
|
91
|
+
function getSdkMajor() {
|
|
92
|
+
const ver = readInjectedSdkVersion();
|
|
93
|
+
if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
|
|
89
94
|
return 3;
|
|
90
95
|
}
|
|
91
96
|
function checkCoreVersionCompat(coreVersion) {
|
|
@@ -163,6 +168,10 @@ async function httpRequest(config, opts) {
|
|
|
163
168
|
accept: "application/json",
|
|
164
169
|
...opts.headers
|
|
165
170
|
};
|
|
171
|
+
const sdkVersion = readInjectedSdkVersion();
|
|
172
|
+
if (sdkVersion) {
|
|
173
|
+
headers["x-neetru-sdk-version"] = sdkVersion;
|
|
174
|
+
}
|
|
166
175
|
if (opts.requireAuth) {
|
|
167
176
|
if (!config.apiKey) {
|
|
168
177
|
throw new NeetruError(
|
|
@@ -527,7 +536,7 @@ var init_lease = __esm({
|
|
|
527
536
|
void this._doRenew();
|
|
528
537
|
}, MIN_RENEWAL_DELAY_MS);
|
|
529
538
|
console.warn(
|
|
530
|
-
`[SqlLeaseManager] renova\xE7\xE3o E emiss\xE3o de lease novo falharam; re-tentando em ${MIN_RENEWAL_DELAY_MS}ms (cert
|
|
539
|
+
`[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):`,
|
|
531
540
|
err instanceof Error ? err.message : err
|
|
532
541
|
);
|
|
533
542
|
return;
|
|
@@ -538,8 +547,9 @@ var init_lease = __esm({
|
|
|
538
547
|
/**
|
|
539
548
|
* Recuperação REATIVA: chamado pelo wrapper resiliente (`resilient-pool.ts`)
|
|
540
549
|
* quando uma query plana falha num erro de ESTABELECIMENTO de conexão (cert
|
|
541
|
-
*
|
|
542
|
-
* disparou). Emite um lease NOVO e faz o swap do pool interno
|
|
550
|
+
* TLS efêmero do servidor expirado no meio de uma request, ou timer de
|
|
551
|
+
* renovação que não disparou). Emite um lease NOVO e faz o swap do pool interno
|
|
552
|
+
* do wrapper com
|
|
543
553
|
* o certificado fresco; o wrapper então re-tenta a query 1x no pool novo.
|
|
544
554
|
*
|
|
545
555
|
* Vai DIRETO ao lease novo (sem `leaseId`) — a conexão falhou porque o
|
|
@@ -1139,7 +1149,14 @@ function toProduct(raw) {
|
|
|
1139
1149
|
if (Array.isArray(r.plans)) {
|
|
1140
1150
|
product.plans = r.plans.filter(
|
|
1141
1151
|
(p) => typeof p === "object" && p !== null && typeof p.id === "string" && typeof p.name === "string"
|
|
1142
|
-
)
|
|
1152
|
+
).map((p) => {
|
|
1153
|
+
const plan = { id: p.id, name: p.name };
|
|
1154
|
+
if (typeof p.amountCents === "number") plan.amountCents = p.amountCents;
|
|
1155
|
+
if (Array.isArray(p.features) && p.features.every((f) => typeof f === "string")) {
|
|
1156
|
+
plan.features = p.features;
|
|
1157
|
+
}
|
|
1158
|
+
return plan;
|
|
1159
|
+
});
|
|
1143
1160
|
}
|
|
1144
1161
|
return product;
|
|
1145
1162
|
}
|
|
@@ -1719,7 +1736,10 @@ function createSupportNamespace(config) {
|
|
|
1719
1736
|
await httpRequest(config, {
|
|
1720
1737
|
method: "POST",
|
|
1721
1738
|
path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/satisfaction-attempt`,
|
|
1722
|
-
requireAuth: true
|
|
1739
|
+
requireAuth: true,
|
|
1740
|
+
// Incrementa satisfactionAttempts += 1 no Core — sem idempotencyKey,
|
|
1741
|
+
// um retry de rede infla o contador (mesmo padrão de createTicket acima).
|
|
1742
|
+
idempotencyKey: true
|
|
1723
1743
|
});
|
|
1724
1744
|
},
|
|
1725
1745
|
/**
|
|
@@ -5824,7 +5844,12 @@ function createWebhooksNamespace(config) {
|
|
|
5824
5844
|
events: input.events,
|
|
5825
5845
|
...input.secret ? { secret: input.secret } : {}
|
|
5826
5846
|
},
|
|
5827
|
-
requireAuth: true
|
|
5847
|
+
requireAuth: true,
|
|
5848
|
+
// Sem isso, um retry de rede (app-level; SDK default é 0 retries em
|
|
5849
|
+
// POST) podia registrar o MESMO webhook duas vezes → entrega
|
|
5850
|
+
// duplicada de todo evento futuro pro endpoint do cliente. Core
|
|
5851
|
+
// dedup TTL 24h (mesmo padrão de usage.report/support.createTicket).
|
|
5852
|
+
idempotencyKey: true
|
|
5828
5853
|
});
|
|
5829
5854
|
return toEndpoint(raw);
|
|
5830
5855
|
},
|
|
@@ -6377,16 +6402,6 @@ async function safeJson2(res) {
|
|
|
6377
6402
|
return void 0;
|
|
6378
6403
|
}
|
|
6379
6404
|
}
|
|
6380
|
-
function statusToCode2(status) {
|
|
6381
|
-
if (status === 401) return "unauthorized";
|
|
6382
|
-
if (status === 403) return "forbidden";
|
|
6383
|
-
if (status === 404) return "not_found";
|
|
6384
|
-
if (status === 409) return "conflict";
|
|
6385
|
-
if (status === 422 || status === 400) return "validation_failed";
|
|
6386
|
-
if (status === 429) return "rate_limited";
|
|
6387
|
-
if (status >= 500) return "server_error";
|
|
6388
|
-
return "unknown";
|
|
6389
|
-
}
|
|
6390
6405
|
function joinUrl(baseUrl, path) {
|
|
6391
6406
|
const base = baseUrl.replace(/\/+$/, "");
|
|
6392
6407
|
const p = path.startsWith("/") ? path : `/${path}`;
|
|
@@ -6421,7 +6436,7 @@ async function aiFetch(config, body, signal, stream) {
|
|
|
6421
6436
|
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
6422
6437
|
if (!res.ok) {
|
|
6423
6438
|
const parsed = await safeJson2(res);
|
|
6424
|
-
let code =
|
|
6439
|
+
let code = statusToCode(res.status);
|
|
6425
6440
|
let message = `HTTP ${res.status}`;
|
|
6426
6441
|
if (parsed && typeof parsed === "object" && "error" in parsed) {
|
|
6427
6442
|
const errField = parsed.error;
|
|
@@ -6539,6 +6554,19 @@ function createAiNamespace(config) {
|
|
|
6539
6554
|
|
|
6540
6555
|
// src/mocks.ts
|
|
6541
6556
|
init_errors();
|
|
6557
|
+
|
|
6558
|
+
// src/runtime-env.ts
|
|
6559
|
+
function isProductionRuntime() {
|
|
6560
|
+
try {
|
|
6561
|
+
if (typeof process !== "undefined" && process.env) {
|
|
6562
|
+
return process.env.NODE_ENV === "production";
|
|
6563
|
+
}
|
|
6564
|
+
} catch {
|
|
6565
|
+
}
|
|
6566
|
+
return false;
|
|
6567
|
+
}
|
|
6568
|
+
|
|
6569
|
+
// src/mocks.ts
|
|
6542
6570
|
var DEV_FIXTURE_USER = Object.freeze({
|
|
6543
6571
|
uid: "dev-fixture-uid-0001",
|
|
6544
6572
|
email: "dev@neetru.local",
|
|
@@ -6555,6 +6583,12 @@ var MockAuth = class {
|
|
|
6555
6583
|
this._user = initialUser;
|
|
6556
6584
|
this._listeners = /* @__PURE__ */ new Set();
|
|
6557
6585
|
this._allowUnsignedDecode = options?.allowUnsignedDecode ?? false;
|
|
6586
|
+
if (this._allowUnsignedDecode && isProductionRuntime()) {
|
|
6587
|
+
throw new NeetruError(
|
|
6588
|
+
"invalid_config",
|
|
6589
|
+
"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."
|
|
6590
|
+
);
|
|
6591
|
+
}
|
|
6558
6592
|
if (this._allowUnsignedDecode) {
|
|
6559
6593
|
const isTestEnv = typeof process !== "undefined" && (process.env?.NODE_ENV === "test" || process.env?.VITEST === "true" || process.env?.VITEST != null);
|
|
6560
6594
|
if (!isTestEnv && typeof console !== "undefined") {
|
|
@@ -6956,6 +6990,94 @@ var MockAi = class {
|
|
|
6956
6990
|
}
|
|
6957
6991
|
};
|
|
6958
6992
|
|
|
6993
|
+
// src/auth-pkce-shared.ts
|
|
6994
|
+
init_errors();
|
|
6995
|
+
function getWebCrypto() {
|
|
6996
|
+
const c = globalThis.crypto;
|
|
6997
|
+
if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
|
|
6998
|
+
throw new NeetruError(
|
|
6999
|
+
"runtime_unsupported",
|
|
7000
|
+
"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."
|
|
7001
|
+
);
|
|
7002
|
+
}
|
|
7003
|
+
return c;
|
|
7004
|
+
}
|
|
7005
|
+
function base64UrlFromBytes(bytes) {
|
|
7006
|
+
let str = "";
|
|
7007
|
+
for (const b of bytes) str += String.fromCharCode(b);
|
|
7008
|
+
const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
|
|
7009
|
+
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
7010
|
+
}
|
|
7011
|
+
function randomUrlSafe(crypto2, byteLen) {
|
|
7012
|
+
const bytes = new Uint8Array(byteLen);
|
|
7013
|
+
crypto2.getRandomValues(bytes);
|
|
7014
|
+
return base64UrlFromBytes(bytes);
|
|
7015
|
+
}
|
|
7016
|
+
async function pkceChallengeS256(crypto2, verifier) {
|
|
7017
|
+
const data = new TextEncoder().encode(verifier);
|
|
7018
|
+
const digest = await crypto2.subtle.digest("SHA-256", data);
|
|
7019
|
+
return base64UrlFromBytes(new Uint8Array(digest));
|
|
7020
|
+
}
|
|
7021
|
+
function resolveIdpOrigin(baseUrl) {
|
|
7022
|
+
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
7023
|
+
return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
7024
|
+
}
|
|
7025
|
+
function resolveOidcClientId(config) {
|
|
7026
|
+
let clientId = config.oidcClientId;
|
|
7027
|
+
if (!clientId && config.apiKey) {
|
|
7028
|
+
clientId = parseApiKey(config.apiKey).keyId;
|
|
7029
|
+
}
|
|
7030
|
+
if (!clientId) {
|
|
7031
|
+
throw new NeetruError(
|
|
7032
|
+
"invalid_config",
|
|
7033
|
+
"auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
|
|
7034
|
+
);
|
|
7035
|
+
}
|
|
7036
|
+
return clientId;
|
|
7037
|
+
}
|
|
7038
|
+
function buildAuthorizeUrl(params) {
|
|
7039
|
+
const url = new URL("/api/v1/oauth/authorize", params.idpOrigin);
|
|
7040
|
+
url.searchParams.set("response_type", "code");
|
|
7041
|
+
url.searchParams.set("client_id", params.clientId);
|
|
7042
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
7043
|
+
url.searchParams.set("scope", params.scope);
|
|
7044
|
+
url.searchParams.set("state", params.state);
|
|
7045
|
+
url.searchParams.set("nonce", params.nonce);
|
|
7046
|
+
url.searchParams.set("code_challenge", params.codeChallenge);
|
|
7047
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
7048
|
+
return url;
|
|
7049
|
+
}
|
|
7050
|
+
function decodeJwtPayload(token) {
|
|
7051
|
+
const parts = token.split(".");
|
|
7052
|
+
if (parts.length !== 3) return null;
|
|
7053
|
+
try {
|
|
7054
|
+
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
7055
|
+
const pad = "=".repeat((4 - b64.length % 4) % 4);
|
|
7056
|
+
const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
|
|
7057
|
+
return JSON.parse(decoded);
|
|
7058
|
+
} catch {
|
|
7059
|
+
return null;
|
|
7060
|
+
}
|
|
7061
|
+
}
|
|
7062
|
+
function jwtToNeetruUser(token) {
|
|
7063
|
+
const payload = decodeJwtPayload(token);
|
|
7064
|
+
if (!payload || typeof payload.sub !== "string") return null;
|
|
7065
|
+
if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
|
|
7066
|
+
return null;
|
|
7067
|
+
}
|
|
7068
|
+
return {
|
|
7069
|
+
uid: payload.sub,
|
|
7070
|
+
email: typeof payload.email === "string" ? payload.email : "",
|
|
7071
|
+
emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
|
|
7072
|
+
displayName: typeof payload.name === "string" ? payload.name : void 0,
|
|
7073
|
+
photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
|
|
7074
|
+
isStaff: payload.is_staff === true,
|
|
7075
|
+
isCustomer: payload.is_customer === true,
|
|
7076
|
+
tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
|
|
7077
|
+
...payload
|
|
7078
|
+
};
|
|
7079
|
+
}
|
|
7080
|
+
|
|
6959
7081
|
// src/auth.ts
|
|
6960
7082
|
function readEnvApiKey() {
|
|
6961
7083
|
try {
|
|
@@ -6976,7 +7098,7 @@ function resolveEnv(configEnv) {
|
|
|
6976
7098
|
}
|
|
6977
7099
|
try {
|
|
6978
7100
|
const g = globalThis.NEETRU_ENV;
|
|
6979
|
-
if (g === "
|
|
7101
|
+
if (g === "workspace" || g === "prod") return g;
|
|
6980
7102
|
} catch {
|
|
6981
7103
|
}
|
|
6982
7104
|
return "prod";
|
|
@@ -7013,36 +7135,6 @@ function _jwtPayloadToUser(payload) {
|
|
|
7013
7135
|
};
|
|
7014
7136
|
}
|
|
7015
7137
|
var OIDC_TX_KEY = "neetru_oauth_tx";
|
|
7016
|
-
function resolveIdpOrigin(baseUrl) {
|
|
7017
|
-
const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
|
|
7018
|
-
return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
|
|
7019
|
-
}
|
|
7020
|
-
function getWebCrypto() {
|
|
7021
|
-
const c = globalThis.crypto;
|
|
7022
|
-
if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
|
|
7023
|
-
throw new NeetruError(
|
|
7024
|
-
"runtime_unsupported",
|
|
7025
|
-
"auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno."
|
|
7026
|
-
);
|
|
7027
|
-
}
|
|
7028
|
-
return c;
|
|
7029
|
-
}
|
|
7030
|
-
function base64UrlFromBytes(bytes) {
|
|
7031
|
-
let str = "";
|
|
7032
|
-
for (const b of bytes) str += String.fromCharCode(b);
|
|
7033
|
-
const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
|
|
7034
|
-
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
7035
|
-
}
|
|
7036
|
-
function randomUrlSafe(crypto2, byteLen) {
|
|
7037
|
-
const bytes = new Uint8Array(byteLen);
|
|
7038
|
-
crypto2.getRandomValues(bytes);
|
|
7039
|
-
return base64UrlFromBytes(bytes);
|
|
7040
|
-
}
|
|
7041
|
-
async function pkceChallengeS256(crypto2, verifier) {
|
|
7042
|
-
const data = new TextEncoder().encode(verifier);
|
|
7043
|
-
const digest = await crypto2.subtle.digest("SHA-256", data);
|
|
7044
|
-
return base64UrlFromBytes(new Uint8Array(digest));
|
|
7045
|
-
}
|
|
7046
7138
|
function cleanCallbackUrl(parsed) {
|
|
7047
7139
|
try {
|
|
7048
7140
|
const history = globalThis.history;
|
|
@@ -7076,36 +7168,6 @@ function createOidcAuthNamespace(config) {
|
|
|
7076
7168
|
return null;
|
|
7077
7169
|
}
|
|
7078
7170
|
}
|
|
7079
|
-
function decodeJwtPayload(token) {
|
|
7080
|
-
const parts = token.split(".");
|
|
7081
|
-
if (parts.length !== 3) return null;
|
|
7082
|
-
try {
|
|
7083
|
-
const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
7084
|
-
const pad = "=".repeat((4 - b64.length % 4) % 4);
|
|
7085
|
-
const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
|
|
7086
|
-
return JSON.parse(decoded);
|
|
7087
|
-
} catch {
|
|
7088
|
-
return null;
|
|
7089
|
-
}
|
|
7090
|
-
}
|
|
7091
|
-
function tokenToUser(token) {
|
|
7092
|
-
const payload = decodeJwtPayload(token);
|
|
7093
|
-
if (!payload || typeof payload.sub !== "string") return null;
|
|
7094
|
-
if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
|
|
7095
|
-
return null;
|
|
7096
|
-
}
|
|
7097
|
-
return {
|
|
7098
|
-
uid: payload.sub,
|
|
7099
|
-
email: typeof payload.email === "string" ? payload.email : "",
|
|
7100
|
-
emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
|
|
7101
|
-
displayName: typeof payload.name === "string" ? payload.name : void 0,
|
|
7102
|
-
photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
|
|
7103
|
-
isStaff: payload.is_staff === true,
|
|
7104
|
-
isCustomer: payload.is_customer === true,
|
|
7105
|
-
tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
|
|
7106
|
-
...payload
|
|
7107
|
-
};
|
|
7108
|
-
}
|
|
7109
7171
|
function loadCachedUser() {
|
|
7110
7172
|
if (cachedUser) {
|
|
7111
7173
|
const exp = cachedUser.exp;
|
|
@@ -7126,7 +7188,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7126
7188
|
attemptSilentRefresh();
|
|
7127
7189
|
return null;
|
|
7128
7190
|
}
|
|
7129
|
-
const user =
|
|
7191
|
+
const user = jwtToNeetruUser(token);
|
|
7130
7192
|
if (!user) {
|
|
7131
7193
|
storage.removeItem(STORAGE_KEY);
|
|
7132
7194
|
attemptSilentRefresh();
|
|
@@ -7197,7 +7259,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7197
7259
|
if (!res.ok || typeof payload?.error === "string") return false;
|
|
7198
7260
|
const idToken = payload?.id_token;
|
|
7199
7261
|
if (typeof idToken !== "string" || idToken.length === 0) return false;
|
|
7200
|
-
const user =
|
|
7262
|
+
const user = jwtToNeetruUser(idToken);
|
|
7201
7263
|
if (!user) return false;
|
|
7202
7264
|
const storage = getStorage();
|
|
7203
7265
|
storage?.setItem(STORAGE_KEY, idToken);
|
|
@@ -7243,17 +7305,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7243
7305
|
}, msUntilExpiry + 1);
|
|
7244
7306
|
}
|
|
7245
7307
|
function resolveClientId() {
|
|
7246
|
-
|
|
7247
|
-
if (!clientId && config.apiKey) {
|
|
7248
|
-
clientId = parseApiKey(config.apiKey).keyId;
|
|
7249
|
-
}
|
|
7250
|
-
if (!clientId) {
|
|
7251
|
-
throw new NeetruError(
|
|
7252
|
-
"invalid_config",
|
|
7253
|
-
"auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
|
|
7254
|
-
);
|
|
7255
|
-
}
|
|
7256
|
-
return clientId;
|
|
7308
|
+
return resolveOidcClientId(config);
|
|
7257
7309
|
}
|
|
7258
7310
|
async function handleRedirectCallback(currentUrl) {
|
|
7259
7311
|
const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
|
|
@@ -7371,7 +7423,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7371
7423
|
"nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
|
|
7372
7424
|
);
|
|
7373
7425
|
}
|
|
7374
|
-
const user =
|
|
7426
|
+
const user = jwtToNeetruUser(idToken);
|
|
7375
7427
|
if (!user) {
|
|
7376
7428
|
throw new NeetruError(
|
|
7377
7429
|
"token_exchange_failed",
|
|
@@ -7416,15 +7468,15 @@ function createOidcAuthNamespace(config) {
|
|
|
7416
7468
|
};
|
|
7417
7469
|
session.setItem(OIDC_TX_KEY, JSON.stringify(tx));
|
|
7418
7470
|
const idpOrigin = resolveIdpOrigin(config.baseUrl);
|
|
7419
|
-
const url =
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7471
|
+
const url = buildAuthorizeUrl({
|
|
7472
|
+
idpOrigin,
|
|
7473
|
+
clientId,
|
|
7474
|
+
redirectUri,
|
|
7475
|
+
scope,
|
|
7476
|
+
state,
|
|
7477
|
+
nonce,
|
|
7478
|
+
codeChallenge
|
|
7479
|
+
});
|
|
7428
7480
|
globalThis.location.assign(url.toString());
|
|
7429
7481
|
return;
|
|
7430
7482
|
}
|
|
@@ -7439,7 +7491,7 @@ function createOidcAuthNamespace(config) {
|
|
|
7439
7491
|
const storage = getStorage();
|
|
7440
7492
|
const token = storage?.getItem(STORAGE_KEY) ?? null;
|
|
7441
7493
|
if (!token) return null;
|
|
7442
|
-
return
|
|
7494
|
+
return jwtToNeetruUser(token) ? token : null;
|
|
7443
7495
|
},
|
|
7444
7496
|
async signOut() {
|
|
7445
7497
|
const storage = getStorage();
|
|
@@ -7564,7 +7616,7 @@ function createNeetruClient(config = {}) {
|
|
|
7564
7616
|
productId: config.productId,
|
|
7565
7617
|
tenantId: config.tenantId
|
|
7566
7618
|
});
|
|
7567
|
-
const isDev = env === "dev";
|
|
7619
|
+
const isDev = env === "dev" && !isProductionRuntime();
|
|
7568
7620
|
const auth = config.mocks?.auth ?? (isDev ? new MockAuth({ ...DEV_FIXTURE_USER }) : createOidcAuthNamespace(resolved));
|
|
7569
7621
|
const usage = config.mocks?.usage ?? (isDev ? new MockUsage() : createUsageNamespace(resolved));
|
|
7570
7622
|
const support = config.mocks?.support ?? (isDev ? new MockSupport() : createSupportNamespace(resolved));
|