@access-dlsu/leapify 0.260531.1 → 0.260601.1

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.
@@ -28,7 +28,7 @@ export declare function createAuth(env: LeapifyBindings): import("better-auth").
28
28
  hooks: {
29
29
  before: {
30
30
  matcher(context: import("better-auth").HookEndpointContext): boolean;
31
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
31
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
32
32
  context: {
33
33
  headers: Headers;
34
34
  };
@@ -36,7 +36,7 @@ export declare function createAuth(env: LeapifyBindings): import("better-auth").
36
36
  }[];
37
37
  after: {
38
38
  matcher(context: import("better-auth").HookEndpointContext): true;
39
- handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
39
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>;
40
40
  }[];
41
41
  };
42
42
  options: import("better-auth/plugins").BearerOptions | undefined;
@@ -32,7 +32,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
32
32
  userId?: string | undefined;
33
33
  } & {
34
34
  fetchOptions?: FetchOptions | undefined;
35
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
35
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
36
36
  accessToken: string | undefined;
37
37
  refreshToken: string;
38
38
  accessTokenExpiresAt: Date | undefined;
@@ -97,7 +97,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
97
97
  additionalData?: Record<string, any> | undefined;
98
98
  } & {
99
99
  fetchOptions?: FetchOptions | undefined;
100
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
100
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
101
101
  redirect: boolean;
102
102
  url: string;
103
103
  } | (Omit<{
@@ -132,7 +132,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
132
132
  signOut: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
133
133
  query?: Record<string, any> | undefined;
134
134
  fetchOptions?: FetchOptions | undefined;
135
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
135
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
136
136
  success: boolean;
137
137
  }, {
138
138
  code?: string | undefined;
@@ -154,7 +154,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
154
154
  image?: string | undefined;
155
155
  callbackURL?: string | undefined;
156
156
  fetchOptions?: FetchOptions | undefined;
157
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<(Omit<{
157
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<(Omit<{
158
158
  token: null;
159
159
  user: {
160
160
  id: string;
@@ -215,7 +215,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
215
215
  rememberMe?: boolean | undefined;
216
216
  } & {
217
217
  fetchOptions?: FetchOptions | undefined;
218
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<Omit<{
218
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<Omit<{
219
219
  redirect: boolean;
220
220
  token: string;
221
221
  url?: string | undefined;
@@ -254,7 +254,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
254
254
  token?: string | undefined;
255
255
  } & {
256
256
  fetchOptions?: FetchOptions | undefined;
257
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
257
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
258
258
  status: boolean;
259
259
  }, {
260
260
  code?: string | undefined;
@@ -270,7 +270,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
270
270
  callbackURL?: string | undefined;
271
271
  };
272
272
  fetchOptions?: FetchOptions | undefined;
273
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<NonNullable<void | {
273
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<NonNullable<void | {
274
274
  status: boolean;
275
275
  }>, {
276
276
  code?: string | undefined;
@@ -285,7 +285,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
285
285
  callbackURL?: string | undefined;
286
286
  } & {
287
287
  fetchOptions?: FetchOptions | undefined;
288
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
288
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
289
289
  status: boolean;
290
290
  }, {
291
291
  code?: string | undefined;
@@ -300,7 +300,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
300
300
  callbackURL?: string | undefined;
301
301
  } & {
302
302
  fetchOptions?: FetchOptions | undefined;
303
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
303
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
304
304
  status: boolean;
305
305
  }, {
306
306
  code?: string | undefined;
@@ -317,7 +317,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
317
317
  revokeOtherSessions?: boolean | undefined;
318
318
  } & {
319
319
  fetchOptions?: FetchOptions | undefined;
320
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<Omit<{
320
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<Omit<{
321
321
  token: string | null;
322
322
  user: {
323
323
  id: string;
@@ -353,7 +353,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
353
353
  } & {
354
354
  updateSession: <FetchOptions extends import("better-auth").ClientFetchOption<Partial<Partial<{}>> & Record<string, any>, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<Partial<{}> & {
355
355
  fetchOptions?: FetchOptions | undefined;
356
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
356
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
357
357
  session: {
358
358
  id: string;
359
359
  createdAt: Date;
@@ -380,7 +380,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
380
380
  token: () => string;
381
381
  };
382
382
  };
383
- }, FetchOptions>> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
383
+ }, FetchOptions>> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
384
384
  status: boolean;
385
385
  }, {
386
386
  code?: string | undefined;
@@ -397,7 +397,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
397
397
  token?: string | undefined;
398
398
  } & {
399
399
  fetchOptions?: FetchOptions | undefined;
400
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
400
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
401
401
  success: boolean;
402
402
  message: string;
403
403
  }, {
@@ -413,7 +413,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
413
413
  redirectTo?: string | undefined;
414
414
  } & {
415
415
  fetchOptions?: FetchOptions | undefined;
416
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
416
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
417
417
  status: boolean;
418
418
  message: string;
419
419
  }, {
@@ -431,7 +431,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
431
431
  callbackURL: string;
432
432
  };
433
433
  fetchOptions?: FetchOptions | undefined;
434
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<never, {
434
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<never, {
435
435
  code?: string | undefined;
436
436
  message?: string | undefined;
437
437
  }, FetchOptions["throw"] extends true ? true : false>>;
@@ -440,7 +440,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
440
440
  listSessions: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
441
441
  query?: Record<string, any> | undefined;
442
442
  fetchOptions?: FetchOptions | undefined;
443
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<import("better-auth").Prettify<{
443
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<import("better-auth").Prettify<{
444
444
  id: string;
445
445
  createdAt: Date;
446
446
  updatedAt: Date;
@@ -460,7 +460,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
460
460
  token: string;
461
461
  } & {
462
462
  fetchOptions?: FetchOptions | undefined;
463
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
463
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
464
464
  status: boolean;
465
465
  }, {
466
466
  code?: string | undefined;
@@ -470,7 +470,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
470
470
  revokeSessions: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
471
471
  query?: Record<string, any> | undefined;
472
472
  fetchOptions?: FetchOptions | undefined;
473
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
473
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
474
474
  status: boolean;
475
475
  }, {
476
476
  code?: string | undefined;
@@ -480,7 +480,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
480
480
  revokeOtherSessions: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
481
481
  query?: Record<string, any> | undefined;
482
482
  fetchOptions?: FetchOptions | undefined;
483
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
483
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
484
484
  status: boolean;
485
485
  }, {
486
486
  code?: string | undefined;
@@ -519,7 +519,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
519
519
  additionalData?: Record<string, any> | undefined;
520
520
  } & {
521
521
  fetchOptions?: FetchOptions | undefined;
522
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
522
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
523
523
  url: string;
524
524
  redirect: boolean;
525
525
  }, {
@@ -530,7 +530,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
530
530
  listAccounts: <FetchOptions extends import("better-auth").ClientFetchOption<never, Partial<Record<string, any>> & Record<string, any>, Record<string, any> | undefined>>(data_0?: import("better-auth").Prettify<{
531
531
  query?: Record<string, any> | undefined;
532
532
  fetchOptions?: FetchOptions | undefined;
533
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
533
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
534
534
  scopes: string[];
535
535
  id: string;
536
536
  createdAt: Date;
@@ -553,7 +553,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
553
553
  callbackURL?: string | undefined;
554
554
  };
555
555
  fetchOptions?: FetchOptions | undefined;
556
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
556
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
557
557
  success: boolean;
558
558
  message: string;
559
559
  }, {
@@ -570,7 +570,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
570
570
  accountId?: string | undefined;
571
571
  } & {
572
572
  fetchOptions?: FetchOptions | undefined;
573
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
573
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
574
574
  status: boolean;
575
575
  }, {
576
576
  code?: string | undefined;
@@ -587,7 +587,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
587
587
  userId?: string | undefined;
588
588
  } & {
589
589
  fetchOptions?: FetchOptions | undefined;
590
- }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
590
+ }>, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
591
591
  accessToken: string;
592
592
  accessTokenExpiresAt: Date | undefined;
593
593
  scopes: string[];
@@ -604,7 +604,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
604
604
  accountId?: string | undefined;
605
605
  } | undefined;
606
606
  fetchOptions?: FetchOptions | undefined;
607
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
607
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
608
608
  user: import("better-auth").OAuth2UserInfo;
609
609
  data: Record<string, any>;
610
610
  }, {
@@ -621,7 +621,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
621
621
  disableRefresh?: unknown;
622
622
  } | undefined;
623
623
  fetchOptions?: FetchOptions | undefined;
624
- }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").BetterFetchResponse<{
624
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("better-auth/client").BetterFetchResponse<{
625
625
  user: import("better-auth").StripEmptyObjects<{
626
626
  id: string;
627
627
  createdAt: Date;
@@ -646,7 +646,7 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
646
646
  message?: string | undefined;
647
647
  }, FetchOptions["throw"] extends true ? true : false>>;
648
648
  } & {
649
- useSession: import("nanostores").Atom<{
649
+ useSession: import("better-auth/client").Atom<{
650
650
  data: {
651
651
  user: import("better-auth").StripEmptyObjects<{
652
652
  id: string;
@@ -668,28 +668,28 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
668
668
  userAgent?: string | null | undefined;
669
669
  }>;
670
670
  } | null;
671
- error: import("@better-fetch/fetch").BetterFetchError | null;
671
+ error: import("better-auth/client").BetterFetchError | null;
672
672
  isPending: boolean;
673
673
  isRefetching: boolean;
674
674
  refetch: (queryParams?: {
675
675
  query?: import("better-auth").SessionQueryParams;
676
676
  } | undefined) => Promise<void>;
677
677
  }>;
678
- $fetch: import("@better-fetch/fetch").BetterFetch<{
679
- plugins: (import("@better-fetch/fetch").BetterFetchPlugin<Record<string, any>> | {
678
+ $fetch: import("better-auth/client").BetterFetch<{
679
+ plugins: (import("better-auth/client").BetterFetchPlugin<Record<string, any>> | {
680
680
  id: string;
681
681
  name: string;
682
682
  hooks: {
683
- onSuccess(context: import("@better-fetch/fetch").SuccessContext<any>): void;
683
+ onSuccess(context: import("better-auth/client").SuccessContext<any>): void;
684
684
  };
685
685
  } | {
686
686
  id: string;
687
687
  name: string;
688
688
  hooks: {
689
- onSuccess: ((context: import("@better-fetch/fetch").SuccessContext<any>) => Promise<void> | void) | undefined;
690
- onError: ((context: import("@better-fetch/fetch").ErrorContext) => Promise<void> | void) | undefined;
691
- onRequest: (<T extends Record<string, any>>(context: import("@better-fetch/fetch").RequestContext<T>) => Promise<import("@better-fetch/fetch").RequestContext | void> | import("@better-fetch/fetch").RequestContext | void) | undefined;
692
- onResponse: ((context: import("@better-fetch/fetch").ResponseContext) => Promise<Response | void | import("@better-fetch/fetch").ResponseContext> | Response | import("@better-fetch/fetch").ResponseContext | void) | undefined;
689
+ onSuccess: ((context: import("better-auth/client").SuccessContext<any>) => Promise<void> | void) | undefined;
690
+ onError: ((context: import("better-auth/client").ErrorContext) => Promise<void> | void) | undefined;
691
+ onRequest: (<T extends Record<string, any>>(context: import("better-auth/client").RequestContext<T>) => Promise<import("better-auth/client").RequestContext | void> | import("better-auth/client").RequestContext | void) | undefined;
692
+ onResponse: ((context: import("better-auth/client").ResponseContext) => Promise<Response | void | import("better-auth/client").ResponseContext> | Response | import("better-auth/client").ResponseContext | void) | undefined;
693
693
  };
694
694
  })[];
695
695
  priority?: RequestPriority | undefined;
@@ -721,12 +721,12 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
721
721
  * const authClient = createLeapifyAuthClient(API_URL)
722
722
  * const api = createLeapifyClient(API_URL, () => getLeapifyToken(authClient))
723
723
  */
724
- ?: ((response: import("@better-fetch/fetch").ResponseContext) => Promise<void> | void) | undefined;
724
+ ?: ((response: import("better-auth/client").ResponseContext) => Promise<void> | void) | undefined;
725
725
  hookOptions?: {
726
726
  cloneResponse?: boolean;
727
727
  } | undefined;
728
728
  timeout?: number | undefined;
729
- customFetchImpl: import("@better-fetch/fetch").FetchEsque;
729
+ customFetchImpl: import("better-auth/client").FetchEsque;
730
730
  baseURL: string;
731
731
  throw?: boolean | undefined;
732
732
  auth?: ({
@@ -746,17 +746,17 @@ export declare function createLeapifyAuthClient(baseUrl: string): {
746
746
  params?: any;
747
747
  duplex?: "full" | "half" | undefined;
748
748
  jsonParser: (text: string) => Promise<any> | any;
749
- retry?: import("@better-fetch/fetch").RetryOptions | undefined;
749
+ retry?: import("better-auth/client").RetryOptions | undefined;
750
750
  retryAttempt?: number | undefined;
751
- output?: (import("@better-fetch/fetch").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
752
- errorSchema?: import("@better-fetch/fetch").StandardSchemaV1 | undefined;
751
+ output?: (import("better-auth/client").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
752
+ errorSchema?: import("better-auth/client").StandardSchemaV1 | undefined;
753
753
  disableValidation?: boolean | undefined;
754
754
  disableSignal?: boolean | undefined;
755
755
  }, unknown, unknown, {}>;
756
756
  $store: {
757
757
  notify: (signal?: (Omit<string, "$sessionSignal"> | "$sessionSignal") | undefined) => void;
758
758
  listen: (signal: Omit<string, "$sessionSignal"> | "$sessionSignal", listener: (value: boolean, oldValue?: boolean | undefined) => void) => void;
759
- atoms: Record<string, import("nanostores").WritableAtom<any>>;
759
+ atoms: Record<string, import("better-auth/client").WritableAtom<any>>;
760
760
  };
761
761
  $Infer: {
762
762
  Session: {
@@ -147,6 +147,8 @@ var LeapifyApiError = class extends Error {
147
147
  this.code = code;
148
148
  this.name = "LeapifyApiError";
149
149
  }
150
+ status;
151
+ code;
150
152
  };
151
153
  var LEAPIFY_ERROR_CODES = {
152
154
  UNAUTHORIZED: "UNAUTHORIZED",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/auth.ts","../../src/client/turnstile.ts","../../src/client/session.ts","../../src/client/index.ts"],"names":["createAuthClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Better Auth client helper for Leapify API consumers.\r\n *\r\n * This module is **browser-safe** — no Cloudflare, Drizzle, or Hono deps.\r\n * It wraps Better Auth's client SDK with the bearer plugin so that tokens\r\n * can be stored and retrieved as plain strings (no cookie dependency on\r\n * the consumer's frontend).\r\n *\r\n * @example\r\n * // lib/auth.ts (frontend)\r\n * import { createLeapifyAuthClient, signInWithGoogleRedirect } from 'leapify/client'\r\n *\r\n * export const authClient = createLeapifyAuthClient(process.env.NEXT_PUBLIC_API_URL!)\r\n *\r\n * // Redirect-based Google sign-in:\r\n * await signInWithGoogleRedirect(authClient, '/dashboard')\r\n */\r\n\r\nimport { createAuthClient } from 'better-auth/client'\r\n\r\nconst AUTH_TOKEN_KEY = 'better-auth.session_token'\r\n\r\n/**\r\n * Create a Better Auth client bound to the Leapify Worker URL.\r\n *\r\n * It uses the 'Bearer' auth type to send the stored session token\r\n * in the Authorization header.\r\n */\r\nexport function createLeapifyAuthClient(baseUrl: string) {\r\n return createAuthClient({\r\n baseURL: baseUrl,\r\n fetchOptions: {\r\n auth: {\r\n type: 'Bearer',\r\n token: () => {\r\n if (typeof window !== 'undefined') {\r\n return localStorage.getItem(AUTH_TOKEN_KEY) || ''\r\n }\r\n return ''\r\n }\r\n }\r\n }\r\n })\r\n}\r\n\r\nexport type LeapifyAuthClient = ReturnType<typeof createLeapifyAuthClient>\r\n\r\n/**\r\n * Sign in with Google via OAuth redirect flow.\r\n *\r\n * Redirects the browser to Google's OAuth page. After authentication,\r\n * Google redirects back to the Better Auth callback endpoint, which\r\n * creates a session and redirects to `callbackURL`.\r\n *\r\n * Call `syncCookieSessionToStorage()` on app init to restore the\r\n * session from the cookie after a redirect-based sign-in.\r\n *\r\n * @param authClient - Client created by createLeapifyAuthClient\r\n * @param callbackURL - Path or URL to redirect to after successful auth (e.g. '/dashboard')\r\n *\r\n * @example\r\n * import { signInWithGoogleRedirect } from 'leapify/client'\r\n *\r\n * document.getElementById('google-btn').onclick = () => {\r\n * signInWithGoogleRedirect(authClient, '/dashboard')\r\n * }\r\n */\r\nexport async function signInWithGoogleRedirect(\r\n authClient: LeapifyAuthClient,\r\n callbackURL: string,\r\n): Promise<void> {\r\n await authClient.signIn.social({\r\n provider: 'google',\r\n callbackURL,\r\n })\r\n}\r\n\r\n/**\r\n * Sync a cookie-based Better Auth session into localStorage.\r\n *\r\n * After an OAuth redirect flow, Better Auth stores the session in an\r\n * HTTP-only cookie. This function reads that session via `getSession()`\r\n * and stores the token in localStorage so that subsequent API calls\r\n * using the Bearer token work correctly.\r\n *\r\n * Call this once on app initialization, before `initializeSession()`.\r\n *\r\n * @param authClient - Client created by createLeapifyAuthClient\r\n *\r\n * @example\r\n * import { syncCookieSessionToStorage, initializeSession } from 'leapify/client'\r\n *\r\n * // On app mount:\r\n * await syncCookieSessionToStorage(authClient)\r\n * const user = await initializeSession(API_URL, getToken)\r\n */\r\nexport async function syncCookieSessionToStorage(\r\n authClient: LeapifyAuthClient,\r\n): Promise<void> {\r\n try {\r\n const result = await authClient.getSession()\r\n const data = result?.data as { session?: { token?: string } } | undefined\r\n const token = data?.session?.token\r\n if (token) {\r\n localStorage.setItem(AUTH_TOKEN_KEY, token)\r\n }\r\n } catch {\r\n // No cookie session — user is a guest.\r\n }\r\n}\r\n\r\n/**\r\n * Get the current bearer token from storage, or null for guests.\r\n * Pass this to `createLeapifyClient` as the `getToken` option.\r\n *\r\n * @example\r\n * import { createLeapifyClient } from 'leapify/client'\r\n * import { createLeapifyAuthClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * const authClient = createLeapifyAuthClient(API_URL)\r\n * const api = createLeapifyClient(API_URL, () => getLeapifyToken(authClient))\r\n */\r\nexport async function getLeapifyToken(\r\n // @ts-ignore - Kept for backwards compatibility with previous signature\r\n authClient?: LeapifyAuthClient,\r\n): Promise<string | null> {\r\n if (typeof window !== 'undefined') {\r\n return localStorage.getItem(AUTH_TOKEN_KEY)\r\n }\r\n return null\r\n}\r\n\r\n/**\r\n * Sign out the current user.\r\n */\r\nexport async function signOut(authClient: LeapifyAuthClient) {\r\n const result = await authClient.signOut()\r\n if (typeof window !== 'undefined') {\r\n localStorage.removeItem(AUTH_TOKEN_KEY)\r\n }\r\n return result\r\n}\r\n","declare global {\r\n interface Window {\r\n turnstile: {\r\n render: (\r\n container: string | HTMLElement,\r\n opts: { sitekey: string; callback: (token: string) => void },\r\n ) => string;\r\n remove: (widgetId: string) => void;\r\n };\r\n }\r\n}\r\n\r\nconst TURNSTILE_VERIFY_PATH = \"/.well-known/leapify/turnstile/verify\";\r\n\r\nfunction getTurnstileSiteKey(): string | undefined {\r\n const config = (window as unknown as Record<string, unknown>).__CONFIG__ as\r\n | { turnstileSiteKey?: string }\r\n | undefined;\r\n return config?.turnstileSiteKey;\r\n}\r\n\r\nfunction loadTurnstileScript(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (typeof window.turnstile !== \"undefined\") {\r\n resolve();\r\n return;\r\n }\r\n const script = document.createElement(\"script\");\r\n script.src =\r\n \"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit\";\r\n script.async = true;\r\n script.defer = true;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(\"Failed to load Turnstile script\"));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\nfunction executeTurnstile(siteKey: string): Promise<string> {\r\n let widgetId: string | undefined;\r\n\r\n const cleanup = () => {\r\n if (widgetId && typeof window.turnstile?.remove === \"function\") {\r\n window.turnstile.remove(widgetId);\r\n }\r\n const el = document.getElementById(\"leapify-turnstile-container\");\r\n el?.remove();\r\n };\r\n\r\n return new Promise((resolve) => {\r\n const container = document.createElement(\"div\");\r\n container.id = \"leapify-turnstile-container\";\r\n container.style.display = \"none\";\r\n document.body.appendChild(container);\r\n\r\n // Timeout guard — Turnstile iframe can hang if postMessage origin mismatch\r\n // or other widget issues prevent the callback from firing.\r\n // After 3s, continue without the cookie; the server-side auth middleware\r\n // will handle verified sessions via the Authorization header instead.\r\n const timer = setTimeout(() => {\r\n cleanup();\r\n resolve(\"\");\r\n }, 3_000);\r\n\r\n widgetId = window.turnstile.render(`#${container.id}`, {\r\n sitekey: siteKey,\r\n callback: (token: string) => {\r\n clearTimeout(timer);\r\n cleanup();\r\n resolve(token);\r\n },\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Solve a Turnstile challenge and obtain a signed cookie from the backend.\r\n *\r\n * Loads the Turnstile script (if not already loaded), executes an invisible\r\n * challenge, and posts the token to the backend verify endpoint. The server\r\n * sets a signed cookie that bypasses Turnstile for subsequent requests.\r\n *\r\n * Call once on app initialization before any API requests.\r\n *\r\n * @param baseUrl - The Leapify Worker URL. If omitted, uses the current origin.\r\n * @param siteKey - Turnstile site key. If omitted, reads from window.__CONFIG__.\r\n * @returns `true` if the challenge was solved and cookie was set.\r\n */\r\nexport async function solveTurnstileChallenge(\r\n baseUrl?: string,\r\n siteKey?: string,\r\n): Promise<boolean> {\r\n siteKey = siteKey ?? getTurnstileSiteKey();\r\n if (!siteKey) return false;\r\n\r\n const base = baseUrl?.replace(/\\/$/, \"\") ?? \"\";\r\n\r\n try {\r\n await loadTurnstileScript();\r\n const token = await executeTurnstile(siteKey);\r\n\r\n if (!token) return false;\r\n\r\n const res = await fetch(`${base}${TURNSTILE_VERIFY_PATH}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ token }),\r\n credentials: \"include\",\r\n });\r\n\r\n return res.ok;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","/**\r\n * Browser-safe session initialization helper.\r\n *\r\n * Checks for an existing session token and fetches the user profile.\r\n * Callers should run solveTurnstileChallenge() separately if the server\r\n * enforces Turnstile for unauthenticated requests.\r\n *\r\n * Import from 'leapify/client' — no Cloudflare, Drizzle, or Hono deps.\r\n *\r\n * @example\r\n * import { initializeSession, createLeapifyClient } from 'leapify/client'\r\n *\r\n * const user = await initializeSession(\r\n * 'https://api.leap.yourdomain.com',\r\n * () => getLeapifyToken(),\r\n * )\r\n * if (user) {\r\n * console.log(`Welcome ${user.name} (${user.role})`)\r\n * }\r\n */\r\n\r\nimport type { UserProfile } from \"./types\";\r\n\r\n/**\r\n * Initialize a browser session: restore existing token and fetch profile.\r\n *\r\n * @param baseUrl - The Leapify Worker URL.\r\n * @param getToken - Async function returning the current session token, or null.\r\n * @returns The authenticated user profile, or null if not signed in.\r\n */\r\nexport async function initializeSession(\r\n baseUrl: string,\r\n getToken: () => Promise<string | null>,\r\n): Promise<UserProfile | null> {\r\n const token = await getToken();\r\n if (!token) return null;\r\n\r\n const base = baseUrl.replace(/\\/$/, \"\");\r\n const res = await fetch(`${base}/api/users/me`, {\r\n headers: { Authorization: `Bearer ${token}` },\r\n });\r\n\r\n if (!res.ok) return null;\r\n\r\n const body = await res.json().catch(() => ({}));\r\n return (body as { data: UserProfile | null }).data ?? null;\r\n}\r\n","/**\r\n * Leapify browser-safe API client.\r\n *\r\n * Import from 'leapify/client' — no Cloudflare, Drizzle, or Hono dependencies.\r\n *\r\n * @example\r\n * import { createLeapifyClient, createLeapifyAuthClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * const authClient = createLeapifyAuthClient(process.env.NEXT_PUBLIC_API_URL!)\r\n * const api = createLeapifyClient(\r\n * process.env.NEXT_PUBLIC_API_URL!,\r\n * () => getLeapifyToken(authClient),\r\n * )\r\n *\r\n * const events = await api.getEvents()\r\n */\r\n\r\nexport type {\r\n LeapEvent,\r\n SlotInfo,\r\n UserProfile,\r\n BookmarkEntry,\r\n Faq,\r\n Theme,\r\n Organization,\r\n SiteConfig,\r\n ToggleBookmarkResult,\r\n LeapifyErrorBody,\r\n UserRole,\r\n EventStatus,\r\n CreateEventBody,\r\n CreateFaqBody,\r\n HealthResponse,\r\n RuntimeConfig,\r\n} from \"./types\";\r\n\r\nexport {\r\n createLeapifyAuthClient,\r\n signInWithGoogleRedirect,\r\n syncCookieSessionToStorage,\r\n getLeapifyToken,\r\n signOut,\r\n} from \"./auth\";\r\nexport type { LeapifyAuthClient } from \"./auth\";\r\n\r\nexport { solveTurnstileChallenge } from \"./turnstile\";\r\nexport { initializeSession } from \"./session\";\r\n\r\n/**\r\n * Read the runtime config injected by the worker into HTML pages.\r\n * Returns null if not running in a browser or config not injected.\r\n */\r\nexport function getClientConfig(): RuntimeConfig | null {\r\n if (typeof window === \"undefined\") return null;\r\n const config = (window as unknown as Record<string, unknown>).__CONFIG__;\r\n if (!config || typeof config !== \"object\") return null;\r\n return config as RuntimeConfig;\r\n}\r\n\r\nimport type { RuntimeConfig } from \"./types\";\r\n\r\n/**\r\n * Structured error thrown by all client methods on non-2xx responses.\r\n *\r\n * @example\r\n * import { LeapifyApiError } from 'leapify/client'\r\n *\r\n * try {\r\n * await api.toggleBookmark(eventId)\r\n * } catch (err) {\r\n * if (err instanceof LeapifyApiError && err.code === 'UNAUTHORIZED') {\r\n * // redirect to sign-in\r\n * }\r\n * }\r\n */\r\nexport class LeapifyApiError extends Error {\r\n constructor(\r\n public readonly status: number,\r\n public readonly code: string,\r\n message: string,\r\n ) {\r\n super(message);\r\n this.name = \"LeapifyApiError\";\r\n }\r\n}\r\n\r\n// ─── Error code constants ───────────────────────────────────────────────────\r\n\r\nexport const LEAPIFY_ERROR_CODES = {\r\n UNAUTHORIZED: \"UNAUTHORIZED\",\r\n DOMAIN_RESTRICTED: \"DOMAIN_RESTRICTED\",\r\n FORBIDDEN: \"FORBIDDEN\",\r\n NOT_FOUND: \"NOT_FOUND\",\r\n CONFLICT: \"CONFLICT\",\r\n TOO_MANY_REQUESTS: \"TOO_MANY_REQUESTS\",\r\n SERVICE_UNAVAILABLE: \"SERVICE_UNAVAILABLE\",\r\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\r\n} as const;\r\n\r\nexport type LeapifyErrorCode = keyof typeof LEAPIFY_ERROR_CODES;\r\n\r\n// ─── Client factory ─────────────────────────────────────────────────────────\r\n\r\nimport type {\r\n LeapEvent,\r\n SlotInfo,\r\n UserProfile,\r\n BookmarkEntry,\r\n Faq,\r\n Theme,\r\n Organization,\r\n SiteConfig,\r\n ToggleBookmarkResult,\r\n LeapifyErrorBody,\r\n CreateEventBody,\r\n CreateFaqBody,\r\n HealthResponse,\r\n} from \"./types\";\r\n\r\ntype GetTokenFn = () => Promise<string | null>;\r\n\r\nasync function buildHeaders(\r\n getToken: GetTokenFn | undefined,\r\n extra: Record<string, string> = {},\r\n): Promise<Record<string, string>> {\r\n const headers: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n ...extra,\r\n };\r\n if (getToken) {\r\n const token = await getToken();\r\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n return headers;\r\n}\r\n\r\nasync function parseResponse<T>(res: Response): Promise<T> {\r\n if (res.status === 204) return undefined as T;\r\n\r\n const body = await res.json().catch(() => ({}));\r\n\r\n if (!res.ok) {\r\n const err = (body as LeapifyErrorBody)?.error;\r\n throw new LeapifyApiError(\r\n res.status,\r\n err?.code ?? \"UNKNOWN\",\r\n err?.message ?? res.statusText,\r\n );\r\n }\r\n\r\n return (body as { data: T }).data;\r\n}\r\n\r\n/**\r\n * Creates a typed Leapify API client bound to a base URL.\r\n *\r\n * @param baseUrl - The deployed Leapify Worker URL (e.g. `https://api.leap.yourdomain.com`).\r\n * @param getToken - Optional async function that returns a session token string,\r\n * or null for guest requests. Use `getLeapifyToken()` from this module.\r\n *\r\n * @example\r\n * // lib/api.ts\r\n * import { createLeapifyClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * export const api = createLeapifyClient(\r\n * process.env.NEXT_PUBLIC_API_URL!,\r\n * () => getLeapifyToken(),\r\n * )\r\n */\r\nexport function createLeapifyClient(baseUrl: string, getToken?: GetTokenFn) {\r\n const base = baseUrl.replace(/\\/$/, \"\");\r\n\r\n async function get<T>(path: string, init?: RequestInit): Promise<T> {\r\n const headers = await buildHeaders(getToken, init?.headers as Record<string, string>);\r\n const res = await fetch(`${base}${path}`, { ...init, method: \"GET\", headers });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function post<T>(path: string, body?: unknown): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"POST\",\r\n headers,\r\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function postFormData<T>(path: string, formData: FormData): Promise<T> {\r\n const headers: Record<string, string> = {};\r\n if (getToken) {\r\n const token = await getToken();\r\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"POST\",\r\n headers,\r\n body: formData,\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function patch<T>(path: string, body: unknown): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"PATCH\",\r\n headers,\r\n body: JSON.stringify(body),\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function del<T>(path: string): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, { method: \"DELETE\", headers });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n return {\r\n // ── Site Config ────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /config\r\n * Returns site-wide configuration. Check `maintenanceMode` and\r\n * `comingSoonUntil` on app load to gate the UI appropriately.\r\n * Use `now` (server unix epoch) for timestamp comparisons.\r\n */\r\n getConfig(): Promise<SiteConfig> {\r\n return get<SiteConfig>(\"/api/config\");\r\n },\r\n\r\n /**\r\n * PATCH /api/config/:key — admin only.\r\n * Upserts a site config value. Requires admin or super_admin role.\r\n */\r\n updateConfig<K extends string>(key: K, value: unknown): Promise<{ key: K; value: unknown }> {\r\n return patch(`/api/config/${encodeURIComponent(key)}`, { value });\r\n },\r\n\r\n // ── Events ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/classes\r\n * Returns all published classes. Response is ETag-cached for 7 days.\r\n */\r\n getEvents(): Promise<LeapEvent[]> {\r\n return get<LeapEvent[]>(\"/api/classes\");\r\n },\r\n\r\n /**\r\n * GET /api/classes/admin — admin only.\r\n * Returns all classes regardless of status.\r\n */\r\n getAdminEvents(): Promise<LeapEvent[]> {\r\n return get<LeapEvent[]>(\"/api/classes/admin\");\r\n },\r\n\r\n /**\r\n * POST /api/classes/admin/publish — admin only.\r\n * Batch publish queued classes immediately or schedule them for later.\r\n */\r\n batchPublish(ids: string[], releaseAt?: number): Promise<{ updated: number }> {\r\n return post(\"/api/classes/admin/publish\", { ids, releaseAt });\r\n },\r\n\r\n /**\r\n * GET /api/classes/:slug\r\n * Returns a single published class by slug.\r\n */\r\n getEvent(slug: string): Promise<LeapEvent> {\r\n return get<LeapEvent>(`/api/classes/${encodeURIComponent(slug)}`);\r\n },\r\n\r\n /**\r\n * GET /api/classes/:slug/slots\r\n * Returns real-time slot availability. CF edge caches this for 5 seconds.\r\n * Poll every 8–10 seconds on class detail pages.\r\n */\r\n getSlots(slug: string): Promise<SlotInfo> {\r\n return get<SlotInfo>(`/api/classes/${encodeURIComponent(slug)}/slots`);\r\n },\r\n\r\n /**\r\n * POST /api/classes — admin only.\r\n * Creates a new class. Auto-generates slug from title.\r\n */\r\n createEvent(data: CreateEventBody): Promise<LeapEvent> {\r\n return post<LeapEvent>(\"/api/classes\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/classes/:slug — admin only.\r\n * Updates an existing class by slug.\r\n */\r\n updateEvent(slug: string, data: Partial<CreateEventBody>): Promise<LeapEvent> {\r\n return patch<LeapEvent>(`/api/classes/${encodeURIComponent(slug)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/classes/:slug — admin only.\r\n * Deletes a class.\r\n */\r\n deleteEvent(slug: string): Promise<void> {\r\n return del<void>(`/api/classes/${encodeURIComponent(slug)}`);\r\n },\r\n\r\n // ── Themes ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/themes\r\n * Returns all themes.\r\n */\r\n getThemes(): Promise<Theme[]> {\r\n return get<Theme[]>(\"/api/themes\");\r\n },\r\n\r\n /**\r\n * POST /api/themes — admin only.\r\n */\r\n createTheme(data: Omit<Theme, \"id\" | \"createdAt\">): Promise<Theme> {\r\n return post<Theme>(\"/api/themes\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/themes/:id — admin only.\r\n */\r\n updateTheme(id: string, data: Partial<Omit<Theme, \"id\" | \"createdAt\">>): Promise<Theme> {\r\n return patch<Theme>(`/api/themes/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/themes/:id — admin only.\r\n */\r\n deleteTheme(id: string): Promise<void> {\r\n return del<void>(`/api/themes/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Organizations ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/organizations\r\n * Returns all organizations.\r\n */\r\n getOrganizations(): Promise<Organization[]> {\r\n return get<Organization[]>(\"/api/organizations\");\r\n },\r\n\r\n /**\r\n * POST /api/organizations — admin only.\r\n */\r\n createOrganization(data: Omit<Organization, \"id\" | \"createdAt\">): Promise<Organization> {\r\n return post<Organization>(\"/api/organizations\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/organizations/:id — admin only.\r\n */\r\n updateOrganization(id: string, data: Partial<Omit<Organization, \"id\" | \"createdAt\">>): Promise<Organization> {\r\n return patch<Organization>(`/api/organizations/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/organizations/:id — admin only.\r\n */\r\n deleteOrganization(id: string): Promise<void> {\r\n return del<void>(`/api/organizations/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Users ──────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users/me\r\n * Returns the authenticated user's profile, or null for guests.\r\n * Use `profile.role` to gate admin UI.\r\n */\r\n getMe(): Promise<UserProfile | null> {\r\n return get<UserProfile | null>(\"/api/users/me\");\r\n },\r\n\r\n // ── Admin: User Management ────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users — admin only.\r\n * Returns all registered users.\r\n */\r\n getUsers(): Promise<UserProfile[]> {\r\n return get<UserProfile[]>(\"/api/users\");\r\n },\r\n\r\n /**\r\n * PATCH /api/users/:id/role — admin only.\r\n * Changes a user's role.\r\n */\r\n updateUserRole(id: string, role: string): Promise<UserProfile> {\r\n return patch<UserProfile>(`/api/users/${encodeURIComponent(id)}/role`, { role });\r\n },\r\n\r\n /**\r\n * POST /api/users/by-email — admin only.\r\n * Finds or creates a user by email and sets their role.\r\n */\r\n upsertUserByEmail(email: string, role: string): Promise<UserProfile> {\r\n return post<UserProfile>(\"/api/users/by-email\", { email, role });\r\n },\r\n\r\n // ── Bookmarks ──────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users/me/bookmarks\r\n * Returns the authenticated user's bookmarked events.\r\n * Returns an empty array for unauthenticated users.\r\n */\r\n getBookmarks(): Promise<BookmarkEntry[]> {\r\n return get<BookmarkEntry[]>(\"/api/users/me/bookmarks\");\r\n },\r\n\r\n /**\r\n * POST /api/users/me/bookmarks/:eventId\r\n * Toggles a bookmark on/off. Requires authentication.\r\n * Returns `{ bookmarked: true }` (201) on add, `{ bookmarked: false }` (200) on remove.\r\n */\r\n toggleBookmark(eventId: string): Promise<ToggleBookmarkResult> {\r\n return post<ToggleBookmarkResult>(\r\n `/api/users/me/bookmarks/${encodeURIComponent(eventId)}`,\r\n );\r\n },\r\n\r\n /**\r\n * DELETE /api/users/me/bookmarks/:eventId\r\n * Removes a bookmark. Requires authentication.\r\n */\r\n deleteBookmark(eventId: string): Promise<ToggleBookmarkResult> {\r\n return del<ToggleBookmarkResult>(\r\n `/api/users/me/bookmarks/${encodeURIComponent(eventId)}`,\r\n );\r\n },\r\n\r\n // ── FAQs ───────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/faqs\r\n * Returns all active FAQs. Cached in KV for 10 minutes.\r\n * The `answer` field is markdown — render with a markdown library.\r\n */\r\n getFaqs(): Promise<Faq[]> {\r\n return get<Faq[]>(\"/api/faqs\");\r\n },\r\n\r\n /**\r\n * POST /api/faqs — admin only.\r\n * Creates a new FAQ item.\r\n */\r\n createFaq(data: CreateFaqBody): Promise<Faq> {\r\n return post<Faq>(\"/api/faqs\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/faqs/:id — admin only.\r\n * Updates an existing FAQ item.\r\n */\r\n updateFaq(id: string, data: Partial<CreateFaqBody>): Promise<Faq> {\r\n return patch<Faq>(`/api/faqs/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/faqs/:id — admin only.\r\n * Soft-deletes a FAQ (sets isActive: false).\r\n */\r\n deleteFaq(id: string): Promise<{ deleted: boolean }> {\r\n return del<{ deleted: boolean }>(`/api/faqs/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Uploads ────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * POST /api/uploads/images — admin only.\r\n * Uploads an image file to R2. Accepts multipart/form-data.\r\n * Returns the public URL, storage key, size, and content type.\r\n */\r\n uploadImage(file: File | Blob): Promise<{\r\n url: string;\r\n key: string;\r\n size: number;\r\n contentType: string;\r\n }> {\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n return postFormData(\"/api/uploads/images\", formData);\r\n },\r\n\r\n // ── Health ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /health\r\n * Public health check. Returns provider availability status.\r\n */\r\n healthCheck(): Promise<HealthResponse> {\r\n return get<HealthResponse>(\"/health\");\r\n },\r\n };\r\n}\r\n\r\nexport type LeapifyClient = ReturnType<typeof createLeapifyClient>;\r\n"]}
1
+ {"version":3,"sources":["../../src/client/auth.ts","../../src/client/turnstile.ts","../../src/client/session.ts","../../src/client/index.ts"],"names":["createAuthClient"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Better Auth client helper for Leapify API consumers.\r\n *\r\n * This module is **browser-safe** — no Cloudflare, Drizzle, or Hono deps.\r\n * It wraps Better Auth's client SDK with the bearer plugin so that tokens\r\n * can be stored and retrieved as plain strings (no cookie dependency on\r\n * the consumer's frontend).\r\n *\r\n * @example\r\n * // lib/auth.ts (frontend)\r\n * import { createLeapifyAuthClient, signInWithGoogleRedirect } from 'leapify/client'\r\n *\r\n * export const authClient = createLeapifyAuthClient(process.env.NEXT_PUBLIC_API_URL!)\r\n *\r\n * // Redirect-based Google sign-in:\r\n * await signInWithGoogleRedirect(authClient, '/dashboard')\r\n */\r\n\r\nimport { createAuthClient } from 'better-auth/client'\r\n\r\nconst AUTH_TOKEN_KEY = 'better-auth.session_token'\r\n\r\n/**\r\n * Create a Better Auth client bound to the Leapify Worker URL.\r\n *\r\n * It uses the 'Bearer' auth type to send the stored session token\r\n * in the Authorization header.\r\n */\r\nexport function createLeapifyAuthClient(baseUrl: string) {\r\n return createAuthClient({\r\n baseURL: baseUrl,\r\n fetchOptions: {\r\n auth: {\r\n type: 'Bearer',\r\n token: () => {\r\n if (typeof window !== 'undefined') {\r\n return localStorage.getItem(AUTH_TOKEN_KEY) || ''\r\n }\r\n return ''\r\n }\r\n }\r\n }\r\n })\r\n}\r\n\r\nexport type LeapifyAuthClient = ReturnType<typeof createLeapifyAuthClient>\r\n\r\n/**\r\n * Sign in with Google via OAuth redirect flow.\r\n *\r\n * Redirects the browser to Google's OAuth page. After authentication,\r\n * Google redirects back to the Better Auth callback endpoint, which\r\n * creates a session and redirects to `callbackURL`.\r\n *\r\n * Call `syncCookieSessionToStorage()` on app init to restore the\r\n * session from the cookie after a redirect-based sign-in.\r\n *\r\n * @param authClient - Client created by createLeapifyAuthClient\r\n * @param callbackURL - Path or URL to redirect to after successful auth (e.g. '/dashboard')\r\n *\r\n * @example\r\n * import { signInWithGoogleRedirect } from 'leapify/client'\r\n *\r\n * document.getElementById('google-btn').onclick = () => {\r\n * signInWithGoogleRedirect(authClient, '/dashboard')\r\n * }\r\n */\r\nexport async function signInWithGoogleRedirect(\r\n authClient: LeapifyAuthClient,\r\n callbackURL: string,\r\n): Promise<void> {\r\n await authClient.signIn.social({\r\n provider: 'google',\r\n callbackURL,\r\n })\r\n}\r\n\r\n/**\r\n * Sync a cookie-based Better Auth session into localStorage.\r\n *\r\n * After an OAuth redirect flow, Better Auth stores the session in an\r\n * HTTP-only cookie. This function reads that session via `getSession()`\r\n * and stores the token in localStorage so that subsequent API calls\r\n * using the Bearer token work correctly.\r\n *\r\n * Call this once on app initialization, before `initializeSession()`.\r\n *\r\n * @param authClient - Client created by createLeapifyAuthClient\r\n *\r\n * @example\r\n * import { syncCookieSessionToStorage, initializeSession } from 'leapify/client'\r\n *\r\n * // On app mount:\r\n * await syncCookieSessionToStorage(authClient)\r\n * const user = await initializeSession(API_URL, getToken)\r\n */\r\nexport async function syncCookieSessionToStorage(\r\n authClient: LeapifyAuthClient,\r\n): Promise<void> {\r\n try {\r\n const result = await authClient.getSession()\r\n const data = result?.data as { session?: { token?: string } } | undefined\r\n const token = data?.session?.token\r\n if (token) {\r\n localStorage.setItem(AUTH_TOKEN_KEY, token)\r\n }\r\n } catch {\r\n // No cookie session — user is a guest.\r\n }\r\n}\r\n\r\n/**\r\n * Get the current bearer token from storage, or null for guests.\r\n * Pass this to `createLeapifyClient` as the `getToken` option.\r\n *\r\n * @example\r\n * import { createLeapifyClient } from 'leapify/client'\r\n * import { createLeapifyAuthClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * const authClient = createLeapifyAuthClient(API_URL)\r\n * const api = createLeapifyClient(API_URL, () => getLeapifyToken(authClient))\r\n */\r\nexport async function getLeapifyToken(\r\n // @ts-ignore - Kept for backwards compatibility with previous signature\r\n authClient?: LeapifyAuthClient,\r\n): Promise<string | null> {\r\n if (typeof window !== 'undefined') {\r\n return localStorage.getItem(AUTH_TOKEN_KEY)\r\n }\r\n return null\r\n}\r\n\r\n/**\r\n * Sign out the current user.\r\n */\r\nexport async function signOut(authClient: LeapifyAuthClient) {\r\n const result = await authClient.signOut()\r\n if (typeof window !== 'undefined') {\r\n localStorage.removeItem(AUTH_TOKEN_KEY)\r\n }\r\n return result\r\n}\r\n","declare global {\r\n interface Window {\r\n turnstile: {\r\n render: (\r\n container: string | HTMLElement,\r\n opts: { sitekey: string; callback: (token: string) => void },\r\n ) => string;\r\n remove: (widgetId: string) => void;\r\n };\r\n }\r\n}\r\n\r\nconst TURNSTILE_VERIFY_PATH = \"/.well-known/leapify/turnstile/verify\";\r\n\r\nfunction getTurnstileSiteKey(): string | undefined {\r\n const config = (window as unknown as Record<string, unknown>).__CONFIG__ as\r\n | { turnstileSiteKey?: string }\r\n | undefined;\r\n return config?.turnstileSiteKey;\r\n}\r\n\r\nfunction loadTurnstileScript(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (typeof window.turnstile !== \"undefined\") {\r\n resolve();\r\n return;\r\n }\r\n const script = document.createElement(\"script\");\r\n script.src =\r\n \"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit\";\r\n script.async = true;\r\n script.defer = true;\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error(\"Failed to load Turnstile script\"));\r\n document.head.appendChild(script);\r\n });\r\n}\r\n\r\nfunction executeTurnstile(siteKey: string): Promise<string> {\r\n let widgetId: string | undefined;\r\n\r\n const cleanup = () => {\r\n if (widgetId && typeof window.turnstile?.remove === \"function\") {\r\n window.turnstile.remove(widgetId);\r\n }\r\n const el = document.getElementById(\"leapify-turnstile-container\");\r\n el?.remove();\r\n };\r\n\r\n return new Promise((resolve) => {\r\n const container = document.createElement(\"div\");\r\n container.id = \"leapify-turnstile-container\";\r\n container.style.display = \"none\";\r\n document.body.appendChild(container);\r\n\r\n // Timeout guard — Turnstile iframe can hang if postMessage origin mismatch\r\n // or other widget issues prevent the callback from firing.\r\n // After 3s, continue without the cookie; the server-side auth middleware\r\n // will handle verified sessions via the Authorization header instead.\r\n const timer = setTimeout(() => {\r\n cleanup();\r\n resolve(\"\");\r\n }, 3_000);\r\n\r\n widgetId = window.turnstile.render(`#${container.id}`, {\r\n sitekey: siteKey,\r\n callback: (token: string) => {\r\n clearTimeout(timer);\r\n cleanup();\r\n resolve(token);\r\n },\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Solve a Turnstile challenge and obtain a signed cookie from the backend.\r\n *\r\n * Loads the Turnstile script (if not already loaded), executes an invisible\r\n * challenge, and posts the token to the backend verify endpoint. The server\r\n * sets a signed cookie that bypasses Turnstile for subsequent requests.\r\n *\r\n * Call once on app initialization before any API requests.\r\n *\r\n * @param baseUrl - The Leapify Worker URL. If omitted, uses the current origin.\r\n * @param siteKey - Turnstile site key. If omitted, reads from window.__CONFIG__.\r\n * @returns `true` if the challenge was solved and cookie was set.\r\n */\r\nexport async function solveTurnstileChallenge(\r\n baseUrl?: string,\r\n siteKey?: string,\r\n): Promise<boolean> {\r\n siteKey = siteKey ?? getTurnstileSiteKey();\r\n if (!siteKey) return false;\r\n\r\n const base = baseUrl?.replace(/\\/$/, \"\") ?? \"\";\r\n\r\n try {\r\n await loadTurnstileScript();\r\n const token = await executeTurnstile(siteKey);\r\n\r\n if (!token) return false;\r\n\r\n const res = await fetch(`${base}${TURNSTILE_VERIFY_PATH}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ token }),\r\n credentials: \"include\",\r\n });\r\n\r\n return res.ok;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","/**\r\n * Browser-safe session initialization helper.\r\n *\r\n * Checks for an existing session token and fetches the user profile.\r\n * Callers should run solveTurnstileChallenge() separately if the server\r\n * enforces Turnstile for unauthenticated requests.\r\n *\r\n * Import from 'leapify/client' — no Cloudflare, Drizzle, or Hono deps.\r\n *\r\n * @example\r\n * import { initializeSession, createLeapifyClient } from 'leapify/client'\r\n *\r\n * const user = await initializeSession(\r\n * 'https://api.leap.yourdomain.com',\r\n * () => getLeapifyToken(),\r\n * )\r\n * if (user) {\r\n * console.log(`Welcome ${user.name} (${user.role})`)\r\n * }\r\n */\r\n\r\nimport type { UserProfile } from \"./types\";\r\n\r\n/**\r\n * Initialize a browser session: restore existing token and fetch profile.\r\n *\r\n * @param baseUrl - The Leapify Worker URL.\r\n * @param getToken - Async function returning the current session token, or null.\r\n * @returns The authenticated user profile, or null if not signed in.\r\n */\r\nexport async function initializeSession(\r\n baseUrl: string,\r\n getToken: () => Promise<string | null>,\r\n): Promise<UserProfile | null> {\r\n const token = await getToken();\r\n if (!token) return null;\r\n\r\n const base = baseUrl.replace(/\\/$/, \"\");\r\n const res = await fetch(`${base}/api/users/me`, {\r\n headers: { Authorization: `Bearer ${token}` },\r\n });\r\n\r\n if (!res.ok) return null;\r\n\r\n const body = await res.json().catch(() => ({}));\r\n return (body as { data: UserProfile | null }).data ?? null;\r\n}\r\n","/**\r\n * Leapify browser-safe API client.\r\n *\r\n * Import from 'leapify/client' — no Cloudflare, Drizzle, or Hono dependencies.\r\n *\r\n * @example\r\n * import { createLeapifyClient, createLeapifyAuthClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * const authClient = createLeapifyAuthClient(process.env.NEXT_PUBLIC_API_URL!)\r\n * const api = createLeapifyClient(\r\n * process.env.NEXT_PUBLIC_API_URL!,\r\n * () => getLeapifyToken(authClient),\r\n * )\r\n *\r\n * const events = await api.getEvents()\r\n */\r\n\r\nexport type {\r\n LeapEvent,\r\n SlotInfo,\r\n UserProfile,\r\n BookmarkEntry,\r\n Faq,\r\n Theme,\r\n Organization,\r\n SiteConfig,\r\n ToggleBookmarkResult,\r\n LeapifyErrorBody,\r\n UserRole,\r\n EventStatus,\r\n CreateEventBody,\r\n CreateFaqBody,\r\n HealthResponse,\r\n RuntimeConfig,\r\n} from \"./types\";\r\n\r\nexport {\r\n createLeapifyAuthClient,\r\n signInWithGoogleRedirect,\r\n syncCookieSessionToStorage,\r\n getLeapifyToken,\r\n signOut,\r\n} from \"./auth\";\r\nexport type { LeapifyAuthClient } from \"./auth\";\r\n\r\nexport { solveTurnstileChallenge } from \"./turnstile\";\r\nexport { initializeSession } from \"./session\";\r\n\r\n/**\r\n * Read the runtime config injected by the worker into HTML pages.\r\n * Returns null if not running in a browser or config not injected.\r\n */\r\nexport function getClientConfig(): RuntimeConfig | null {\r\n if (typeof window === \"undefined\") return null;\r\n const config = (window as unknown as Record<string, unknown>).__CONFIG__;\r\n if (!config || typeof config !== \"object\") return null;\r\n return config as RuntimeConfig;\r\n}\r\n\r\nimport type { RuntimeConfig } from \"./types\";\r\n\r\n/**\r\n * Structured error thrown by all client methods on non-2xx responses.\r\n *\r\n * @example\r\n * import { LeapifyApiError } from 'leapify/client'\r\n *\r\n * try {\r\n * await api.toggleBookmark(eventId)\r\n * } catch (err) {\r\n * if (err instanceof LeapifyApiError && err.code === 'UNAUTHORIZED') {\r\n * // redirect to sign-in\r\n * }\r\n * }\r\n */\r\nexport class LeapifyApiError extends Error {\r\n constructor(\r\n public readonly status: number,\r\n public readonly code: string,\r\n message: string,\r\n ) {\r\n super(message);\r\n this.name = \"LeapifyApiError\";\r\n }\r\n}\r\n\r\n// ─── Error code constants ───────────────────────────────────────────────────\r\n\r\nexport const LEAPIFY_ERROR_CODES = {\r\n UNAUTHORIZED: \"UNAUTHORIZED\",\r\n DOMAIN_RESTRICTED: \"DOMAIN_RESTRICTED\",\r\n FORBIDDEN: \"FORBIDDEN\",\r\n NOT_FOUND: \"NOT_FOUND\",\r\n CONFLICT: \"CONFLICT\",\r\n TOO_MANY_REQUESTS: \"TOO_MANY_REQUESTS\",\r\n SERVICE_UNAVAILABLE: \"SERVICE_UNAVAILABLE\",\r\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\r\n} as const;\r\n\r\nexport type LeapifyErrorCode = keyof typeof LEAPIFY_ERROR_CODES;\r\n\r\n// ─── Client factory ─────────────────────────────────────────────────────────\r\n\r\nimport type {\r\n LeapEvent,\r\n SlotInfo,\r\n UserProfile,\r\n BookmarkEntry,\r\n Faq,\r\n Theme,\r\n Organization,\r\n SiteConfig,\r\n ToggleBookmarkResult,\r\n LeapifyErrorBody,\r\n CreateEventBody,\r\n CreateFaqBody,\r\n HealthResponse,\r\n} from \"./types\";\r\n\r\ntype GetTokenFn = () => Promise<string | null>;\r\n\r\nasync function buildHeaders(\r\n getToken: GetTokenFn | undefined,\r\n extra: Record<string, string> = {},\r\n): Promise<Record<string, string>> {\r\n const headers: Record<string, string> = {\r\n \"Content-Type\": \"application/json\",\r\n ...extra,\r\n };\r\n if (getToken) {\r\n const token = await getToken();\r\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n return headers;\r\n}\r\n\r\nasync function parseResponse<T>(res: Response): Promise<T> {\r\n if (res.status === 204) return undefined as T;\r\n\r\n const body = await res.json().catch(() => ({}));\r\n\r\n if (!res.ok) {\r\n const err = (body as LeapifyErrorBody)?.error;\r\n throw new LeapifyApiError(\r\n res.status,\r\n err?.code ?? \"UNKNOWN\",\r\n err?.message ?? res.statusText,\r\n );\r\n }\r\n\r\n return (body as { data: T }).data;\r\n}\r\n\r\n/**\r\n * Creates a typed Leapify API client bound to a base URL.\r\n *\r\n * @param baseUrl - The deployed Leapify Worker URL (e.g. `https://api.leap.yourdomain.com`).\r\n * @param getToken - Optional async function that returns a session token string,\r\n * or null for guest requests. Use `getLeapifyToken()` from this module.\r\n *\r\n * @example\r\n * // lib/api.ts\r\n * import { createLeapifyClient, getLeapifyToken } from 'leapify/client'\r\n *\r\n * export const api = createLeapifyClient(\r\n * process.env.NEXT_PUBLIC_API_URL!,\r\n * () => getLeapifyToken(),\r\n * )\r\n */\r\nexport function createLeapifyClient(baseUrl: string, getToken?: GetTokenFn) {\r\n const base = baseUrl.replace(/\\/$/, \"\");\r\n\r\n async function get<T>(path: string, init?: RequestInit): Promise<T> {\r\n const headers = await buildHeaders(getToken, init?.headers as Record<string, string>);\r\n const res = await fetch(`${base}${path}`, { ...init, method: \"GET\", headers });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function post<T>(path: string, body?: unknown): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"POST\",\r\n headers,\r\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function postFormData<T>(path: string, formData: FormData): Promise<T> {\r\n const headers: Record<string, string> = {};\r\n if (getToken) {\r\n const token = await getToken();\r\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\r\n }\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"POST\",\r\n headers,\r\n body: formData,\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function patch<T>(path: string, body: unknown): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, {\r\n method: \"PATCH\",\r\n headers,\r\n body: JSON.stringify(body),\r\n });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n async function del<T>(path: string): Promise<T> {\r\n const headers = await buildHeaders(getToken);\r\n const res = await fetch(`${base}${path}`, { method: \"DELETE\", headers });\r\n return parseResponse<T>(res);\r\n }\r\n\r\n return {\r\n // ── Site Config ────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /config\r\n * Returns site-wide configuration. Check `maintenanceMode` and\r\n * `comingSoonUntil` on app load to gate the UI appropriately.\r\n * Use `now` (server unix epoch) for timestamp comparisons.\r\n */\r\n getConfig(): Promise<SiteConfig> {\r\n return get<SiteConfig>(\"/api/config\");\r\n },\r\n\r\n /**\r\n * PATCH /api/config/:key — admin only.\r\n * Upserts a site config value. Requires admin or super_admin role.\r\n */\r\n updateConfig<K extends string>(key: K, value: unknown): Promise<{ key: K; value: unknown }> {\r\n return patch(`/api/config/${encodeURIComponent(key)}`, { value });\r\n },\r\n\r\n // ── Events ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/classes\r\n * Returns all published classes. Response is ETag-cached for 7 days.\r\n */\r\n getEvents(): Promise<LeapEvent[]> {\r\n return get<LeapEvent[]>(\"/api/classes\");\r\n },\r\n\r\n /**\r\n * GET /api/classes/admin — admin only.\r\n * Returns all classes regardless of status.\r\n */\r\n getAdminEvents(): Promise<LeapEvent[]> {\r\n return get<LeapEvent[]>(\"/api/classes/admin\");\r\n },\r\n\r\n /**\r\n * POST /api/classes/admin/publish — admin only.\r\n * Batch publish queued classes immediately or schedule them for later.\r\n */\r\n batchPublish(ids: string[], releaseAt?: number): Promise<{ updated: number }> {\r\n return post(\"/api/classes/admin/publish\", { ids, releaseAt });\r\n },\r\n\r\n /**\r\n * GET /api/classes/:slug\r\n * Returns a single published class by slug.\r\n */\r\n getEvent(slug: string): Promise<LeapEvent> {\r\n return get<LeapEvent>(`/api/classes/${encodeURIComponent(slug)}`);\r\n },\r\n\r\n /**\r\n * GET /api/classes/:slug/slots\r\n * Returns real-time slot availability. CF edge caches this for 5 seconds.\r\n * Poll every 8–10 seconds on class detail pages.\r\n */\r\n getSlots(slug: string): Promise<SlotInfo> {\r\n return get<SlotInfo>(`/api/classes/${encodeURIComponent(slug)}/slots`);\r\n },\r\n\r\n /**\r\n * POST /api/classes — admin only.\r\n * Creates a new class. Auto-generates slug from title.\r\n */\r\n createEvent(data: CreateEventBody): Promise<LeapEvent> {\r\n return post<LeapEvent>(\"/api/classes\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/classes/:slug — admin only.\r\n * Updates an existing class by slug.\r\n */\r\n updateEvent(slug: string, data: Partial<CreateEventBody>): Promise<LeapEvent> {\r\n return patch<LeapEvent>(`/api/classes/${encodeURIComponent(slug)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/classes/:slug — admin only.\r\n * Deletes a class.\r\n */\r\n deleteEvent(slug: string): Promise<void> {\r\n return del<void>(`/api/classes/${encodeURIComponent(slug)}`);\r\n },\r\n\r\n // ── Themes ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/themes\r\n * Returns all themes.\r\n */\r\n getThemes(): Promise<Theme[]> {\r\n return get<Theme[]>(\"/api/themes\");\r\n },\r\n\r\n /**\r\n * POST /api/themes — admin only.\r\n */\r\n createTheme(data: Omit<Theme, \"id\" | \"createdAt\">): Promise<Theme> {\r\n return post<Theme>(\"/api/themes\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/themes/:id — admin only.\r\n */\r\n updateTheme(id: string, data: Partial<Omit<Theme, \"id\" | \"createdAt\">>): Promise<Theme> {\r\n return patch<Theme>(`/api/themes/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/themes/:id — admin only.\r\n */\r\n deleteTheme(id: string): Promise<void> {\r\n return del<void>(`/api/themes/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Organizations ──────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/organizations\r\n * Returns all organizations.\r\n */\r\n getOrganizations(): Promise<Organization[]> {\r\n return get<Organization[]>(\"/api/organizations\");\r\n },\r\n\r\n /**\r\n * POST /api/organizations — admin only.\r\n */\r\n createOrganization(data: Omit<Organization, \"id\" | \"createdAt\">): Promise<Organization> {\r\n return post<Organization>(\"/api/organizations\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/organizations/:id — admin only.\r\n */\r\n updateOrganization(id: string, data: Partial<Omit<Organization, \"id\" | \"createdAt\">>): Promise<Organization> {\r\n return patch<Organization>(`/api/organizations/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/organizations/:id — admin only.\r\n */\r\n deleteOrganization(id: string): Promise<void> {\r\n return del<void>(`/api/organizations/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Users ──────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users/me\r\n * Returns the authenticated user's profile, or null for guests.\r\n * Use `profile.role` to gate admin UI.\r\n */\r\n getMe(): Promise<UserProfile | null> {\r\n return get<UserProfile | null>(\"/api/users/me\");\r\n },\r\n\r\n // ── Admin: User Management ────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users — admin only.\r\n * Returns all registered users.\r\n */\r\n getUsers(): Promise<UserProfile[]> {\r\n return get<UserProfile[]>(\"/api/users\");\r\n },\r\n\r\n /**\r\n * PATCH /api/users/:id/role — admin only.\r\n * Changes a user's role.\r\n */\r\n updateUserRole(id: string, role: string): Promise<UserProfile> {\r\n return patch<UserProfile>(`/api/users/${encodeURIComponent(id)}/role`, { role });\r\n },\r\n\r\n /**\r\n * POST /api/users/by-email — admin only.\r\n * Finds or creates a user by email and sets their role.\r\n */\r\n upsertUserByEmail(email: string, role: string): Promise<UserProfile> {\r\n return post<UserProfile>(\"/api/users/by-email\", { email, role });\r\n },\r\n\r\n // ── Bookmarks ──────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/users/me/bookmarks\r\n * Returns the authenticated user's bookmarked events.\r\n * Returns an empty array for unauthenticated users.\r\n */\r\n getBookmarks(): Promise<BookmarkEntry[]> {\r\n return get<BookmarkEntry[]>(\"/api/users/me/bookmarks\");\r\n },\r\n\r\n /**\r\n * POST /api/users/me/bookmarks/:eventId\r\n * Toggles a bookmark on/off. Requires authentication.\r\n * Returns `{ bookmarked: true }` (201) on add, `{ bookmarked: false }` (200) on remove.\r\n */\r\n toggleBookmark(eventId: string): Promise<ToggleBookmarkResult> {\r\n return post<ToggleBookmarkResult>(\r\n `/api/users/me/bookmarks/${encodeURIComponent(eventId)}`,\r\n );\r\n },\r\n\r\n /**\r\n * DELETE /api/users/me/bookmarks/:eventId\r\n * Removes a bookmark. Requires authentication.\r\n */\r\n deleteBookmark(eventId: string): Promise<ToggleBookmarkResult> {\r\n return del<ToggleBookmarkResult>(\r\n `/api/users/me/bookmarks/${encodeURIComponent(eventId)}`,\r\n );\r\n },\r\n\r\n // ── FAQs ───────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /api/faqs\r\n * Returns all active FAQs. Cached in KV for 10 minutes.\r\n * The `answer` field is markdown — render with a markdown library.\r\n */\r\n getFaqs(): Promise<Faq[]> {\r\n return get<Faq[]>(\"/api/faqs\");\r\n },\r\n\r\n /**\r\n * POST /api/faqs — admin only.\r\n * Creates a new FAQ item.\r\n */\r\n createFaq(data: CreateFaqBody): Promise<Faq> {\r\n return post<Faq>(\"/api/faqs\", data);\r\n },\r\n\r\n /**\r\n * PATCH /api/faqs/:id — admin only.\r\n * Updates an existing FAQ item.\r\n */\r\n updateFaq(id: string, data: Partial<CreateFaqBody>): Promise<Faq> {\r\n return patch<Faq>(`/api/faqs/${encodeURIComponent(id)}`, data);\r\n },\r\n\r\n /**\r\n * DELETE /api/faqs/:id — admin only.\r\n * Soft-deletes a FAQ (sets isActive: false).\r\n */\r\n deleteFaq(id: string): Promise<{ deleted: boolean }> {\r\n return del<{ deleted: boolean }>(`/api/faqs/${encodeURIComponent(id)}`);\r\n },\r\n\r\n // ── Uploads ────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * POST /api/uploads/images — admin only.\r\n * Uploads an image file to R2. Accepts multipart/form-data.\r\n * Returns the public URL, storage key, size, and content type.\r\n */\r\n uploadImage(file: File | Blob): Promise<{\r\n url: string;\r\n key: string;\r\n size: number;\r\n contentType: string;\r\n }> {\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n return postFormData(\"/api/uploads/images\", formData);\r\n },\r\n\r\n // ── Health ─────────────────────────────────────────────────────────────\r\n\r\n /**\r\n * GET /health\r\n * Public health check. Returns provider availability status.\r\n */\r\n healthCheck(): Promise<HealthResponse> {\r\n return get<HealthResponse>(\"/health\");\r\n },\r\n };\r\n}\r\n\r\nexport type LeapifyClient = ReturnType<typeof createLeapifyClient>;\r\n"]}
@@ -145,6 +145,8 @@ var LeapifyApiError = class extends Error {
145
145
  this.code = code;
146
146
  this.name = "LeapifyApiError";
147
147
  }
148
+ status;
149
+ code;
148
150
  };
149
151
  var LEAPIFY_ERROR_CODES = {
150
152
  UNAUTHORIZED: "UNAUTHORIZED",