@neetru/sdk 3.4.2 → 3.4.4

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 (58) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/ai.d.cts +1 -1
  3. package/dist/ai.d.ts +1 -1
  4. package/dist/auth.cjs +17 -7
  5. package/dist/auth.cjs.map +1 -1
  6. package/dist/auth.d.cts +1 -1
  7. package/dist/auth.d.ts +1 -1
  8. package/dist/auth.mjs +17 -7
  9. package/dist/auth.mjs.map +1 -1
  10. package/dist/build-guard.cjs +98 -0
  11. package/dist/build-guard.cjs.map +1 -1
  12. package/dist/build-guard.d.cts +63 -1
  13. package/dist/build-guard.d.ts +63 -1
  14. package/dist/build-guard.mjs +93 -1
  15. package/dist/build-guard.mjs.map +1 -1
  16. package/dist/catalog.d.cts +1 -1
  17. package/dist/catalog.d.ts +1 -1
  18. package/dist/checkout.cjs +17 -7
  19. package/dist/checkout.cjs.map +1 -1
  20. package/dist/checkout.d.cts +1 -1
  21. package/dist/checkout.d.ts +1 -1
  22. package/dist/checkout.mjs +17 -7
  23. package/dist/checkout.mjs.map +1 -1
  24. package/dist/db-react.d.cts +1 -1
  25. package/dist/db-react.d.ts +1 -1
  26. package/dist/db.d.cts +1 -1
  27. package/dist/db.d.ts +1 -1
  28. package/dist/entitlements.d.cts +1 -1
  29. package/dist/entitlements.d.ts +1 -1
  30. package/dist/firestore-compat.d.cts +1 -1
  31. package/dist/firestore-compat.d.ts +1 -1
  32. package/dist/index.cjs +18 -8
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.mjs +18 -8
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/mocks.d.cts +1 -1
  39. package/dist/mocks.d.ts +1 -1
  40. package/dist/notifications.d.cts +1 -1
  41. package/dist/notifications.d.ts +1 -1
  42. package/dist/react.cjs +62 -3
  43. package/dist/react.cjs.map +1 -1
  44. package/dist/react.d.cts +38 -7
  45. package/dist/react.d.ts +38 -7
  46. package/dist/react.mjs +62 -3
  47. package/dist/react.mjs.map +1 -1
  48. package/dist/support.d.cts +1 -1
  49. package/dist/support.d.ts +1 -1
  50. package/dist/telemetry.d.cts +1 -1
  51. package/dist/telemetry.d.ts +1 -1
  52. package/dist/{types-BlOLDMR0.d.ts → types-Bzxb5rlF.d.ts} +26 -8
  53. package/dist/{types-D-QdG502.d.cts → types-Dw0fqhHm.d.cts} +26 -8
  54. package/dist/usage.d.cts +1 -1
  55. package/dist/usage.d.ts +1 -1
  56. package/dist/webhooks.d.cts +1 -1
  57. package/dist/webhooks.d.ts +1 -1
  58. package/package.json +1 -1
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { W as NeetruClient, t as CheckoutStartResult, l as AuthNamespace, a5 as NeetruUser } from './types-D-QdG502.cjs';
2
+ import { W as NeetruClient, t as CheckoutStartResult, l as AuthNamespace, a5 as NeetruUser } from './types-Dw0fqhHm.cjs';
3
3
  import { CollectionReference, Query, DocumentReference } from './firestore-compat.cjs';
4
4
  import 'drizzle-orm/node-postgres';
5
5
  import './errors.cjs';
@@ -121,8 +121,27 @@ declare function NeetruAccountBar({ client, currentProductSlug, settingsUrl, onS
121
121
  */
122
122
 
123
123
  interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'onClick' | 'onError'> {
124
- /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */
125
- client: NeetruClient;
124
+ /**
125
+ * Cliente SDK Neetru. Passado explicitamente pra evitar context provider.
126
+ *
127
+ * **Opcional** quando `startPath` é usado (padrão BFF/cookie recomendado): o
128
+ * browser não tem token nem client, o start acontece no route BFF do app.
129
+ * Obrigatório no modo legado (client-side start), quando o browser tem o token.
130
+ */
131
+ client?: NeetruClient;
132
+ /**
133
+ * **BFF/cookie (padrão recomendado):** path do route do PRÓPRIO app que inicia
134
+ * o checkout server-side (ex: `/api/checkout/start`). Quando presente, o clique
135
+ * faz `POST` nesse path (same-origin, `credentials: 'include'` → manda o cookie
136
+ * httpOnly de sessão), o route lê o id_token do cookie e chama o Core
137
+ * server-side, devolvendo `{ redirectUrl }`. Assim o **browser nunca precisa do
138
+ * access_token** — que no padrão BFF é descartado no servidor.
139
+ *
140
+ * A resposta esperada do route BFF é `{ redirectUrl, intentId?, status?,
141
+ * expiresAt?, requiresKyc? }` (ou `{ intent: { redirectUrl, ... } }`). Sem
142
+ * `startPath`, o componente cai no modo legado `client.checkout.start()`.
143
+ */
144
+ startPath?: string;
126
145
  /** Slug do produto (ex: `neetru-pulse`). */
127
146
  productId: string;
128
147
  /** Plan id (ex: `pro_monthly`). */
@@ -144,12 +163,16 @@ interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEl
144
163
  href?: string;
145
164
  }
146
165
  /**
147
- * Wrapper de `<a>` que dispara `client.checkout.start()` no click.
166
+ * Wrapper de `<a>` que inicia o checkout no click.
148
167
  *
149
- * Uso típico:
168
+ * Dois modos:
169
+ *
170
+ * **1. BFF/cookie (recomendado)** — passe `startPath`. O browser NÃO precisa de
171
+ * token; o clique faz `POST` no route do seu app, que inicia o checkout
172
+ * server-side com o id_token do cookie httpOnly:
150
173
  * ```tsx
151
174
  * <CheckoutLink
152
- * client={client}
175
+ * startPath="/api/checkout/start"
153
176
  * productId="meu-saas"
154
177
  * planId="pro_monthly"
155
178
  * callbackUrl="https://meu-saas.com/billing/success"
@@ -158,10 +181,18 @@ interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEl
158
181
  * </CheckoutLink>
159
182
  * ```
160
183
  *
184
+ * **2. Legado (client-side)** — passe `client`. Só funciona se o browser tiver o
185
+ * token (SPA não-BFF que guarda o access_token no browser). Chama
186
+ * `client.checkout.start()` direto:
187
+ * ```tsx
188
+ * <CheckoutLink client={client} productId="meu-saas" planId="pro_monthly"
189
+ * callbackUrl="https://meu-saas.com/billing/success">Assinar Pro</CheckoutLink>
190
+ * ```
191
+ *
161
192
  * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview
162
193
  * de URL no hover (pode ser sobrescrito via prop spread).
163
194
  */
164
- declare function CheckoutLink({ client, productId, planId, callbackUrl, tenantType, tenantId, children, onIntentCreated, onError, noAutoRedirect, ...rest }: CheckoutLinkProps): React.ReactElement;
195
+ declare function CheckoutLink({ client, startPath, productId, planId, callbackUrl, tenantType, tenantId, children, onIntentCreated, onError, noAutoRedirect, ...rest }: CheckoutLinkProps): React.ReactElement;
165
196
  interface NeetruLoginButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'onError' | 'children' | 'style'> {
166
197
  /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */
167
198
  client: NeetruClient;
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { W as NeetruClient, t as CheckoutStartResult, l as AuthNamespace, a5 as NeetruUser } from './types-BlOLDMR0.js';
2
+ import { W as NeetruClient, t as CheckoutStartResult, l as AuthNamespace, a5 as NeetruUser } from './types-Bzxb5rlF.js';
3
3
  import { CollectionReference, Query, DocumentReference } from './firestore-compat.js';
4
4
  import 'drizzle-orm/node-postgres';
5
5
  import './errors.js';
@@ -121,8 +121,27 @@ declare function NeetruAccountBar({ client, currentProductSlug, settingsUrl, onS
121
121
  */
122
122
 
123
123
  interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'onClick' | 'onError'> {
124
- /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */
125
- client: NeetruClient;
124
+ /**
125
+ * Cliente SDK Neetru. Passado explicitamente pra evitar context provider.
126
+ *
127
+ * **Opcional** quando `startPath` é usado (padrão BFF/cookie recomendado): o
128
+ * browser não tem token nem client, o start acontece no route BFF do app.
129
+ * Obrigatório no modo legado (client-side start), quando o browser tem o token.
130
+ */
131
+ client?: NeetruClient;
132
+ /**
133
+ * **BFF/cookie (padrão recomendado):** path do route do PRÓPRIO app que inicia
134
+ * o checkout server-side (ex: `/api/checkout/start`). Quando presente, o clique
135
+ * faz `POST` nesse path (same-origin, `credentials: 'include'` → manda o cookie
136
+ * httpOnly de sessão), o route lê o id_token do cookie e chama o Core
137
+ * server-side, devolvendo `{ redirectUrl }`. Assim o **browser nunca precisa do
138
+ * access_token** — que no padrão BFF é descartado no servidor.
139
+ *
140
+ * A resposta esperada do route BFF é `{ redirectUrl, intentId?, status?,
141
+ * expiresAt?, requiresKyc? }` (ou `{ intent: { redirectUrl, ... } }`). Sem
142
+ * `startPath`, o componente cai no modo legado `client.checkout.start()`.
143
+ */
144
+ startPath?: string;
126
145
  /** Slug do produto (ex: `neetru-pulse`). */
127
146
  productId: string;
128
147
  /** Plan id (ex: `pro_monthly`). */
@@ -144,12 +163,16 @@ interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEl
144
163
  href?: string;
145
164
  }
146
165
  /**
147
- * Wrapper de `<a>` que dispara `client.checkout.start()` no click.
166
+ * Wrapper de `<a>` que inicia o checkout no click.
148
167
  *
149
- * Uso típico:
168
+ * Dois modos:
169
+ *
170
+ * **1. BFF/cookie (recomendado)** — passe `startPath`. O browser NÃO precisa de
171
+ * token; o clique faz `POST` no route do seu app, que inicia o checkout
172
+ * server-side com o id_token do cookie httpOnly:
150
173
  * ```tsx
151
174
  * <CheckoutLink
152
- * client={client}
175
+ * startPath="/api/checkout/start"
153
176
  * productId="meu-saas"
154
177
  * planId="pro_monthly"
155
178
  * callbackUrl="https://meu-saas.com/billing/success"
@@ -158,10 +181,18 @@ interface CheckoutLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorEl
158
181
  * </CheckoutLink>
159
182
  * ```
160
183
  *
184
+ * **2. Legado (client-side)** — passe `client`. Só funciona se o browser tiver o
185
+ * token (SPA não-BFF que guarda o access_token no browser). Chama
186
+ * `client.checkout.start()` direto:
187
+ * ```tsx
188
+ * <CheckoutLink client={client} productId="meu-saas" planId="pro_monthly"
189
+ * callbackUrl="https://meu-saas.com/billing/success">Assinar Pro</CheckoutLink>
190
+ * ```
191
+ *
161
192
  * `href` é stub (`#`) — preventDefault no click. Mantido pra a11y / preview
162
193
  * de URL no hover (pode ser sobrescrito via prop spread).
163
194
  */
164
- declare function CheckoutLink({ client, productId, planId, callbackUrl, tenantType, tenantId, children, onIntentCreated, onError, noAutoRedirect, ...rest }: CheckoutLinkProps): React.ReactElement;
195
+ declare function CheckoutLink({ client, startPath, productId, planId, callbackUrl, tenantType, tenantId, children, onIntentCreated, onError, noAutoRedirect, ...rest }: CheckoutLinkProps): React.ReactElement;
165
196
  interface NeetruLoginButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'onError' | 'children' | 'style'> {
166
197
  /** Cliente SDK Neetru. Passado explicitamente pra evitar context provider. */
167
198
  client: NeetruClient;
package/dist/react.mjs CHANGED
@@ -588,8 +588,44 @@ function normalizeOp(op) {
588
588
  }
589
589
 
590
590
  // src/react.ts
591
+ async function startCheckoutViaBff(startPath, input) {
592
+ const res = await fetch(startPath, {
593
+ method: "POST",
594
+ headers: { "content-type": "application/json", accept: "application/json" },
595
+ credentials: "include",
596
+ body: JSON.stringify(input)
597
+ });
598
+ let payload = null;
599
+ try {
600
+ payload = await res.json();
601
+ } catch {
602
+ payload = null;
603
+ }
604
+ if (!res.ok) {
605
+ const p = payload;
606
+ const msg = p && (typeof p.error === "object" && p.error?.message || typeof p.error === "string" && p.error || typeof p.message === "string" && p.message) || `Checkout BFF respondeu HTTP ${res.status}`;
607
+ throw new Error(typeof msg === "string" ? msg : `Checkout BFF respondeu HTTP ${res.status}`);
608
+ }
609
+ const intent = payload?.intent ?? payload ?? {};
610
+ const redirectUrl = payload?.redirectUrl ?? intent.redirectUrl;
611
+ if (!redirectUrl || typeof redirectUrl !== "string") {
612
+ throw new Error("Resposta do route BFF de checkout sem `redirectUrl`.");
613
+ }
614
+ return {
615
+ intentId: String(payload?.intentId ?? intent.intentId ?? ""),
616
+ redirectUrl,
617
+ status: payload?.status ?? intent.status ?? "pending",
618
+ expiresAt: typeof payload?.expiresAt === "string" ? payload.expiresAt : typeof intent.expiresAt === "string" ? intent.expiresAt : "",
619
+ requiresKyc: payload?.requiresKyc === true || intent.requiresKyc === true
620
+ };
621
+ }
622
+ function checkoutRedirect(url) {
623
+ const loc = globalThis.location;
624
+ if (loc && typeof loc.assign === "function") loc.assign(url);
625
+ }
591
626
  function CheckoutLink({
592
627
  client,
628
+ startPath,
593
629
  productId,
594
630
  planId,
595
631
  callbackUrl,
@@ -602,13 +638,36 @@ function CheckoutLink({
602
638
  ...rest
603
639
  }) {
604
640
  const [submitting, setSubmitting] = React2.useState(false);
605
- const checkout = client.checkout;
641
+ const checkout = client?.checkout;
606
642
  const handleClick = React2.useCallback(
607
643
  async (event) => {
608
644
  event.preventDefault();
609
645
  if (submitting) return;
646
+ if (startPath) {
647
+ setSubmitting(true);
648
+ try {
649
+ const result = await startCheckoutViaBff(startPath, {
650
+ productId,
651
+ planId,
652
+ callbackUrl,
653
+ tenantType,
654
+ tenantId
655
+ });
656
+ onIntentCreated?.(result);
657
+ if (!noAutoRedirect) checkoutRedirect(result.redirectUrl);
658
+ } catch (err) {
659
+ onError?.(err instanceof Error ? err : new Error(String(err)));
660
+ } finally {
661
+ setSubmitting(false);
662
+ }
663
+ return;
664
+ }
610
665
  if (!checkout || typeof checkout.start !== "function") {
611
- onError?.(new Error("SDK client missing `checkout` namespace. Upgrade @neetru/sdk to 1.1+."));
666
+ onError?.(
667
+ new Error(
668
+ "CheckoutLink: passe `startPath` (padr\xE3o BFF/cookie recomendado) OU um `client` com o namespace `checkout` (SDK 1.1+)."
669
+ )
670
+ );
612
671
  return;
613
672
  }
614
673
  setSubmitting(true);
@@ -628,7 +687,7 @@ function CheckoutLink({
628
687
  setSubmitting(false);
629
688
  }
630
689
  },
631
- [submitting, checkout, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError]
690
+ [submitting, checkout, startPath, productId, planId, callbackUrl, tenantType, tenantId, noAutoRedirect, onIntentCreated, onError]
632
691
  );
633
692
  return React2.createElement(
634
693
  "a",