@neetru/sdk 3.4.3 → 3.4.5
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 +40 -0
- package/dist/ai.d.cts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/auth.cjs +33 -11
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +33 -11
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/checkout.cjs +17 -7
- 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 +17 -7
- 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.d.cts +1 -1
- package/dist/db.d.ts +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 +34 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +34 -12
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/react.cjs +62 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +38 -7
- package/dist/react.d.ts +38 -7
- package/dist/react.mjs +62 -3
- package/dist/react.mjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/telemetry.cjs +16 -4
- 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 +16 -4
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-D-QdG502.d.cts → types-DIVZl7nO.d.cts} +29 -8
- package/dist/{types-BlOLDMR0.d.ts → types-nnztVk7G.d.ts} +29 -8
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ All notable changes to `@neetru/sdk` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.4.5] - 2026-09-12 — **fix(telemetry): event()/track() usáveis no browser (401 silencioso em produção)**
|
|
9
|
+
|
|
10
|
+
Release **patch** (correção de bug — `client.telemetry.event()`/`.track()` documentados como uso client-side de alta frequência, mas nunca funcionaram de fato no browser).
|
|
11
|
+
|
|
12
|
+
### Contexto
|
|
13
|
+
|
|
14
|
+
`event()`/`track()` só chamavam `POST /api/sdk/v1/telemetry/event`, que exige `Bearer` com `cli_api_keys` — credencial de operador que nunca deveria estar no browser. Resultado real em produção (achado 2026-09-09, `pdvagiliza.neetru.com`): 401 silencioso, telemetria de UI nunca persistida. Compondo o problema, `productSlug` nunca era enviado no body de nenhum dos dois métodos (só `log()` já mandava) — o Core exige `productSlug` fail-closed, então mesmo corrigindo a auth o evento seria rejeitado.
|
|
15
|
+
|
|
16
|
+
### Corrigido
|
|
17
|
+
|
|
18
|
+
- **`event()`/`track()` agora enviam `productSlug`** no body (`input.productSlug ?? config.productId`, mesmo default de `log()`/`usage.report()`).
|
|
19
|
+
- **Roteamento browser vs server**: em contexto browser (`typeof window !== 'undefined'`), `event()`/`track()` chamam o novo `POST /api/sdk/v1/telemetry/event/public` do Core (sem Bearer — autoriza via `Origin`, não credencial). Server-side continua no endpoint autenticado original, sem mudança de comportamento.
|
|
20
|
+
|
|
21
|
+
### Adicionado (aditivo, opcional)
|
|
22
|
+
|
|
23
|
+
- **`TelemetryEventInput.productSlug?: string`** — override explícito, mesmo padrão de `TelemetryLogInput.productSlug`.
|
|
24
|
+
|
|
25
|
+
Requer Core com a rota `/api/sdk/v1/telemetry/event/public` (PR companion `Neetru/neetru-core#448`) para o caminho browser funcionar; server-side não tem dependência nova.
|
|
26
|
+
|
|
27
|
+
## [3.4.4] - 2026-09-07 — **fix(checkout): aceitar id_token no padrão BFF/cookie (desbloqueia checkout PAGO)**
|
|
28
|
+
|
|
29
|
+
Release **patch** (correção de bug que bloqueava 100% do checkout PAGO no padrão BFF/cookie; aditivos opcionais retrocompatíveis, nenhuma remoção de API, nenhuma mudança de wire além de um header aceito a mais). Bug `bug_72ccf42065304d3384aa3ed09accef8d` (HIGH).
|
|
30
|
+
|
|
31
|
+
### Contexto
|
|
32
|
+
|
|
33
|
+
No padrão **BFF/cookie** (recomendado), o app troca `code`→tokens **no servidor**, guarda só o **id_token** num cookie **httpOnly** e **descarta o access_token** — então o browser NUNCA tem o access_token. Mas `checkout.start()` / `<CheckoutLink>` exigiam o access_token no browser, tornando impossível iniciar o checkout PAGO nesse padrão (só o `MockCheckout` de dev "funcionava"). O Core passou a aceitar o **id_token** no endpoint de checkout (via `verifyEndUserIdToken`, mesma validação forte de assinatura/kid/iss/exp da barra de conta), então o SDK agora expõe o caminho BFF.
|
|
34
|
+
|
|
35
|
+
### Corrigido
|
|
36
|
+
|
|
37
|
+
- **`checkout.start()` / `get()` / `cancel()` aceitam `idToken`** além de `accessToken`. O helper de auth manda o token que houver no header `Bearer` (o Core resolve se é access_token ou id_token). Quando ambos vêm, `accessToken` tem prioridade (é revogável no servidor). Sem nenhum dos dois, continua lançando `validation_failed` sem tocar a rede.
|
|
38
|
+
|
|
39
|
+
### Adicionado (aditivo, opcional)
|
|
40
|
+
|
|
41
|
+
- **`CheckoutStartInput.idToken?` / `CheckoutAuthOpts.idToken?`** — id_token OIDC do usuário final para o padrão BFF/cookie.
|
|
42
|
+
- **`<CheckoutLink startPath="/api/checkout/start">`** — novo modo BFF: o clique faz `POST` no route do PRÓPRIO app (same-origin, `credentials: 'include'` → manda o cookie httpOnly), que inicia o checkout server-side e devolve `{ redirectUrl }`. O `client` vira **opcional** neste modo (o browser não precisa de token nem de client). O modo legado `client.checkout.start()` (client-side, browser com token) segue intacto.
|
|
43
|
+
|
|
44
|
+
### Padrão BFF suportado
|
|
45
|
+
|
|
46
|
+
Ver `docs/CHECKOUT_BFF.md` — passo a passo canônico do checkout num app BFF/cookie (o que o produto tem que fazer: route BFF que lê o id_token do cookie e chama `client.checkout.start({ ..., idToken })`, + `<CheckoutLink startPath=...>` no client).
|
|
47
|
+
|
|
8
48
|
## [3.4.3] - 2026-09-07 — **build-guard força pg + drizzle-orm no trace do standalone (causa-2 outage PDV 2026-09-07)**
|
|
9
49
|
|
|
10
50
|
Release **patch** (só correção de build; nada de wire, nada removido da API). Fase 2 do conserto do outage do PDV.
|
package/dist/ai.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, aJ as createAiNamespace } from './types-
|
|
1
|
+
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, aJ as createAiNamespace } from './types-DIVZl7nO.cjs';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.cjs';
|
package/dist/ai.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, aJ as createAiNamespace } from './types-
|
|
1
|
+
export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, aJ as createAiNamespace } from './types-nnztVk7G.js';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.js';
|
package/dist/auth.cjs
CHANGED
|
@@ -1273,6 +1273,12 @@ function createEntitlementsNamespace(config) {
|
|
|
1273
1273
|
init_errors();
|
|
1274
1274
|
init_http();
|
|
1275
1275
|
var VALID_LOG_LEVELS = ["debug", "info", "warn", "error", "fatal"];
|
|
1276
|
+
function isBrowserContext() {
|
|
1277
|
+
return typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
|
|
1278
|
+
}
|
|
1279
|
+
function resolveEventTransport() {
|
|
1280
|
+
return isBrowserContext() ? { path: "/api/sdk/v1/telemetry/event/public", requireAuth: false } : { path: "/api/sdk/v1/telemetry/event", requireAuth: true };
|
|
1281
|
+
}
|
|
1276
1282
|
function consoleFor(level) {
|
|
1277
1283
|
switch (level) {
|
|
1278
1284
|
case "debug":
|
|
@@ -1302,15 +1308,18 @@ function createTelemetryNamespace(config) {
|
|
|
1302
1308
|
batch.map(async (ev) => {
|
|
1303
1309
|
try {
|
|
1304
1310
|
const body = { name: ev.name };
|
|
1311
|
+
const productSlug = ev.productSlug ?? config.productId;
|
|
1312
|
+
if (productSlug) body.productSlug = productSlug;
|
|
1305
1313
|
if (ev.properties && typeof ev.properties === "object") {
|
|
1306
1314
|
body.properties = ev.properties;
|
|
1307
1315
|
}
|
|
1308
1316
|
if (ev.timestamp) body.timestamp = ev.timestamp;
|
|
1317
|
+
const transport = resolveEventTransport();
|
|
1309
1318
|
await httpRequest(config, {
|
|
1310
1319
|
method: "POST",
|
|
1311
|
-
path:
|
|
1320
|
+
path: transport.path,
|
|
1312
1321
|
body,
|
|
1313
|
-
requireAuth:
|
|
1322
|
+
requireAuth: transport.requireAuth,
|
|
1314
1323
|
retries: 1,
|
|
1315
1324
|
// caça-bruxas: retry sem Idempotency-Key duplicava o evento se o
|
|
1316
1325
|
// servidor já tinha persistido antes da falha transiente. Mesmo
|
|
@@ -1363,15 +1372,18 @@ function createTelemetryNamespace(config) {
|
|
|
1363
1372
|
throw new NeetruError("validation_failed", "event.name max 128 chars");
|
|
1364
1373
|
}
|
|
1365
1374
|
const body = { name: input.name };
|
|
1375
|
+
const productSlug = input.productSlug ?? config.productId;
|
|
1376
|
+
if (productSlug) body.productSlug = productSlug;
|
|
1366
1377
|
if (input.properties && typeof input.properties === "object") {
|
|
1367
1378
|
body.properties = input.properties;
|
|
1368
1379
|
}
|
|
1369
1380
|
if (input.timestamp) body.timestamp = input.timestamp;
|
|
1381
|
+
const transport = resolveEventTransport();
|
|
1370
1382
|
const raw = await httpRequest(config, {
|
|
1371
1383
|
method: "POST",
|
|
1372
|
-
path:
|
|
1384
|
+
path: transport.path,
|
|
1373
1385
|
body,
|
|
1374
|
-
requireAuth:
|
|
1386
|
+
requireAuth: transport.requireAuth
|
|
1375
1387
|
});
|
|
1376
1388
|
if (!raw || raw.ok !== true || typeof raw.eventId !== "string") {
|
|
1377
1389
|
throw new NeetruError("invalid_response", "Telemetry response missing eventId");
|
|
@@ -5576,14 +5588,15 @@ function createLazyCollectionRef(name, getDocsPromise) {
|
|
|
5576
5588
|
// src/checkout.ts
|
|
5577
5589
|
init_errors();
|
|
5578
5590
|
init_http();
|
|
5579
|
-
function checkoutAuth(
|
|
5580
|
-
|
|
5591
|
+
function checkoutAuth(auth, method) {
|
|
5592
|
+
const token = auth?.accessToken || auth?.idToken;
|
|
5593
|
+
if (!token || typeof token !== "string") {
|
|
5581
5594
|
throw new NeetruError(
|
|
5582
5595
|
"validation_failed",
|
|
5583
|
-
`checkout.${method} requer o access_token OIDC do usu\xE1rio final (passe \`accessToken\`). A chave de API do SDK (nrt_*) N\xC3O \xE9 aceita pelo endpoint de checkout \u2014 ele autentica a identidade do cliente que est\xE1 assinando (Bearer access_token OIDC ou cookie de sess\xE3o).`
|
|
5596
|
+
`checkout.${method} requer o access_token OU o id_token OIDC do usu\xE1rio final (passe \`accessToken\` ou \`idToken\`). A chave de API do SDK (nrt_*) N\xC3O \xE9 aceita pelo endpoint de checkout \u2014 ele autentica a identidade do cliente que est\xE1 assinando (Bearer access_token/id_token OIDC ou cookie de sess\xE3o). No padr\xE3o BFF/cookie, passe o \`idToken\` que seu servidor guardou no cookie httpOnly.`
|
|
5584
5597
|
);
|
|
5585
5598
|
}
|
|
5586
|
-
return { requireAuth: false, headers: { authorization: `Bearer ${
|
|
5599
|
+
return { requireAuth: false, headers: { authorization: `Bearer ${token}` } };
|
|
5587
5600
|
}
|
|
5588
5601
|
function parseStartResponse(raw) {
|
|
5589
5602
|
if (!raw || typeof raw !== "object") {
|
|
@@ -5662,7 +5675,10 @@ function createHttpCheckoutNamespace(config) {
|
|
|
5662
5675
|
};
|
|
5663
5676
|
if (input.tenantType) body.targetTenantType = input.tenantType;
|
|
5664
5677
|
if (input.tenantId) body.targetTenantId = input.tenantId;
|
|
5665
|
-
const { requireAuth, headers } = checkoutAuth(
|
|
5678
|
+
const { requireAuth, headers } = checkoutAuth(
|
|
5679
|
+
{ accessToken: input.accessToken, idToken: input.idToken },
|
|
5680
|
+
"start"
|
|
5681
|
+
);
|
|
5666
5682
|
const raw = await httpRequest(config, {
|
|
5667
5683
|
method: "POST",
|
|
5668
5684
|
path: "/api/v1/checkout/intents",
|
|
@@ -5682,7 +5698,10 @@ function createHttpCheckoutNamespace(config) {
|
|
|
5682
5698
|
if (!intentId || typeof intentId !== "string") {
|
|
5683
5699
|
throw new NeetruError("validation_failed", "checkout.get: intentId is required");
|
|
5684
5700
|
}
|
|
5685
|
-
const { requireAuth, headers } = checkoutAuth(
|
|
5701
|
+
const { requireAuth, headers } = checkoutAuth(
|
|
5702
|
+
{ accessToken: opts?.accessToken, idToken: opts?.idToken },
|
|
5703
|
+
"get"
|
|
5704
|
+
);
|
|
5686
5705
|
const raw = await httpRequest(config, {
|
|
5687
5706
|
method: "GET",
|
|
5688
5707
|
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|
|
@@ -5695,7 +5714,10 @@ function createHttpCheckoutNamespace(config) {
|
|
|
5695
5714
|
if (!intentId || typeof intentId !== "string") {
|
|
5696
5715
|
throw new NeetruError("validation_failed", "checkout.cancel: intentId is required");
|
|
5697
5716
|
}
|
|
5698
|
-
const { requireAuth, headers } = checkoutAuth(
|
|
5717
|
+
const { requireAuth, headers } = checkoutAuth(
|
|
5718
|
+
{ accessToken: opts?.accessToken, idToken: opts?.idToken },
|
|
5719
|
+
"cancel"
|
|
5720
|
+
);
|
|
5699
5721
|
const raw = await httpRequest(config, {
|
|
5700
5722
|
method: "DELETE",
|
|
5701
5723
|
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|