@reauth-dev/sdk 0.2.0 → 0.3.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/dist/chunk-5LFJ5PXQ.mjs +1042 -0
- package/dist/index.d.mts +182 -4
- package/dist/index.d.ts +182 -4
- package/dist/index.js +706 -0
- package/dist/index.mjs +1 -1
- package/dist/react/index.d.mts +62 -2
- package/dist/react/index.d.ts +62 -2
- package/dist/react/index.js +848 -11
- package/dist/react/index.mjs +134 -4
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +4 -0
- package/dist/server.mjs +4 -0
- package/dist/{types-BqZzje-y.d.mts → types-DKUKhCNE.d.mts} +165 -3
- package/dist/{types-BqZzje-y.d.ts → types-DKUKhCNE.d.ts} +165 -3
- package/package.json +1 -1
- package/dist/chunk-DMNMTW2C.mjs +0 -336
package/dist/chunk-DMNMTW2C.mjs
DELETED
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_TIMEOUT_MS
|
|
3
|
-
} from "./chunk-EY5LQCDG.mjs";
|
|
4
|
-
|
|
5
|
-
// src/client.ts
|
|
6
|
-
function assertHttpsUrl(url) {
|
|
7
|
-
let parsed;
|
|
8
|
-
try {
|
|
9
|
-
parsed = new URL(url);
|
|
10
|
-
} catch {
|
|
11
|
-
throw new Error("URL must use HTTPS");
|
|
12
|
-
}
|
|
13
|
-
if (parsed.protocol !== "https:") {
|
|
14
|
-
throw new Error("URL must use HTTPS");
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function createReauthClient(config) {
|
|
18
|
-
const { domain } = config;
|
|
19
|
-
if (config.timeout !== void 0 && (!Number.isFinite(config.timeout) || config.timeout <= 0)) {
|
|
20
|
-
throw new Error("timeout must be a positive finite number in milliseconds");
|
|
21
|
-
}
|
|
22
|
-
const timeoutMs = config.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
23
|
-
const baseUrl = `https://reauth.${domain}/api/public`;
|
|
24
|
-
return {
|
|
25
|
-
/**
|
|
26
|
-
* Redirect the user to the reauth.dev login page.
|
|
27
|
-
* After successful login, they'll be redirected back to your configured redirect URL.
|
|
28
|
-
*/
|
|
29
|
-
login() {
|
|
30
|
-
if (typeof window === "undefined") {
|
|
31
|
-
throw new Error("login() can only be called in browser");
|
|
32
|
-
}
|
|
33
|
-
window.location.href = `https://reauth.${domain}/`;
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Check if the user is authenticated.
|
|
37
|
-
* Returns session info including user ID, email, and roles.
|
|
38
|
-
*/
|
|
39
|
-
async getSession() {
|
|
40
|
-
const res = await fetch(`${baseUrl}/auth/session`, {
|
|
41
|
-
credentials: "include",
|
|
42
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
43
|
-
});
|
|
44
|
-
if (!res.ok) {
|
|
45
|
-
throw new Error(`Failed to get session: ${res.status}`);
|
|
46
|
-
}
|
|
47
|
-
return res.json();
|
|
48
|
-
},
|
|
49
|
-
/**
|
|
50
|
-
* Refresh the access token using the refresh token.
|
|
51
|
-
* Call this when getSession() returns valid: false but no error_code.
|
|
52
|
-
* @throws Error on failed refresh (401) or server error
|
|
53
|
-
*/
|
|
54
|
-
async refresh() {
|
|
55
|
-
const res = await fetch(`${baseUrl}/auth/refresh`, {
|
|
56
|
-
method: "POST",
|
|
57
|
-
credentials: "include",
|
|
58
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
59
|
-
});
|
|
60
|
-
if (!res.ok) {
|
|
61
|
-
throw new Error(`Failed to refresh: ${res.status}`);
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
/**
|
|
65
|
-
* Get an access token for Bearer authentication.
|
|
66
|
-
* Use this when calling your own API that uses local token verification.
|
|
67
|
-
*
|
|
68
|
-
* @returns TokenResponse with access token, or null if not authenticated or network unreachable
|
|
69
|
-
* @throws Error on server errors (non-401 HTTP status codes) or request timeout
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```typescript
|
|
73
|
-
* try {
|
|
74
|
-
* const tokenResponse = await reauth.getToken();
|
|
75
|
-
* if (tokenResponse) {
|
|
76
|
-
* fetch('/api/data', {
|
|
77
|
-
* headers: { Authorization: `Bearer ${tokenResponse.accessToken}` }
|
|
78
|
-
* });
|
|
79
|
-
* }
|
|
80
|
-
* } catch (err) {
|
|
81
|
-
* // Server error or timeout — do not log the user out
|
|
82
|
-
* }
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
async getToken() {
|
|
86
|
-
try {
|
|
87
|
-
const res = await fetch(`${baseUrl}/auth/token`, {
|
|
88
|
-
method: "GET",
|
|
89
|
-
credentials: "include",
|
|
90
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
91
|
-
});
|
|
92
|
-
if (!res.ok) {
|
|
93
|
-
if (res.status === 401) return null;
|
|
94
|
-
throw new Error(`Failed to get token: ${res.status}`);
|
|
95
|
-
}
|
|
96
|
-
const data = await res.json();
|
|
97
|
-
return {
|
|
98
|
-
accessToken: data.access_token,
|
|
99
|
-
expiresIn: data.expires_in,
|
|
100
|
-
tokenType: data.token_type
|
|
101
|
-
};
|
|
102
|
-
} catch (err) {
|
|
103
|
-
if (err instanceof TypeError) return null;
|
|
104
|
-
throw err;
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
/**
|
|
108
|
-
* Log out the user by clearing all session cookies.
|
|
109
|
-
* @throws Error on server error
|
|
110
|
-
*/
|
|
111
|
-
async logout() {
|
|
112
|
-
const res = await fetch(`${baseUrl}/auth/logout`, {
|
|
113
|
-
method: "POST",
|
|
114
|
-
credentials: "include",
|
|
115
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
116
|
-
});
|
|
117
|
-
if (!res.ok) {
|
|
118
|
-
throw new Error(`Failed to logout: ${res.status}`);
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
/**
|
|
122
|
-
* Delete the user's own account (self-service).
|
|
123
|
-
* @throws Error on permission denied or server error
|
|
124
|
-
*/
|
|
125
|
-
async deleteAccount() {
|
|
126
|
-
const res = await fetch(`${baseUrl}/auth/account`, {
|
|
127
|
-
method: "DELETE",
|
|
128
|
-
credentials: "include",
|
|
129
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
130
|
-
});
|
|
131
|
-
if (!res.ok) {
|
|
132
|
-
throw new Error(`Failed to delete account: ${res.status}`);
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
// ========================================================================
|
|
136
|
-
// Billing Methods
|
|
137
|
-
// ========================================================================
|
|
138
|
-
/**
|
|
139
|
-
* Get available subscription plans for the domain.
|
|
140
|
-
* Only returns public plans sorted by display order.
|
|
141
|
-
* @throws Error on server error
|
|
142
|
-
*/
|
|
143
|
-
async getPlans() {
|
|
144
|
-
const res = await fetch(`${baseUrl}/billing/plans`, {
|
|
145
|
-
credentials: "include",
|
|
146
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
147
|
-
});
|
|
148
|
-
if (!res.ok) {
|
|
149
|
-
throw new Error(`Failed to get plans: ${res.status}`);
|
|
150
|
-
}
|
|
151
|
-
const data = await res.json();
|
|
152
|
-
return data.map(
|
|
153
|
-
(p) => ({
|
|
154
|
-
id: p.id,
|
|
155
|
-
code: p.code,
|
|
156
|
-
name: p.name,
|
|
157
|
-
description: p.description,
|
|
158
|
-
priceCents: p.price_cents,
|
|
159
|
-
currency: p.currency,
|
|
160
|
-
interval: p.interval,
|
|
161
|
-
intervalCount: p.interval_count,
|
|
162
|
-
trialDays: p.trial_days,
|
|
163
|
-
features: p.features.map((f) => ({
|
|
164
|
-
code: f.code,
|
|
165
|
-
name: f.name,
|
|
166
|
-
featureType: f.feature_type,
|
|
167
|
-
numericValue: f.numeric_value,
|
|
168
|
-
unitLabel: f.unit_label
|
|
169
|
-
})),
|
|
170
|
-
displayOrder: p.display_order,
|
|
171
|
-
creditsAmount: p.credits_amount,
|
|
172
|
-
planType: p.plan_type,
|
|
173
|
-
contactUrl: p.contact_url
|
|
174
|
-
})
|
|
175
|
-
);
|
|
176
|
-
},
|
|
177
|
-
/**
|
|
178
|
-
* Get the current user's subscription status.
|
|
179
|
-
*/
|
|
180
|
-
async getSubscription() {
|
|
181
|
-
const res = await fetch(`${baseUrl}/billing/subscription`, {
|
|
182
|
-
credentials: "include",
|
|
183
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
184
|
-
});
|
|
185
|
-
if (!res.ok) {
|
|
186
|
-
throw new Error(`Failed to get subscription: ${res.status}`);
|
|
187
|
-
}
|
|
188
|
-
const data = await res.json();
|
|
189
|
-
return {
|
|
190
|
-
id: data.id,
|
|
191
|
-
planCode: data.plan_code,
|
|
192
|
-
planName: data.plan_name,
|
|
193
|
-
status: data.status,
|
|
194
|
-
currentPeriodEnd: data.current_period_end,
|
|
195
|
-
trialEnd: data.trial_end,
|
|
196
|
-
cancelAtPeriodEnd: data.cancel_at_period_end
|
|
197
|
-
};
|
|
198
|
-
},
|
|
199
|
-
/**
|
|
200
|
-
* Create a Stripe checkout session to subscribe to a plan.
|
|
201
|
-
* @param planCode The plan code to subscribe to
|
|
202
|
-
* @param successUrl URL to redirect to after successful payment
|
|
203
|
-
* @param cancelUrl URL to redirect to if checkout is canceled
|
|
204
|
-
* @returns Checkout session with URL to redirect the user to
|
|
205
|
-
*/
|
|
206
|
-
async createCheckout(planCode, successUrl, cancelUrl) {
|
|
207
|
-
const res = await fetch(`${baseUrl}/billing/checkout`, {
|
|
208
|
-
method: "POST",
|
|
209
|
-
headers: { "Content-Type": "application/json" },
|
|
210
|
-
credentials: "include",
|
|
211
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
212
|
-
body: JSON.stringify({
|
|
213
|
-
plan_code: planCode,
|
|
214
|
-
success_url: successUrl,
|
|
215
|
-
cancel_url: cancelUrl
|
|
216
|
-
})
|
|
217
|
-
});
|
|
218
|
-
if (!res.ok) {
|
|
219
|
-
const err = await res.json().catch(() => ({}));
|
|
220
|
-
throw new Error(err.message || "Failed to create checkout session");
|
|
221
|
-
}
|
|
222
|
-
const data = await res.json();
|
|
223
|
-
return { checkoutUrl: data.checkout_url };
|
|
224
|
-
},
|
|
225
|
-
/**
|
|
226
|
-
* Redirect user to subscribe to a plan.
|
|
227
|
-
* Creates a checkout session and redirects to Stripe.
|
|
228
|
-
* @param planCode The plan code to subscribe to
|
|
229
|
-
*/
|
|
230
|
-
async subscribe(planCode) {
|
|
231
|
-
if (typeof window === "undefined") {
|
|
232
|
-
throw new Error("subscribe() can only be called in browser");
|
|
233
|
-
}
|
|
234
|
-
const currentUrl = window.location.href;
|
|
235
|
-
const { checkoutUrl } = await this.createCheckout(
|
|
236
|
-
planCode,
|
|
237
|
-
currentUrl,
|
|
238
|
-
currentUrl
|
|
239
|
-
);
|
|
240
|
-
assertHttpsUrl(checkoutUrl);
|
|
241
|
-
window.location.href = checkoutUrl;
|
|
242
|
-
},
|
|
243
|
-
/**
|
|
244
|
-
* Open the Stripe customer portal for managing subscription.
|
|
245
|
-
* @param returnUrl URL to return to after leaving the portal
|
|
246
|
-
*/
|
|
247
|
-
async openBillingPortal(returnUrl) {
|
|
248
|
-
if (typeof window === "undefined") {
|
|
249
|
-
throw new Error("openBillingPortal() can only be called in browser");
|
|
250
|
-
}
|
|
251
|
-
const res = await fetch(`${baseUrl}/billing/portal`, {
|
|
252
|
-
method: "POST",
|
|
253
|
-
headers: { "Content-Type": "application/json" },
|
|
254
|
-
credentials: "include",
|
|
255
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
256
|
-
body: JSON.stringify({
|
|
257
|
-
return_url: returnUrl || window.location.href
|
|
258
|
-
})
|
|
259
|
-
});
|
|
260
|
-
if (!res.ok) {
|
|
261
|
-
throw new Error("Failed to open billing portal");
|
|
262
|
-
}
|
|
263
|
-
const data = await res.json();
|
|
264
|
-
assertHttpsUrl(data.portal_url);
|
|
265
|
-
window.location.href = data.portal_url;
|
|
266
|
-
},
|
|
267
|
-
/**
|
|
268
|
-
* Cancel the user's subscription at period end.
|
|
269
|
-
* @throws Error on failure or server error
|
|
270
|
-
*/
|
|
271
|
-
async cancelSubscription() {
|
|
272
|
-
const res = await fetch(`${baseUrl}/billing/cancel`, {
|
|
273
|
-
method: "POST",
|
|
274
|
-
credentials: "include",
|
|
275
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
276
|
-
});
|
|
277
|
-
if (!res.ok) {
|
|
278
|
-
throw new Error(`Failed to cancel subscription: ${res.status}`);
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
// ========================================================================
|
|
282
|
-
// Balance Methods
|
|
283
|
-
// ========================================================================
|
|
284
|
-
/**
|
|
285
|
-
* Get the current user's balance.
|
|
286
|
-
* @returns Object with the current balance
|
|
287
|
-
*/
|
|
288
|
-
async getBalance() {
|
|
289
|
-
const res = await fetch(`${baseUrl}/balance`, {
|
|
290
|
-
credentials: "include",
|
|
291
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
292
|
-
});
|
|
293
|
-
if (!res.ok) {
|
|
294
|
-
if (res.status === 401) throw new Error("Not authenticated");
|
|
295
|
-
throw new Error(`Failed to get balance: ${res.status}`);
|
|
296
|
-
}
|
|
297
|
-
const data = await res.json();
|
|
298
|
-
return { balance: data.balance };
|
|
299
|
-
},
|
|
300
|
-
/**
|
|
301
|
-
* Get the current user's balance transaction history.
|
|
302
|
-
* @param opts - Optional pagination (limit, offset)
|
|
303
|
-
* @returns Object with array of transactions (newest first)
|
|
304
|
-
*/
|
|
305
|
-
async getTransactions(opts) {
|
|
306
|
-
const params = new URLSearchParams();
|
|
307
|
-
if (opts?.limit !== void 0) params.set("limit", String(opts.limit));
|
|
308
|
-
if (opts?.offset !== void 0) params.set("offset", String(opts.offset));
|
|
309
|
-
const qs = params.toString();
|
|
310
|
-
const res = await fetch(
|
|
311
|
-
`${baseUrl}/balance/transactions${qs ? `?${qs}` : ""}`,
|
|
312
|
-
{ credentials: "include", signal: AbortSignal.timeout(timeoutMs) }
|
|
313
|
-
);
|
|
314
|
-
if (!res.ok) {
|
|
315
|
-
if (res.status === 401) throw new Error("Not authenticated");
|
|
316
|
-
throw new Error(`Failed to get transactions: ${res.status}`);
|
|
317
|
-
}
|
|
318
|
-
const data = await res.json();
|
|
319
|
-
return {
|
|
320
|
-
transactions: data.transactions.map(
|
|
321
|
-
(t) => ({
|
|
322
|
-
id: t.id,
|
|
323
|
-
amountDelta: t.amount_delta,
|
|
324
|
-
reason: t.reason,
|
|
325
|
-
balanceAfter: t.balance_after,
|
|
326
|
-
createdAt: t.created_at
|
|
327
|
-
})
|
|
328
|
-
)
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export {
|
|
335
|
-
createReauthClient
|
|
336
|
-
};
|