@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.
Files changed (94) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/ai.cjs +17 -13
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.d.cts +1 -1
  5. package/dist/ai.d.ts +1 -1
  6. package/dist/ai.mjs +17 -13
  7. package/dist/ai.mjs.map +1 -1
  8. package/dist/auth.cjs +159 -107
  9. package/dist/auth.cjs.map +1 -1
  10. package/dist/auth.d.cts +2 -2
  11. package/dist/auth.d.ts +2 -2
  12. package/dist/auth.mjs +159 -107
  13. package/dist/auth.mjs.map +1 -1
  14. package/dist/catalog.cjs +19 -4
  15. package/dist/catalog.cjs.map +1 -1
  16. package/dist/catalog.d.cts +1 -1
  17. package/dist/catalog.d.ts +1 -1
  18. package/dist/catalog.mjs +19 -4
  19. package/dist/catalog.mjs.map +1 -1
  20. package/dist/checkout.cjs +11 -3
  21. package/dist/checkout.cjs.map +1 -1
  22. package/dist/checkout.d.cts +1 -1
  23. package/dist/checkout.d.ts +1 -1
  24. package/dist/checkout.mjs +11 -3
  25. package/dist/checkout.mjs.map +1 -1
  26. package/dist/db-react.d.cts +1 -1
  27. package/dist/db-react.d.ts +1 -1
  28. package/dist/db.cjs +17 -7
  29. package/dist/db.cjs.map +1 -1
  30. package/dist/db.d.cts +1 -1
  31. package/dist/db.d.ts +1 -1
  32. package/dist/db.mjs +17 -7
  33. package/dist/db.mjs.map +1 -1
  34. package/dist/entitlements.d.cts +1 -1
  35. package/dist/entitlements.d.ts +1 -1
  36. package/dist/firestore-compat.d.cts +1 -1
  37. package/dist/firestore-compat.d.ts +1 -1
  38. package/dist/index.cjs +160 -108
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +30 -2
  41. package/dist/index.d.ts +30 -2
  42. package/dist/index.mjs +160 -108
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/mobile.cjs +515 -0
  45. package/dist/mobile.cjs.map +1 -0
  46. package/dist/mobile.d.cts +89 -0
  47. package/dist/mobile.d.ts +89 -0
  48. package/dist/mobile.mjs +513 -0
  49. package/dist/mobile.mjs.map +1 -0
  50. package/dist/mocks.cjs +17 -0
  51. package/dist/mocks.cjs.map +1 -1
  52. package/dist/mocks.d.cts +5 -1
  53. package/dist/mocks.d.ts +5 -1
  54. package/dist/mocks.mjs +17 -0
  55. package/dist/mocks.mjs.map +1 -1
  56. package/dist/notifications.cjs +11 -3
  57. package/dist/notifications.cjs.map +1 -1
  58. package/dist/notifications.d.cts +1 -1
  59. package/dist/notifications.d.ts +1 -1
  60. package/dist/notifications.mjs +11 -3
  61. package/dist/notifications.mjs.map +1 -1
  62. package/dist/react.cjs +36 -2
  63. package/dist/react.cjs.map +1 -1
  64. package/dist/react.d.cts +1 -1
  65. package/dist/react.d.ts +1 -1
  66. package/dist/react.mjs +36 -2
  67. package/dist/react.mjs.map +1 -1
  68. package/dist/support.cjs +15 -4
  69. package/dist/support.cjs.map +1 -1
  70. package/dist/support.d.cts +1 -1
  71. package/dist/support.d.ts +1 -1
  72. package/dist/support.mjs +15 -4
  73. package/dist/support.mjs.map +1 -1
  74. package/dist/telemetry.cjs +11 -3
  75. package/dist/telemetry.cjs.map +1 -1
  76. package/dist/telemetry.d.cts +1 -1
  77. package/dist/telemetry.d.ts +1 -1
  78. package/dist/telemetry.mjs +11 -3
  79. package/dist/telemetry.mjs.map +1 -1
  80. package/dist/{types-nnztVk7G.d.ts → types-BPATkXYu.d.ts} +35 -7
  81. package/dist/{types-DIVZl7nO.d.cts → types-Du_iioJ7.d.cts} +35 -7
  82. package/dist/usage.cjs +11 -3
  83. package/dist/usage.cjs.map +1 -1
  84. package/dist/usage.d.cts +1 -1
  85. package/dist/usage.d.ts +1 -1
  86. package/dist/usage.mjs +11 -3
  87. package/dist/usage.mjs.map +1 -1
  88. package/dist/webhooks.cjs +17 -4
  89. package/dist/webhooks.cjs.map +1 -1
  90. package/dist/webhooks.d.cts +1 -1
  91. package/dist/webhooks.d.ts +1 -1
  92. package/dist/webhooks.mjs +17 -4
  93. package/dist/webhooks.mjs.map +1 -1
  94. package/package.json +9 -1
package/dist/index.d.cts CHANGED
@@ -1,9 +1,37 @@
1
1
  export { createNeetruClient, getServerNeetruClient } from './auth.cjs';
2
2
  export { NeetruError, NeetruErrorCode } from './errors.cjs';
3
- 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, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-DIVZl7nO.cjs';
3
+ 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, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-Du_iioJ7.cjs';
4
4
  export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.cjs';
5
5
  import 'drizzle-orm/node-postgres';
6
6
 
7
+ /**
8
+ * HTTP transport interno do SDK.
9
+ *
10
+ * Responsabilidades:
11
+ * - Construir URL absoluta a partir de `baseUrl` + path
12
+ * - Injetar Bearer token quando `requireAuth=true`
13
+ * - Mapear status HTTP → `NeetruError` com `code` estável
14
+ * - Parse defensivo de JSON (não lança em body vazio em 204)
15
+ * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)
16
+ * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando
17
+ * presente.
18
+ * - **Captura `X-Neetru-Version`** das respostas e emite `console.warn` quando
19
+ * o Core está abaixo da versão mínima para a major do SDK.
20
+ *
21
+ * Política de retries (mudança breaking 3.0):
22
+ * - GET/HEAD: default 2 retries (3 tentativas total) — idempotente, seguro.
23
+ * - POST/PUT/PATCH/DELETE: default **0 retries** — mutations podem duplicar
24
+ * side effects (ex: `usage.report` incrementa contador). Caller pode
25
+ * reativar passando `retries: N` explicitamente ou usar `Idempotency-Key`
26
+ * header (gerado automaticamente se `opts.idempotencyKey=true`).
27
+ *
28
+ * Idempotency-Key (3.0):
29
+ * - `opts.idempotencyKey === true` → SDK gera UUID v4 e injeta header.
30
+ * - `opts.idempotencyKey === 'uuid-string'` → usa o valor passado.
31
+ * - Caller mantém retentos client-side se quiser; Core dedup serverside
32
+ * (vide `docs/CORE_CHANGES_REQUIRED.md` §2).
33
+ */
34
+
7
35
  /**
8
36
  * Verifica se a versão do Core (`X-Neetru-Version`) é compatível com a SDK major.
9
37
  * Emite `console.warn` quando incompatível (uma vez por processo por versão detectada).
@@ -42,6 +70,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
42
70
  */
43
71
 
44
72
  /** Versão do SDK — exportada explicitamente pra detecção em runtime. */
45
- declare const VERSION: "3.4.6";
73
+ declare const VERSION: "3.6.0";
46
74
 
47
75
  export { VERSION, checkCoreVersionCompat };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,37 @@
1
1
  export { createNeetruClient, getServerNeetruClient } from './auth.js';
2
2
  export { NeetruError, NeetruErrorCode } from './errors.js';
3
- 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, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-nnztVk7G.js';
3
+ 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, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-BPATkXYu.js';
4
4
  export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.js';
5
5
  import 'drizzle-orm/node-postgres';
6
6
 
7
+ /**
8
+ * HTTP transport interno do SDK.
9
+ *
10
+ * Responsabilidades:
11
+ * - Construir URL absoluta a partir de `baseUrl` + path
12
+ * - Injetar Bearer token quando `requireAuth=true`
13
+ * - Mapear status HTTP → `NeetruError` com `code` estável
14
+ * - Parse defensivo de JSON (não lança em body vazio em 204)
15
+ * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)
16
+ * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando
17
+ * presente.
18
+ * - **Captura `X-Neetru-Version`** das respostas e emite `console.warn` quando
19
+ * o Core está abaixo da versão mínima para a major do SDK.
20
+ *
21
+ * Política de retries (mudança breaking 3.0):
22
+ * - GET/HEAD: default 2 retries (3 tentativas total) — idempotente, seguro.
23
+ * - POST/PUT/PATCH/DELETE: default **0 retries** — mutations podem duplicar
24
+ * side effects (ex: `usage.report` incrementa contador). Caller pode
25
+ * reativar passando `retries: N` explicitamente ou usar `Idempotency-Key`
26
+ * header (gerado automaticamente se `opts.idempotencyKey=true`).
27
+ *
28
+ * Idempotency-Key (3.0):
29
+ * - `opts.idempotencyKey === true` → SDK gera UUID v4 e injeta header.
30
+ * - `opts.idempotencyKey === 'uuid-string'` → usa o valor passado.
31
+ * - Caller mantém retentos client-side se quiser; Core dedup serverside
32
+ * (vide `docs/CORE_CHANGES_REQUIRED.md` §2).
33
+ */
34
+
7
35
  /**
8
36
  * Verifica se a versão do Core (`X-Neetru-Version`) é compatível com a SDK major.
9
37
  * Emite `console.warn` quando incompatível (uma vez por processo por versão detectada).
@@ -42,6 +70,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
42
70
  */
43
71
 
44
72
  /** Versão do SDK — exportada explicitamente pra detecção em runtime. */
45
- declare const VERSION: "3.4.6";
73
+ declare const VERSION: "3.6.0";
46
74
 
47
75
  export { VERSION, checkCoreVersionCompat };
package/dist/index.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 getSdkMajor() {
82
+ function readInjectedSdkVersion() {
82
83
  try {
83
- const ver = globalThis.__NEETRU_SDK_VERSION__;
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 mTLS expira ~15min ap\xF3s o \xFAltimo swap):`,
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
- * mTLS expirado no meio de uma request, ou timer de renovação que não
540
- * disparou). Emite um lease NOVO e faz o swap do pool interno do wrapper com
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
  /**
@@ -5919,7 +5939,12 @@ function createWebhooksNamespace(config) {
5919
5939
  events: input.events,
5920
5940
  ...input.secret ? { secret: input.secret } : {}
5921
5941
  },
5922
- requireAuth: true
5942
+ requireAuth: true,
5943
+ // Sem isso, um retry de rede (app-level; SDK default é 0 retries em
5944
+ // POST) podia registrar o MESMO webhook duas vezes → entrega
5945
+ // duplicada de todo evento futuro pro endpoint do cliente. Core
5946
+ // dedup TTL 24h (mesmo padrão de usage.report/support.createTicket).
5947
+ idempotencyKey: true
5923
5948
  });
5924
5949
  return toEndpoint(raw);
5925
5950
  },
@@ -6472,16 +6497,6 @@ async function safeJson2(res) {
6472
6497
  return void 0;
6473
6498
  }
6474
6499
  }
6475
- function statusToCode2(status) {
6476
- if (status === 401) return "unauthorized";
6477
- if (status === 403) return "forbidden";
6478
- if (status === 404) return "not_found";
6479
- if (status === 409) return "conflict";
6480
- if (status === 422 || status === 400) return "validation_failed";
6481
- if (status === 429) return "rate_limited";
6482
- if (status >= 500) return "server_error";
6483
- return "unknown";
6484
- }
6485
6500
  function joinUrl(baseUrl, path) {
6486
6501
  const base = baseUrl.replace(/\/+$/, "");
6487
6502
  const p = path.startsWith("/") ? path : `/${path}`;
@@ -6516,7 +6531,7 @@ async function aiFetch(config, body, signal, stream) {
6516
6531
  const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
6517
6532
  if (!res.ok) {
6518
6533
  const parsed = await safeJson2(res);
6519
- let code = statusToCode2(res.status);
6534
+ let code = statusToCode(res.status);
6520
6535
  let message = `HTTP ${res.status}`;
6521
6536
  if (parsed && typeof parsed === "object" && "error" in parsed) {
6522
6537
  const errField = parsed.error;
@@ -6635,6 +6650,19 @@ function createAiNamespace(config) {
6635
6650
  // src/mocks.ts
6636
6651
  init_db_errors();
6637
6652
  init_errors();
6653
+
6654
+ // src/runtime-env.ts
6655
+ function isProductionRuntime() {
6656
+ try {
6657
+ if (typeof process !== "undefined" && process.env) {
6658
+ return process.env.NODE_ENV === "production";
6659
+ }
6660
+ } catch {
6661
+ }
6662
+ return false;
6663
+ }
6664
+
6665
+ // src/mocks.ts
6638
6666
  var DEV_FIXTURE_USER = Object.freeze({
6639
6667
  uid: "dev-fixture-uid-0001",
6640
6668
  email: "dev@neetru.local",
@@ -6651,6 +6679,12 @@ var MockAuth = class {
6651
6679
  this._user = initialUser;
6652
6680
  this._listeners = /* @__PURE__ */ new Set();
6653
6681
  this._allowUnsignedDecode = options?.allowUnsignedDecode ?? false;
6682
+ if (this._allowUnsignedDecode && isProductionRuntime()) {
6683
+ throw new NeetruError(
6684
+ "invalid_config",
6685
+ "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."
6686
+ );
6687
+ }
6654
6688
  if (this._allowUnsignedDecode) {
6655
6689
  const isTestEnv = typeof process !== "undefined" && (process.env?.NODE_ENV === "test" || process.env?.VITEST === "true" || process.env?.VITEST != null);
6656
6690
  if (!isTestEnv && typeof console !== "undefined") {
@@ -7366,6 +7400,94 @@ var MockAi = class {
7366
7400
  }
7367
7401
  };
7368
7402
 
7403
+ // src/auth-pkce-shared.ts
7404
+ init_errors();
7405
+ function getWebCrypto() {
7406
+ const c = globalThis.crypto;
7407
+ if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
7408
+ throw new NeetruError(
7409
+ "runtime_unsupported",
7410
+ "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."
7411
+ );
7412
+ }
7413
+ return c;
7414
+ }
7415
+ function base64UrlFromBytes(bytes) {
7416
+ let str = "";
7417
+ for (const b of bytes) str += String.fromCharCode(b);
7418
+ const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
7419
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
7420
+ }
7421
+ function randomUrlSafe(crypto2, byteLen) {
7422
+ const bytes = new Uint8Array(byteLen);
7423
+ crypto2.getRandomValues(bytes);
7424
+ return base64UrlFromBytes(bytes);
7425
+ }
7426
+ async function pkceChallengeS256(crypto2, verifier) {
7427
+ const data = new TextEncoder().encode(verifier);
7428
+ const digest = await crypto2.subtle.digest("SHA-256", data);
7429
+ return base64UrlFromBytes(new Uint8Array(digest));
7430
+ }
7431
+ function resolveIdpOrigin(baseUrl) {
7432
+ const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
7433
+ return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
7434
+ }
7435
+ function resolveOidcClientId(config) {
7436
+ let clientId = config.oidcClientId;
7437
+ if (!clientId && config.apiKey) {
7438
+ clientId = parseApiKey(config.apiKey).keyId;
7439
+ }
7440
+ if (!clientId) {
7441
+ throw new NeetruError(
7442
+ "invalid_config",
7443
+ "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
7444
+ );
7445
+ }
7446
+ return clientId;
7447
+ }
7448
+ function buildAuthorizeUrl(params) {
7449
+ const url = new URL("/api/v1/oauth/authorize", params.idpOrigin);
7450
+ url.searchParams.set("response_type", "code");
7451
+ url.searchParams.set("client_id", params.clientId);
7452
+ url.searchParams.set("redirect_uri", params.redirectUri);
7453
+ url.searchParams.set("scope", params.scope);
7454
+ url.searchParams.set("state", params.state);
7455
+ url.searchParams.set("nonce", params.nonce);
7456
+ url.searchParams.set("code_challenge", params.codeChallenge);
7457
+ url.searchParams.set("code_challenge_method", "S256");
7458
+ return url;
7459
+ }
7460
+ function decodeJwtPayload(token) {
7461
+ const parts = token.split(".");
7462
+ if (parts.length !== 3) return null;
7463
+ try {
7464
+ const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
7465
+ const pad = "=".repeat((4 - b64.length % 4) % 4);
7466
+ const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
7467
+ return JSON.parse(decoded);
7468
+ } catch {
7469
+ return null;
7470
+ }
7471
+ }
7472
+ function jwtToNeetruUser(token) {
7473
+ const payload = decodeJwtPayload(token);
7474
+ if (!payload || typeof payload.sub !== "string") return null;
7475
+ if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
7476
+ return null;
7477
+ }
7478
+ return {
7479
+ uid: payload.sub,
7480
+ email: typeof payload.email === "string" ? payload.email : "",
7481
+ emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
7482
+ displayName: typeof payload.name === "string" ? payload.name : void 0,
7483
+ photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
7484
+ isStaff: payload.is_staff === true,
7485
+ isCustomer: payload.is_customer === true,
7486
+ tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
7487
+ ...payload
7488
+ };
7489
+ }
7490
+
7369
7491
  // src/auth.ts
7370
7492
  function readEnvApiKey() {
7371
7493
  try {
@@ -7386,7 +7508,7 @@ function resolveEnv(configEnv) {
7386
7508
  }
7387
7509
  try {
7388
7510
  const g = globalThis.NEETRU_ENV;
7389
- if (g === "dev" || g === "workspace" || g === "prod") return g;
7511
+ if (g === "workspace" || g === "prod") return g;
7390
7512
  } catch {
7391
7513
  }
7392
7514
  return "prod";
@@ -7420,36 +7542,6 @@ function _jwtPayloadToUser(payload) {
7420
7542
  };
7421
7543
  }
7422
7544
  var OIDC_TX_KEY = "neetru_oauth_tx";
7423
- function resolveIdpOrigin(baseUrl) {
7424
- const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
7425
- return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
7426
- }
7427
- function getWebCrypto() {
7428
- const c = globalThis.crypto;
7429
- if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
7430
- throw new NeetruError(
7431
- "runtime_unsupported",
7432
- "auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno."
7433
- );
7434
- }
7435
- return c;
7436
- }
7437
- function base64UrlFromBytes(bytes) {
7438
- let str = "";
7439
- for (const b of bytes) str += String.fromCharCode(b);
7440
- const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
7441
- return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
7442
- }
7443
- function randomUrlSafe(crypto2, byteLen) {
7444
- const bytes = new Uint8Array(byteLen);
7445
- crypto2.getRandomValues(bytes);
7446
- return base64UrlFromBytes(bytes);
7447
- }
7448
- async function pkceChallengeS256(crypto2, verifier) {
7449
- const data = new TextEncoder().encode(verifier);
7450
- const digest = await crypto2.subtle.digest("SHA-256", data);
7451
- return base64UrlFromBytes(new Uint8Array(digest));
7452
- }
7453
7545
  function cleanCallbackUrl(parsed) {
7454
7546
  try {
7455
7547
  const history = globalThis.history;
@@ -7483,36 +7575,6 @@ function createOidcAuthNamespace(config) {
7483
7575
  return null;
7484
7576
  }
7485
7577
  }
7486
- function decodeJwtPayload(token) {
7487
- const parts = token.split(".");
7488
- if (parts.length !== 3) return null;
7489
- try {
7490
- const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
7491
- const pad = "=".repeat((4 - b64.length % 4) % 4);
7492
- const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
7493
- return JSON.parse(decoded);
7494
- } catch {
7495
- return null;
7496
- }
7497
- }
7498
- function tokenToUser(token) {
7499
- const payload = decodeJwtPayload(token);
7500
- if (!payload || typeof payload.sub !== "string") return null;
7501
- if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
7502
- return null;
7503
- }
7504
- return {
7505
- uid: payload.sub,
7506
- email: typeof payload.email === "string" ? payload.email : "",
7507
- emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
7508
- displayName: typeof payload.name === "string" ? payload.name : void 0,
7509
- photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
7510
- isStaff: payload.is_staff === true,
7511
- isCustomer: payload.is_customer === true,
7512
- tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
7513
- ...payload
7514
- };
7515
- }
7516
7578
  function loadCachedUser() {
7517
7579
  if (cachedUser) {
7518
7580
  const exp = cachedUser.exp;
@@ -7533,7 +7595,7 @@ function createOidcAuthNamespace(config) {
7533
7595
  attemptSilentRefresh();
7534
7596
  return null;
7535
7597
  }
7536
- const user = tokenToUser(token);
7598
+ const user = jwtToNeetruUser(token);
7537
7599
  if (!user) {
7538
7600
  storage.removeItem(STORAGE_KEY);
7539
7601
  attemptSilentRefresh();
@@ -7604,7 +7666,7 @@ function createOidcAuthNamespace(config) {
7604
7666
  if (!res.ok || typeof payload?.error === "string") return false;
7605
7667
  const idToken = payload?.id_token;
7606
7668
  if (typeof idToken !== "string" || idToken.length === 0) return false;
7607
- const user = tokenToUser(idToken);
7669
+ const user = jwtToNeetruUser(idToken);
7608
7670
  if (!user) return false;
7609
7671
  const storage = getStorage();
7610
7672
  storage?.setItem(STORAGE_KEY, idToken);
@@ -7650,17 +7712,7 @@ function createOidcAuthNamespace(config) {
7650
7712
  }, msUntilExpiry + 1);
7651
7713
  }
7652
7714
  function resolveClientId() {
7653
- let clientId = config.oidcClientId;
7654
- if (!clientId && config.apiKey) {
7655
- clientId = parseApiKey(config.apiKey).keyId;
7656
- }
7657
- if (!clientId) {
7658
- throw new NeetruError(
7659
- "invalid_config",
7660
- "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
7661
- );
7662
- }
7663
- return clientId;
7715
+ return resolveOidcClientId(config);
7664
7716
  }
7665
7717
  async function handleRedirectCallback(currentUrl) {
7666
7718
  const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
@@ -7778,7 +7830,7 @@ function createOidcAuthNamespace(config) {
7778
7830
  "nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
7779
7831
  );
7780
7832
  }
7781
- const user = tokenToUser(idToken);
7833
+ const user = jwtToNeetruUser(idToken);
7782
7834
  if (!user) {
7783
7835
  throw new NeetruError(
7784
7836
  "token_exchange_failed",
@@ -7823,15 +7875,15 @@ function createOidcAuthNamespace(config) {
7823
7875
  };
7824
7876
  session.setItem(OIDC_TX_KEY, JSON.stringify(tx));
7825
7877
  const idpOrigin = resolveIdpOrigin(config.baseUrl);
7826
- const url = new URL("/api/v1/oauth/authorize", idpOrigin);
7827
- url.searchParams.set("response_type", "code");
7828
- url.searchParams.set("client_id", clientId);
7829
- url.searchParams.set("redirect_uri", redirectUri);
7830
- url.searchParams.set("scope", scope);
7831
- url.searchParams.set("state", state);
7832
- url.searchParams.set("nonce", nonce);
7833
- url.searchParams.set("code_challenge", codeChallenge);
7834
- url.searchParams.set("code_challenge_method", "S256");
7878
+ const url = buildAuthorizeUrl({
7879
+ idpOrigin,
7880
+ clientId,
7881
+ redirectUri,
7882
+ scope,
7883
+ state,
7884
+ nonce,
7885
+ codeChallenge
7886
+ });
7835
7887
  globalThis.location.assign(url.toString());
7836
7888
  return;
7837
7889
  }
@@ -7846,7 +7898,7 @@ function createOidcAuthNamespace(config) {
7846
7898
  const storage = getStorage();
7847
7899
  const token = storage?.getItem(STORAGE_KEY) ?? null;
7848
7900
  if (!token) return null;
7849
- return tokenToUser(token) ? token : null;
7901
+ return jwtToNeetruUser(token) ? token : null;
7850
7902
  },
7851
7903
  async signOut() {
7852
7904
  const storage = getStorage();
@@ -7971,7 +8023,7 @@ function createNeetruClient(config = {}) {
7971
8023
  productId: config.productId,
7972
8024
  tenantId: config.tenantId
7973
8025
  });
7974
- const isDev = env === "dev";
8026
+ const isDev = env === "dev" && !isProductionRuntime();
7975
8027
  const auth = config.mocks?.auth ?? (isDev ? new MockAuth({ ...DEV_FIXTURE_USER }) : createOidcAuthNamespace(resolved));
7976
8028
  const usage = config.mocks?.usage ?? (isDev ? new MockUsage() : createUsageNamespace(resolved));
7977
8029
  const support = config.mocks?.support ?? (isDev ? new MockSupport() : createSupportNamespace(resolved));
@@ -8009,7 +8061,7 @@ function getServerNeetruClient(config = {}) {
8009
8061
  init_errors();
8010
8062
  init_db_errors();
8011
8063
  init_http();
8012
- var VERSION = "3.4.6";
8064
+ var VERSION = "3.6.0";
8013
8065
 
8014
8066
  export { DEFAULT_BASE_URL, DEV_FIXTURE_USER, MockAi, MockAuth, MockCheckout, MockDb, MockEntitlements, MockNotifications, MockSupport, MockUsage, MockWebhooks, NEETRU_SENTINEL_KEY, NeetruDbError, NeetruError, VERSION, checkCoreVersionCompat, createAiNamespace, createCheckoutNamespace, createNeetruClient, createNeetruDb, createNotificationsNamespace, createWebhooksNamespace, getServerNeetruClient, increment, isFieldSentinel, isIncrementSentinel, isServerTimestampSentinel, serverTimestamp, verifyWebhookRequest, verifyWebhookSignature };
8015
8067
  //# sourceMappingURL=index.mjs.map