@kerne/react 0.1.1 → 0.1.3

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/index.cjs CHANGED
@@ -1,731 +1,43 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- Allows: () => Allows,
34
- AuthLoading: () => AuthLoading,
35
- Authenticated: () => Authenticated,
36
- HasSubscription: () => HasSubscription,
37
- KerneClient: () => KerneClient,
38
- KerneContext: () => KerneContext,
39
- KerneErrorBoundary: () => KerneErrorBoundary,
40
- KerneProvider: () => KerneProvider,
41
- KerneStore: () => KerneStore,
42
- Protected: () => Protected,
43
- Unauthenticated: () => Unauthenticated,
44
- useAllows: () => useAllows,
45
- useAuth: () => useAuth,
46
- useCheck: () => useCheck,
47
- useCheckout: () => useCheckout,
48
- useClient: () => useClient,
49
- useEntitlements: () => useEntitlements,
50
- useInvitation: () => useInvitation,
51
- useKerneError: () => useKerneError,
52
- usePlans: () => usePlans,
53
- usePortal: () => usePortal,
54
- useSubscription: () => useSubscription,
55
- useUsage: () => useUsage,
56
- useUser: () => useUser,
57
- useWaitlist: () => useWaitlist
58
- });
59
- module.exports = __toCommonJS(index_exports);
60
-
61
- // src/provider.tsx
62
- var import_react = require("react");
63
- var import_server = require("@kerne/server");
64
- var import_jsx_runtime = require("react/jsx-runtime");
65
- var DEFAULT_STORAGE_KEY = "kerne_auth";
66
- var DEFAULT_REFRESH_BUFFER = 60;
67
- var KerneClient = class {
68
- kerne;
69
- storage;
70
- storageKey;
71
- onAuthChange;
72
- autoRefresh;
73
- refreshBuffer;
74
- refreshTimer = null;
75
- listeners = /* @__PURE__ */ new Set();
76
- _user = null;
77
- _token = null;
78
- _refreshToken = null;
79
- _expiresAt = null;
80
- _isLoading = true;
81
- // Public config properties
82
- baseUrl;
83
- appId;
84
- constructor(config) {
85
- this.baseUrl = config.baseUrl ?? "https://api.kerne.io";
86
- this.appId = config.appId;
87
- this.storage = config.storage ?? (typeof window !== "undefined" ? localStorage : null);
88
- this.storageKey = config.storageKey ?? DEFAULT_STORAGE_KEY;
89
- this.onAuthChange = config.onAuthChange;
90
- this.autoRefresh = config.autoRefresh ?? true;
91
- this.refreshBuffer = config.refreshBuffer ?? DEFAULT_REFRESH_BUFFER;
92
- this.kerne = new import_server.Kerne({
93
- baseUrl: this.baseUrl,
94
- appId: this.appId,
95
- timeout: config.timeout,
96
- onUnauthorized: () => {
97
- if (process.env.NODE_ENV === "development") {
98
- console.warn("[Kerne] 401 received. Auto-logout disabled in dev.");
99
- return;
100
- }
101
- this.clearSession();
102
- }
103
- });
104
- this.loadSession();
105
- }
106
- // ============================================================================
107
- // Reactive State (useSyncExternalStore compatible)
108
- // ============================================================================
109
- subscribe(listener) {
110
- this.listeners.add(listener);
111
- return () => this.listeners.delete(listener);
112
- }
113
- notify() {
114
- this.listeners.forEach((l) => l());
115
- }
116
- get user() {
117
- return this._user;
118
- }
119
- get token() {
120
- return this._token;
121
- }
122
- get isAuthenticated() {
123
- return this._token !== null;
124
- }
125
- get isLoading() {
126
- return this._isLoading;
127
- }
128
- // ============================================================================
129
- // Session Management
130
- // ============================================================================
131
- loadSession() {
132
- if (!this.storage) {
133
- this._isLoading = false;
134
- this.notify();
135
- return;
136
- }
137
- try {
138
- const data = this.storage.getItem(this.storageKey);
139
- if (data) {
140
- const { user, token, refresh_token, expires_at } = JSON.parse(data);
141
- const expiresAt = expires_at ? new Date(expires_at) : null;
142
- if (!expiresAt || expiresAt > /* @__PURE__ */ new Date()) {
143
- this._user = user;
144
- this._token = token;
145
- this._refreshToken = refresh_token ?? null;
146
- this._expiresAt = expiresAt;
147
- this.kerne = this.kerne.withToken(token);
148
- this.scheduleRefresh();
149
- } else {
150
- this.storage.removeItem(this.storageKey);
151
- }
152
- }
153
- } catch (e) {
154
- console.error("[Kerne] Failed to load session:", e);
155
- this.storage?.removeItem(this.storageKey);
156
- }
157
- this._isLoading = false;
158
- this.notify();
159
- }
160
- /**
161
- * `AuthResponse.user` is the minimal `{id, email, role}` claim set the
162
- * token endpoint returns, not the full profile (`User`) - so this always
163
- * follows up with `users.me()` rather than assigning it directly (that
164
- * used to leave `_user` looking like a `User` while actually missing
165
- * `email_verified`/`first_name`/`avatar`/etc).
166
- */
167
- async saveSession(response) {
168
- this._token = response.token;
169
- this._refreshToken = response.refresh_token;
170
- this._expiresAt = response.expires_at ? new Date(response.expires_at) : null;
171
- this.kerne = this.kerne.withToken(response.token);
172
- this._user = await this.kerne.users.me();
173
- if (this.storage) {
174
- this.storage.setItem(
175
- this.storageKey,
176
- JSON.stringify({
177
- user: this._user,
178
- token: response.token,
179
- refresh_token: response.refresh_token,
180
- expires_at: response.expires_at
181
- })
182
- );
183
- }
184
- this.scheduleRefresh();
185
- this.onAuthChange?.(this._user);
186
- this.notify();
187
- }
188
- clearSession() {
189
- this._user = null;
190
- this._token = null;
191
- this._refreshToken = null;
192
- this._expiresAt = null;
193
- this.cancelRefresh();
194
- if (this.storage) {
195
- this.storage.removeItem(this.storageKey);
196
- }
197
- this.onAuthChange?.(null);
198
- this.notify();
199
- }
200
- // ============================================================================
201
- // Auto-Refresh
202
- // ============================================================================
203
- scheduleRefresh() {
204
- if (!this.autoRefresh || !this._expiresAt) return;
205
- this.cancelRefresh();
206
- const now = Date.now();
207
- const expiry = this._expiresAt.getTime();
208
- const refreshAt = expiry - this.refreshBuffer * 1e3;
209
- const delay = Math.max(0, refreshAt - now);
210
- if (delay > 0) {
211
- this.refreshTimer = setTimeout(() => this.silentRefresh(), delay);
212
- }
213
- }
214
- cancelRefresh() {
215
- if (this.refreshTimer) {
216
- clearTimeout(this.refreshTimer);
217
- this.refreshTimer = null;
218
- }
219
- }
220
- async silentRefresh() {
221
- if (!this._refreshToken) return;
222
- try {
223
- const response = await this.kerne.auth.refreshToken({ refresh_token: this._refreshToken });
224
- await this.saveSession(response);
225
- console.debug("[Kerne] Session refreshed silently");
226
- } catch (e) {
227
- console.warn("[Kerne] Silent refresh failed:", e);
228
- }
229
- }
230
- // ============================================================================
231
- // Auth Methods
232
- // ============================================================================
233
- async register(params) {
234
- const [firstName, ...lastNameParts] = (params.name || "").split(" ");
235
- const response = await this.kerne.auth.signup({
236
- email: params.email,
237
- password: params.password,
238
- first_name: firstName || void 0,
239
- last_name: lastNameParts.join(" ") || void 0,
240
- invitationToken: params.invitationToken,
241
- invitationCode: params.invitationCode
242
- });
243
- await this.saveSession(response);
244
- return response;
245
- }
246
- async login(params) {
247
- const response = await this.kerne.auth.login(params);
248
- await this.saveSession(response);
249
- return response;
250
- }
251
- /** Manually trigger a token refresh - normally handled automatically by `autoRefresh`. */
252
- async refreshToken() {
253
- if (!this._refreshToken) return null;
254
- const response = await this.kerne.auth.refreshToken({ refresh_token: this._refreshToken });
255
- await this.saveSession(response);
256
- return response;
257
- }
258
- logout() {
259
- this.clearSession();
260
- }
261
- async refreshUser() {
262
- if (!this._token) return null;
263
- try {
264
- const user = await this.kerne.users.me();
265
- this._user = user;
266
- this.onAuthChange?.(user);
267
- this.notify();
268
- return user;
269
- } catch {
270
- this.clearSession();
271
- return null;
272
- }
273
- }
274
- // No `avatar` here - UpdateUserDto doesn't accept it server-side
275
- // (`forbidNonWhitelisted` rejects the field with a 400).
276
- async updateProfile(params) {
277
- if (!this._user) throw new Error("User not authenticated");
278
- const updated = await this.kerne.users.update(this._user.id, params);
279
- this._user = updated;
280
- if (this.storage && this._token) {
281
- try {
282
- const data = this.storage.getItem(this.storageKey);
283
- if (data) {
284
- const session = JSON.parse(data);
285
- session.user = updated;
286
- this.storage.setItem(this.storageKey, JSON.stringify(session));
287
- }
288
- } catch (e) {
289
- }
290
- }
291
- this.onAuthChange?.(updated);
292
- this.notify();
293
- return updated;
294
- }
295
- async updatePassword(params) {
296
- await this.kerne.auth.changePassword(params);
297
- }
298
- /** Forgot-password flow (logged out) - sends the reset email. */
299
- async requestPasswordReset(email) {
300
- await this.kerne.auth.requestPasswordReset(email);
301
- }
302
- /** Confirms a password reset with the token from the email. */
303
- async confirmPasswordReset(token, password) {
304
- await this.kerne.auth.confirmPasswordReset(token, password);
305
- }
306
- // ============================================================================
307
- // Billing Methods
308
- // ============================================================================
309
- /**
310
- * Errors are not swallowed here (unlike the old implementation, which
311
- * caught everything and returned `false`) - a 401/500 must not be
312
- * indistinguishable from a real denial, that's exactly what let the
313
- * `has_access`/`allowed` mismatch below ship unnoticed. Callers that want
314
- * a fail-closed boolean regardless of the reason (e.g. `<Allows>`)
315
- * catch around this themselves.
316
- */
317
- async allows(featureKey, requested) {
318
- const check = await this.kerne.check(featureKey, { requested });
319
- return check.allowed;
320
- }
321
- /** Full entitlement detail (limit/used/remaining/overage) - use `allows()` for a plain boolean. */
322
- async check(featureKey, requested) {
323
- return this.kerne.check(featureKey, { requested });
324
- }
325
- async createCheckout(planPriceId, options) {
326
- const { url } = await this.kerne.billing.checkout(planPriceId, options);
327
- return url;
328
- }
329
- async openCheckout(planPriceId, options) {
330
- const url = await this.createCheckout(planPriceId, options);
331
- if (typeof window !== "undefined") window.location.href = url;
332
- }
333
- async createPortal(returnUrl) {
334
- const { url } = await this.kerne.billing.portal({ returnUrl });
335
- return url;
336
- }
337
- async openPortal(returnUrl) {
338
- const url = await this.createPortal(returnUrl);
339
- if (typeof window !== "undefined") window.location.href = url;
340
- }
341
- async getSubscription(productSlug) {
342
- const subs = await this.kerne.billing.subscriptions.list({
343
- productSlug,
344
- scopeType: "USER"
345
- });
346
- const active = subs.find(
347
- (s) => s.status === "ACTIVE" || s.status === "TRIALING" || s.status === "PAST_DUE"
348
- );
349
- return active ?? null;
350
- }
351
- /** Public pricing data - omit `productIdOrSlug` for the tenant's default product. */
352
- async getPlans(productIdOrSlug) {
353
- return this.kerne.billing.plans(productIdOrSlug);
354
- }
355
- /** Every entitlement for the current user in one call - for a "your plan" screen. */
356
- async getEntitlements() {
357
- return this.kerne.entitlements();
358
- }
359
- /** Usage for the current user - all QUOTA features, or one via `featureKey`. */
360
- async getUsage(featureKey) {
361
- return this.kerne.usage({ featureKey });
362
- }
363
- // ============================================================================
364
- // Growth Methods (waitlist, invitations)
365
- // ============================================================================
366
- async joinWaitlist(params) {
367
- return this.kerne.waitlist.join(params);
368
- }
369
- /** Validate an invitation token before showing the registration form. */
370
- async validateInvitationToken(token) {
371
- return this.kerne.invitations.validateToken(token);
372
- }
373
- /** Validate an invitation code before showing the registration form. */
374
- async validateInvitationCode(code) {
375
- return this.kerne.invitations.validateCode(code);
376
- }
377
- // ============================================================================
378
- // Email Verification Methods
379
- // ============================================================================
380
- async sendVerificationEmail(verificationType = "code") {
381
- await this.kerne.auth.sendVerificationEmail(verificationType);
382
- }
383
- async verifyEmailWithCode(code) {
384
- return await this.kerne.auth.verifyEmailWithCode(code);
385
- }
386
- async verifyEmailWithLink(token) {
387
- return await this.kerne.auth.verifyEmailWithLink(token);
388
- }
389
- async getVerificationStatus() {
390
- return await this.kerne.auth.getVerificationStatus();
391
- }
392
- };
393
- var KerneContext = (0, import_react.createContext)(null);
394
- function KerneProvider({ children, ...config }) {
395
- const clientRef = (0, import_react.useRef)(null);
396
- const client = (0, import_react.useMemo)(() => {
397
- if (!clientRef.current) {
398
- clientRef.current = new KerneClient(config);
399
- }
400
- return clientRef.current;
401
- }, [config.appId, config.baseUrl]);
402
- (0, import_react.useEffect)(() => {
403
- return () => {
404
- client.cancelRefresh?.();
405
- };
406
- }, [client]);
407
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KerneContext.Provider, { value: client, children });
408
- }
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;"use client";
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
409
16
 
410
- // src/hooks.ts
411
- var import_react2 = require("react");
412
- function useClient() {
413
- const context = (0, import_react2.useContext)(KerneContext);
414
- if (!context) {
415
- throw new Error("useClient must be used within a KerneProvider");
416
- }
417
- return context;
418
- }
419
- function useAuth() {
420
- const client = useClient();
421
- const user = (0, import_react2.useSyncExternalStore)(
422
- (callback) => client.subscribe(callback),
423
- () => client.user,
424
- () => client.user
425
- // Server snapshot
426
- );
427
- const token = (0, import_react2.useSyncExternalStore)(
428
- (callback) => client.subscribe(callback),
429
- () => client.token,
430
- () => null
431
- // Server always null
432
- );
433
- const isAuthenticated = (0, import_react2.useSyncExternalStore)(
434
- (callback) => client.subscribe(callback),
435
- () => client.isAuthenticated,
436
- () => false
437
- // Server always unauthenticated
438
- );
439
- const isLoading = (0, import_react2.useSyncExternalStore)(
440
- (callback) => client.subscribe(callback),
441
- () => client.isLoading,
442
- () => true
443
- // Server always loading
444
- );
445
- return {
446
- user,
447
- token,
448
- isAuthenticated,
449
- isLoading,
450
- login: (0, import_react2.useCallback)(
451
- (params) => client.login(params),
452
- [client]
453
- ),
454
- register: (0, import_react2.useCallback)(
455
- (params) => client.register(params),
456
- [client]
457
- ),
458
- logout: (0, import_react2.useCallback)(() => client.logout(), [client]),
459
- refreshUser: (0, import_react2.useCallback)(() => client.refreshUser(), [client]),
460
- refreshToken: (0, import_react2.useCallback)(() => client.refreshToken(), [client]),
461
- updateProfile: (0, import_react2.useCallback)(
462
- (params) => client.updateProfile(params),
463
- [client]
464
- ),
465
- updatePassword: (0, import_react2.useCallback)(
466
- (params) => client.updatePassword(params),
467
- [client]
468
- ),
469
- requestPasswordReset: (0, import_react2.useCallback)(
470
- (email) => client.requestPasswordReset(email),
471
- [client]
472
- ),
473
- confirmPasswordReset: (0, import_react2.useCallback)(
474
- (token2, password) => client.confirmPasswordReset(token2, password),
475
- [client]
476
- ),
477
- // Email verification
478
- sendVerificationEmail: (0, import_react2.useCallback)(
479
- (verificationType = "code") => client.sendVerificationEmail(verificationType),
480
- [client]
481
- ),
482
- verifyEmailWithCode: (0, import_react2.useCallback)((code) => client.verifyEmailWithCode(code), [client]),
483
- verifyEmailWithLink: (0, import_react2.useCallback)(
484
- (token2) => client.verifyEmailWithLink(token2),
485
- [client]
486
- ),
487
- getVerificationStatus: (0, import_react2.useCallback)(() => client.getVerificationStatus(), [client])
488
- };
489
- }
490
- function useCheckout() {
491
- const client = useClient();
492
- return {
493
- createCheckout: (0, import_react2.useCallback)(
494
- (planPriceId, options) => client.createCheckout(planPriceId, options),
495
- [client]
496
- ),
497
- openCheckout: (0, import_react2.useCallback)(
498
- (planPriceId, options) => client.openCheckout(planPriceId, options),
499
- [client]
500
- )
501
- };
502
- }
503
- function usePortal() {
504
- const client = useClient();
505
- return {
506
- createPortal: (0, import_react2.useCallback)((returnUrl) => client.createPortal(returnUrl), [client]),
507
- openPortal: (0, import_react2.useCallback)((returnUrl) => client.openPortal(returnUrl), [client])
508
- };
509
- }
510
- function useAllows(featureKey, requested) {
511
- const client = useClient();
512
- const [state, setState] = (0, import_react2.useState)({
513
- allowed: false,
514
- isLoading: true,
515
- error: null
516
- });
517
- (0, import_react2.useEffect)(() => {
518
- let mounted = true;
519
- client.allows(featureKey, requested).then((allowed) => {
520
- if (mounted) {
521
- setState({ allowed, isLoading: false, error: null });
522
- }
523
- }).catch((error) => {
524
- if (mounted) {
525
- setState({ allowed: false, isLoading: false, error });
526
- }
527
- });
528
- return () => {
529
- mounted = false;
530
- };
531
- }, [client, featureKey, requested]);
532
- return state;
533
- }
534
- function useCheck(featureKey, requested) {
535
- const client = useClient();
536
- const [state, setState] = (0, import_react2.useState)({
537
- check: null,
538
- isLoading: true,
539
- error: null
540
- });
541
- (0, import_react2.useEffect)(() => {
542
- let mounted = true;
543
- client.check(featureKey, requested).then((check) => {
544
- if (mounted) {
545
- setState({ check, isLoading: false, error: null });
546
- }
547
- }).catch((error) => {
548
- if (mounted) {
549
- setState({ check: null, isLoading: false, error });
550
- }
551
- });
552
- return () => {
553
- mounted = false;
554
- };
555
- }, [client, featureKey, requested]);
556
- return state;
557
- }
558
- function useSubscription(productSlug) {
559
- const client = useClient();
560
- const [state, setState] = (0, import_react2.useState)({
561
- subscription: null,
562
- isLoading: true,
563
- error: null
564
- });
565
- (0, import_react2.useEffect)(() => {
566
- let mounted = true;
567
- client.getSubscription(productSlug).then((subscription) => {
568
- if (mounted) {
569
- setState({ subscription, isLoading: false, error: null });
570
- }
571
- }).catch((error) => {
572
- if (mounted) {
573
- setState({ subscription: null, isLoading: false, error });
574
- }
575
- });
576
- return () => {
577
- mounted = false;
578
- };
579
- }, [client, productSlug]);
580
- const isActive = state.subscription?.status === "ACTIVE" || state.subscription?.status === "TRIALING";
581
- const planSlug = state.subscription?.plan?.slug;
582
- return {
583
- ...state,
584
- isActive,
585
- planSlug
586
- };
587
- }
588
- function usePlans(productIdOrSlug) {
589
- const client = useClient();
590
- const [state, setState] = (0, import_react2.useState)({
591
- plans: [],
592
- isLoading: true,
593
- error: null
594
- });
595
- (0, import_react2.useEffect)(() => {
596
- let mounted = true;
597
- client.getPlans(productIdOrSlug).then((plans) => {
598
- if (mounted) {
599
- setState({ plans, isLoading: false, error: null });
600
- }
601
- }).catch((error) => {
602
- if (mounted) {
603
- setState({ plans: [], isLoading: false, error });
604
- }
605
- });
606
- return () => {
607
- mounted = false;
608
- };
609
- }, [client, productIdOrSlug]);
610
- return state;
611
- }
612
- function useEntitlements() {
613
- const client = useClient();
614
- const [state, setState] = (0, import_react2.useState)({
615
- entitlements: null,
616
- isLoading: true,
617
- error: null
618
- });
619
- (0, import_react2.useEffect)(() => {
620
- let mounted = true;
621
- client.getEntitlements().then((entitlements) => {
622
- if (mounted) {
623
- setState({ entitlements, isLoading: false, error: null });
624
- }
625
- }).catch((error) => {
626
- if (mounted) {
627
- setState({ entitlements: null, isLoading: false, error });
628
- }
629
- });
630
- return () => {
631
- mounted = false;
632
- };
633
- }, [client]);
634
- return state;
635
- }
636
- function useUsage(featureKey) {
637
- const client = useClient();
638
- const [state, setState] = (0, import_react2.useState)({
639
- usage: [],
640
- isLoading: true,
641
- error: null
642
- });
643
- (0, import_react2.useEffect)(() => {
644
- let mounted = true;
645
- client.getUsage(featureKey).then((usage) => {
646
- if (mounted) {
647
- setState({ usage, isLoading: false, error: null });
648
- }
649
- }).catch((error) => {
650
- if (mounted) {
651
- setState({ usage: [], isLoading: false, error });
652
- }
653
- });
654
- return () => {
655
- mounted = false;
656
- };
657
- }, [client, featureKey]);
658
- return state;
659
- }
660
- function useWaitlist() {
661
- const client = useClient();
662
- return {
663
- join: (0, import_react2.useCallback)((params) => client.joinWaitlist(params), [client])
664
- };
665
- }
666
- function useInvitation(params) {
667
- const client = useClient();
668
- const { token, code } = params;
669
- const [state, setState] = (0, import_react2.useState)({
670
- result: null,
671
- isLoading: !!(token || code),
672
- error: null
673
- });
674
- (0, import_react2.useEffect)(() => {
675
- if (!token && !code) {
676
- setState({ result: null, isLoading: false, error: null });
677
- return;
678
- }
679
- let mounted = true;
680
- const validate = token ? client.validateInvitationToken(token) : client.validateInvitationCode(code);
681
- validate.then((result) => {
682
- if (mounted) {
683
- setState({ result, isLoading: false, error: null });
684
- }
685
- }).catch((error) => {
686
- if (mounted) {
687
- setState({ result: null, isLoading: false, error });
688
- }
689
- });
690
- return () => {
691
- mounted = false;
692
- };
693
- }, [client, token, code]);
694
- return state;
695
- }
696
- function useUser() {
697
- const { user, isLoading, updateProfile } = useAuth();
698
- return {
699
- user,
700
- isLoading,
701
- update: updateProfile,
702
- // Computed properties
703
- fullName: user ? `${user.first_name || ""} ${user.last_name || ""}`.trim() : null,
704
- initials: user ? `${user.first_name?.[0] || ""}${user.last_name?.[0] || ""}`.toUpperCase() : null,
705
- email: user?.email || null,
706
- emailVerified: user?.email_verified || false
707
- };
708
- }
17
+
18
+
19
+
20
+ var _chunk7U3QBMA7cjs = require('./chunk-7U3QBMA7.cjs');
709
21
 
710
22
  // src/components.tsx
711
- var import_react3 = __toESM(require("react"), 1);
712
- var import_jsx_runtime2 = require("react/jsx-runtime");
23
+ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
24
+ var _jsxruntime = require('react/jsx-runtime');
713
25
  function Authenticated({ children, fallback = null }) {
714
- const { isAuthenticated } = useAuth();
26
+ const { isAuthenticated } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
715
27
  return isAuthenticated ? children : fallback;
716
28
  }
717
29
  function Unauthenticated({ children, fallback = null }) {
718
- const { isAuthenticated } = useAuth();
30
+ const { isAuthenticated } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
719
31
  return !isAuthenticated ? children : fallback;
720
32
  }
721
33
  function AuthLoading({ children }) {
722
- const client = useClient();
34
+ const client = _chunk7U3QBMA7cjs.useClient.call(void 0, );
723
35
  return client.isLoading ? children : null;
724
36
  }
725
37
  function HasSubscription({ children, fallback = null }) {
726
- const client = useClient();
727
- const [hasSubscription, setHasSubscription] = import_react3.default.useState(null);
728
- import_react3.default.useEffect(() => {
38
+ const client = _chunk7U3QBMA7cjs.useClient.call(void 0, );
39
+ const [hasSubscription, setHasSubscription] = _react2.default.useState(null);
40
+ _react2.default.useEffect(() => {
729
41
  client.getSubscription().then((sub) => {
730
42
  setHasSubscription(sub !== null && ["ACTIVE", "TRIALING"].includes(sub.status));
731
43
  }).catch(() => {
@@ -737,45 +49,45 @@ function HasSubscription({ children, fallback = null }) {
737
49
  }
738
50
  function Allows({
739
51
  children,
740
- key,
52
+ featureKey,
741
53
  minimum,
742
54
  fallback = null
743
55
  }) {
744
- const client = useClient();
745
- const [allowed, setAllowed] = import_react3.default.useState(null);
746
- import_react3.default.useEffect(() => {
747
- client.allows(key, minimum).then((result) => {
56
+ const client = _chunk7U3QBMA7cjs.useClient.call(void 0, );
57
+ const [allowed, setAllowed] = _react2.default.useState(null);
58
+ _react2.default.useEffect(() => {
59
+ client.allows(featureKey, minimum).then((result) => {
748
60
  setAllowed(result);
749
61
  }).catch(() => {
750
62
  setAllowed(false);
751
63
  });
752
- }, [client, key, minimum]);
64
+ }, [client, featureKey, minimum]);
753
65
  if (allowed === null) return null;
754
66
  return allowed ? children : fallback;
755
67
  }
756
68
  function Protected({
757
69
  children,
758
70
  auth = true,
759
- key,
71
+ featureKey,
760
72
  authFallback = null,
761
73
  billingFallback = null
762
74
  }) {
763
- const { isAuthenticated } = useAuth();
75
+ const { isAuthenticated } = _chunk7U3QBMA7cjs.useAuth.call(void 0, );
764
76
  if (auth && !isAuthenticated) {
765
77
  return authFallback;
766
78
  }
767
- if (key) {
768
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Allows, { fallback: billingFallback, children }, key);
79
+ if (featureKey) {
80
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Allows, { featureKey, fallback: billingFallback, children });
769
81
  }
770
82
  return children;
771
83
  }
772
84
 
773
85
  // src/error-boundary.tsx
774
- var import_react4 = __toESM(require("react"), 1);
775
- var import_jsx_runtime3 = require("react/jsx-runtime");
776
- var KerneErrorBoundary = class extends import_react4.Component {
86
+
87
+
88
+ var KerneErrorBoundary = (_class = class extends _react.Component {
777
89
  constructor(props) {
778
- super(props);
90
+ super(props);_class.prototype.__init.call(this);;
779
91
  this.state = { error: null, hasError: false };
780
92
  }
781
93
  static getDerivedStateFromError(error) {
@@ -783,16 +95,16 @@ var KerneErrorBoundary = class extends import_react4.Component {
783
95
  }
784
96
  componentDidCatch(error, errorInfo) {
785
97
  const kerneError = error;
786
- this.props.onError?.(kerneError, errorInfo);
98
+ _optionalChain([this, 'access', _4 => _4.props, 'access', _5 => _5.onError, 'optionalCall', _6 => _6(kerneError, errorInfo)]);
787
99
  if (process.env.NODE_ENV === "development") {
788
100
  console.error("[KerneSDK] Error caught by boundary:", kerneError);
789
101
  console.error("[KerneSDK] Component stack:", errorInfo.componentStack);
790
102
  }
791
103
  }
792
- reset = () => {
793
- this.props.onReset?.();
104
+ __init() {this.reset = () => {
105
+ _optionalChain([this, 'access', _7 => _7.props, 'access', _8 => _8.onReset, 'optionalCall', _9 => _9()]);
794
106
  this.setState({ error: null, hasError: false });
795
- };
107
+ }}
796
108
  render() {
797
109
  if (this.state.hasError && this.state.error) {
798
110
  const { fallback } = this.props;
@@ -803,14 +115,14 @@ var KerneErrorBoundary = class extends import_react4.Component {
803
115
  }
804
116
  return fallback;
805
117
  }
806
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "20px", textAlign: "center" }, children: [
807
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { style: { color: "#dc2626", marginBottom: "10px" }, children: "Something went wrong" }),
808
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { color: "#6b7280", marginBottom: "20px" }, children: error.message || "An unexpected error occurred" }),
809
- error.code && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { style: { color: "#9ca3af", fontSize: "12px", marginBottom: "20px" }, children: [
118
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: "20px", textAlign: "center" }, children: [
119
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { style: { color: "#dc2626", marginBottom: "10px" }, children: "Something went wrong" }),
120
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { color: "#6b7280", marginBottom: "20px" }, children: error.message || "An unexpected error occurred" }),
121
+ error.code && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { style: { color: "#9ca3af", fontSize: "12px", marginBottom: "20px" }, children: [
810
122
  "Error code: ",
811
123
  error.code
812
124
  ] }),
813
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
125
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
814
126
  "button",
815
127
  {
816
128
  onClick: this.reset,
@@ -829,13 +141,13 @@ var KerneErrorBoundary = class extends import_react4.Component {
829
141
  }
830
142
  return this.props.children;
831
143
  }
832
- };
144
+ }, _class);
833
145
  function useKerneError() {
834
- const [error, setError] = import_react4.default.useState(null);
835
- const handleError = import_react4.default.useCallback((err) => {
146
+ const [error, setError] = _react2.default.useState(null);
147
+ const handleError = _react2.default.useCallback((err) => {
836
148
  setError(err);
837
149
  }, []);
838
- const clearError = import_react4.default.useCallback(() => {
150
+ const clearError = _react2.default.useCallback(() => {
839
151
  setError(null);
840
152
  }, []);
841
153
  return {
@@ -846,78 +158,29 @@ function useKerneError() {
846
158
  };
847
159
  }
848
160
 
849
- // src/store.ts
850
- var KerneStore = class {
851
- state;
852
- listeners = /* @__PURE__ */ new Set();
853
- constructor(initialState) {
854
- this.state = {
855
- user: null,
856
- isAuthenticated: false,
857
- isLoading: true,
858
- subscription: null,
859
- error: null,
860
- ...initialState
861
- };
862
- }
863
- getState() {
864
- return this.state;
865
- }
866
- getSnapshot() {
867
- return this.state;
868
- }
869
- getServerSnapshot() {
870
- return this.state;
871
- }
872
- setState(partial) {
873
- const prevState = this.state;
874
- this.state = { ...this.state, ...partial };
875
- if (this.hasChanged(prevState, this.state)) {
876
- this.notify();
877
- }
878
- }
879
- hasChanged(prev, next) {
880
- return prev.user !== next.user || prev.isAuthenticated !== next.isAuthenticated || prev.isLoading !== next.isLoading || prev.subscription !== next.subscription || prev.error !== next.error;
881
- }
882
- subscribe(listener) {
883
- this.listeners.add(listener);
884
- return () => {
885
- this.listeners.delete(listener);
886
- };
887
- }
888
- notify() {
889
- this.listeners.forEach((listener) => listener());
890
- }
891
- // Selector-based subscription for optimized re-renders
892
- select(selector) {
893
- return selector(this.state);
894
- }
895
- };
896
- // Annotate the CommonJS export names for ESM import in node:
897
- 0 && (module.exports = {
898
- Allows,
899
- AuthLoading,
900
- Authenticated,
901
- HasSubscription,
902
- KerneClient,
903
- KerneContext,
904
- KerneErrorBoundary,
905
- KerneProvider,
906
- KerneStore,
907
- Protected,
908
- Unauthenticated,
909
- useAllows,
910
- useAuth,
911
- useCheck,
912
- useCheckout,
913
- useClient,
914
- useEntitlements,
915
- useInvitation,
916
- useKerneError,
917
- usePlans,
918
- usePortal,
919
- useSubscription,
920
- useUsage,
921
- useUser,
922
- useWaitlist
923
- });
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+ exports.Allows = Allows; exports.AuthLoading = AuthLoading; exports.Authenticated = Authenticated; exports.HasSubscription = HasSubscription; exports.KerneClient = _chunk7U3QBMA7cjs.KerneClient; exports.KerneContext = _chunk7U3QBMA7cjs.KerneContext; exports.KerneErrorBoundary = KerneErrorBoundary; exports.KerneProvider = _chunk7U3QBMA7cjs.KerneProvider; exports.Protected = Protected; exports.Unauthenticated = Unauthenticated; exports.defaultLocalization = _chunk7U3QBMA7cjs.defaultLocalization; exports.useAccess = _chunk7U3QBMA7cjs.useAccess; exports.useAuth = _chunk7U3QBMA7cjs.useAuth; exports.useAuthConfig = _chunk7U3QBMA7cjs.useAuthConfig; exports.useCheckout = _chunk7U3QBMA7cjs.useCheckout; exports.useClient = _chunk7U3QBMA7cjs.useClient; exports.useEntitlements = _chunk7U3QBMA7cjs.useEntitlements; exports.useInvitation = _chunk7U3QBMA7cjs.useInvitation; exports.useKerneError = useKerneError; exports.usePlans = _chunk7U3QBMA7cjs.usePlans; exports.usePortal = _chunk7U3QBMA7cjs.usePortal; exports.useSubscription = _chunk7U3QBMA7cjs.useSubscription; exports.useUsage = _chunk7U3QBMA7cjs.useUsage; exports.useUser = _chunk7U3QBMA7cjs.useUser; exports.useWaitlist = _chunk7U3QBMA7cjs.useWaitlist;