@nozle-js/react 0.5.2 → 0.7.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/README.md CHANGED
@@ -1,241 +1,59 @@
1
1
  # @nozle-js/react
2
2
 
3
- React SDK for usage-based billing. Hooks and components for entitlements, real-time usage tracking, plan management, and Stripe checkout.
3
+ Browser-safe React components for Nozle's public plan catalog and merchant-controlled checkout.
4
4
 
5
- ## Install
5
+ ## Credential boundary
6
6
 
7
- ```bash
8
- npm install @nozle-js/react
9
- ```
7
+ - `pk_` is used only for `GET /api/v1/plans`.
8
+ - Secret keys stay on the merchant backend.
9
+ - The React package does not fetch customer billing, invoice, subscription, entitlement, or credit data.
10
+ - The React package never sends a customer ID.
10
11
 
11
- Peer dependencies:
12
+ ## Install
12
13
 
13
14
  ```bash
14
- npm install react react-dom @stripe/stripe-js @stripe/react-stripe-js
15
+ npm install @nozle-js/react react react-dom @stripe/stripe-js @stripe/react-stripe-js
15
16
  ```
16
17
 
17
- ## Quick Start
18
-
19
- Wrap your app with `BillingProvider`:
18
+ ## Merchant-backed checkout
20
19
 
21
20
  ```tsx
22
- import { BillingProvider } from "@nozle-js/react";
21
+ import { BillingProvider, PricingTable } from "@nozle-js/react";
23
22
 
24
- function App() {
23
+ export function BillingPage({ csrfToken }: { csrfToken: string }) {
25
24
  return (
26
25
  <BillingProvider
27
- apiKey="pk_live_..."
28
- baseUrl="https://api.nozle.app" // Default: https://api.nozle.app
29
- workspaceId="ws_123" // Optional: workspace scoping
30
- centrifugoUrl="wss://ws.nozle.app/connection/websocket" // Optional: real-time updates
26
+ publishableKey={import.meta.env.VITE_NOZLE_PUBLISHABLE_KEY}
27
+ createCheckout={async ({ planCode, returnUrl }) => {
28
+ const response = await fetch("/api/billing/checkout", {
29
+ method: "POST",
30
+ credentials: "include",
31
+ headers: {
32
+ "Content-Type": "application/json",
33
+ "X-CSRF-Token": csrfToken,
34
+ },
35
+ body: JSON.stringify({ planCode, returnUrl }),
36
+ });
37
+
38
+ if (!response.ok) throw new Error("Checkout failed");
39
+ return response.json();
40
+ }}
31
41
  >
32
- <YourApp />
42
+ <PricingTable returnUrl={window.location.href} highlightPlan="pro" />
33
43
  </BillingProvider>
34
44
  );
35
45
  }
36
46
  ```
37
47
 
38
- > **Note:** LLM wrappers (`wrapOpenAI`, `wrapAnthropic`) and server-side methods (`checkAndDeduct`, `customers.upsert`) are only available in `@nozle-js/node`. The React SDK is for client-side billing UI only.
39
-
40
- ## Hooks
41
-
42
- ### `useCan(feature)`
43
-
44
- Check if a customer has access to a feature.
45
-
46
- ```tsx
47
- import { useCan } from "@nozle-js/react";
48
-
49
- function MyFeature() {
50
- const { allowed, isLoading, error } = useCan("advanced_analytics");
51
-
52
- if (isLoading) return <p>Loading...</p>;
53
- if (!allowed) return <p>Upgrade to access this feature.</p>;
54
-
55
- return <div>Feature content here</div>;
56
- }
57
- ```
58
-
59
- ### `useUsage(metric)`
60
-
61
- Get real-time usage data for a metric. Updates automatically via WebSocket.
62
-
63
- ```tsx
64
- import { useUsage } from "@nozle-js/react";
65
-
66
- function TokenCounter() {
67
- const { data, isLoading } = useUsage("tokens_used");
68
-
69
- if (isLoading || !data) return null;
70
-
71
- return (
72
- <p>
73
- {data.used.toLocaleString()} / {data.limit.toLocaleString()} tokens used
74
- </p>
75
- );
76
- }
77
- ```
78
-
79
- ### `usePlan()`
80
-
81
- Get the customer's current plan and subscription status.
82
-
83
- ```tsx
84
- import { usePlan } from "@nozle-js/react";
85
-
86
- function CurrentPlan() {
87
- const { data } = usePlan();
88
-
89
- if (!data) return null;
90
-
91
- return (
92
- <p>
93
- Plan: {data.plan_slug} ({data.subscription_status})
94
- </p>
95
- );
96
- }
97
- ```
98
-
99
- ### `usePlans()`
100
-
101
- Fetch all available plans.
102
-
103
- ```tsx
104
- import { usePlans } from "@nozle-js/react";
105
-
106
- function PlanList() {
107
- const { plans, isLoading } = usePlans();
108
-
109
- if (isLoading) return <p>Loading plans...</p>;
110
-
111
- return (
112
- <ul>
113
- {plans.map((plan) => (
114
- <li key={plan.code}>
115
- {plan.name} — ${(plan.amount_cents / 100).toFixed(2)}/{plan.interval}
116
- </li>
117
- ))}
118
- </ul>
119
- );
120
- }
121
- ```
122
-
123
- ### `useCheckout()`
48
+ The merchant endpoint authenticates the user, derives the Nozle customer from the authenticated user or team, validates the plan and HTTPS return URL, and calls Nozle with a restricted server-side `sk_`. Any browser-supplied customer identifier must be ignored or rejected.
124
49
 
125
- Create a Stripe checkout session and render embedded checkout.
126
-
127
- ```tsx
128
- import { useCheckout } from "@nozle-js/react";
129
-
130
- function UpgradeButton({ planCode }: { planCode: string }) {
131
- const { fetchClientSecret, isLoading } = useCheckout();
132
-
133
- const handleUpgrade = async () => {
134
- const clientSecret = await fetchClientSecret(planCode);
135
- // Use clientSecret with Stripe EmbeddedCheckout
136
- };
137
-
138
- return (
139
- <button onClick={handleUpgrade} disabled={isLoading}>
140
- Upgrade
141
- </button>
142
- );
143
- }
144
- ```
145
-
146
- ### `useSubscribe()`
147
-
148
- Create a subscription after successful payment.
149
-
150
- ```tsx
151
- import { useSubscribe } from "@nozle-js/react";
152
-
153
- function AfterPayment({ planCode }: { planCode: string }) {
154
- const { subscribe, isLoading } = useSubscribe();
155
-
156
- const handleComplete = async () => {
157
- await subscribe(planCode);
158
- };
159
-
160
- return (
161
- <button onClick={handleComplete} disabled={isLoading}>
162
- Activate Subscription
163
- </button>
164
- );
165
- }
166
- ```
50
+ `createCheckout` may return a hosted URL, an embedded Stripe client secret, `type: "completed"`, or `type: "scheduled"`. Paid plans activate only after Nozle processes verified Stripe success; a browser redirect is not proof of payment.
167
51
 
168
52
  ## Components
169
53
 
170
- Pre-built UI components with built-in styling. No CSS imports needed.
171
-
172
- ### `UsageMeter`
173
-
174
- Displays usage with bar, ring, or minimal variants.
175
-
176
- ```tsx
177
- import { UsageMeter } from "@nozle-js/react";
178
-
179
- <UsageMeter metric="tokens_used" variant="bar" />
180
- <UsageMeter metric="tokens_used" variant="ring" />
181
- <UsageMeter metric="tokens_used" variant="minimal" />
182
- ```
183
-
184
- ### `PlanBadge`
185
-
186
- Shows the current plan with status indicator.
187
-
188
- ```tsx
189
- import { PlanBadge } from "@nozle-js/react";
190
-
191
- <PlanBadge variant="pill" />
192
- <PlanBadge variant="text" />
193
- <PlanBadge variant="icon" />
194
- ```
195
-
196
- ### `UpgradePrompt`
197
-
198
- Conditionally renders an upgrade prompt when a feature is gated.
199
-
200
- ```tsx
201
- import { UpgradePrompt } from "@nozle-js/react";
202
-
203
- <UpgradePrompt feature="advanced_analytics" variant="card" upgradeUrl="/upgrade" />
204
- <UpgradePrompt feature="advanced_analytics" variant="banner" />
205
- <UpgradePrompt feature="advanced_analytics" variant="inline" />
206
- ```
207
-
208
- ## Tailwind CSS Preset
209
-
210
- Optional Tailwind preset for styling the `data-nozle` attributes on components.
211
-
212
- ```ts
213
- // tailwind.config.ts
214
- import { nozlePreset } from "@nozle-js/react/styles/preset";
215
-
216
- export default {
217
- presets: [nozlePreset],
218
- };
219
- ```
220
-
221
- ## TypeScript
222
-
223
- All hooks and components are fully typed. Exported types:
224
-
225
- ```ts
226
- import type {
227
- BillingState,
228
- UseCanResult,
229
- UseUsageResult,
230
- UsePlanResult,
231
- UseCheckoutResult,
232
- Plan,
233
- UsageMeterProps,
234
- PlanBadgeProps,
235
- UpgradePromptProps,
236
- } from "@nozle-js/react";
237
- ```
238
-
239
- ## License
54
+ - `PricingTable` and `usePlans` read the public catalog with the publishable key.
55
+ - `CheckoutButton`, `UpgradeButton`, `UpgradeModal`, and the default `PricingTable` CTA call the merchant's `createCheckout` callback.
56
+ - `Checkout` renders Stripe hosted/embedded checkout results supplied by the merchant.
57
+ - Gates, usage displays, `PlanBadge`, and `PaymentMethodDisplay` are presentational and consume caller-supplied data.
240
58
 
241
- Proprietary
59
+ Customer billing, invoices, cancellation, top-ups, subscriptions, entitlements, and credits belong behind authenticated merchant endpoints. Never put an `sk_`, master key, or internal credential in browser code.