@access-dlsu/leapify 0.260601.2 → 0.260602.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-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
31
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").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-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>;
39
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
40
40
  }[];
41
41
  };
42
42
  options: import("better-auth/plugins").BearerOptions | undefined;
@@ -14,6 +14,8 @@ var EXEMPT_PATHS = [
14
14
  "/api/classes",
15
15
  "/api/faqs",
16
16
  "/api/config",
17
+ "/api/themes",
18
+ "/api/organizations",
17
19
  TURNSTILE_VERIFY_PATH
18
20
  ];
19
21
  function base64urlEncode(bytes) {
@@ -157,5 +159,5 @@ function createTurnstileMiddleware() {
157
159
  }
158
160
 
159
161
  export { TURNSTILE_COOKIE_NAME, TURNSTILE_PATH, TURNSTILE_VERIFY_PATH, createTurnstileMiddleware, handleTurnstileVerify };
160
- //# sourceMappingURL=chunk-2JEY6TSO.js.map
161
- //# sourceMappingURL=chunk-2JEY6TSO.js.map
162
+ //# sourceMappingURL=chunk-WTA2QGY5.js.map
163
+ //# sourceMappingURL=chunk-WTA2QGY5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/middleware/turnstile-challenge.ts"],"names":[],"mappings":"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","file":"chunk-WTA2QGY5.js","sourcesContent":["import { createMiddleware } from 'hono/factory'\r\nimport type { Context } from 'hono'\r\nimport type { LeapifyBindings } from '../../types'\r\n\r\nexport const TURNSTILE_PATH = '/.well-known/leapify/turnstile'\r\n\r\nexport const TURNSTILE_VERIFY_PATH = `${TURNSTILE_PATH}/verify`\r\n\r\nexport const TURNSTILE_COOKIE_NAME = 'leapify-turnstile'\r\n\r\nconst VERIFY_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'\r\n\r\nconst COOKIE_MAX_AGE_SEC = 86400\r\n\r\nconst EXEMPT_PATHS = [\r\n \"/health\",\r\n \"/internal\",\r\n \"/api/auth\",\r\n \"/api/uploads/images\",\r\n \"/api/classes\",\r\n \"/api/faqs\",\r\n \"/api/config\",\r\n \"/api/themes\",\r\n \"/api/organizations\",\r\n TURNSTILE_VERIFY_PATH,\r\n];\r\n\r\nfunction base64urlEncode(bytes: Uint8Array): string {\r\n let binary = ''\r\n for (const byte of bytes) {\r\n binary += String.fromCharCode(byte)\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\r\n}\r\n\r\nfunction base64urlDecode(str: string): Uint8Array<ArrayBuffer> {\r\n const padded = str.replace(/-/g, '+').replace(/_/g, '/')\r\n const binary = atob(padded)\r\n const bytes = new Uint8Array(new ArrayBuffer(binary.length))\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\nasync function importHmacKey(secret: string): Promise<CryptoKey> {\r\n return crypto.subtle.importKey(\r\n 'raw',\r\n new TextEncoder().encode(secret),\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign', 'verify']\r\n )\r\n}\r\n\r\nasync function signCookie(secret: string, ip: string): Promise<string> {\r\n const ts = Date.now()\r\n const nonce = base64urlEncode(crypto.getRandomValues(new Uint8Array(8)))\r\n const payload = `${ip}:${ts}:${nonce}`\r\n const key = await importHmacKey(secret)\r\n const sig = await crypto.subtle.sign(\r\n 'HMAC',\r\n key,\r\n new TextEncoder().encode(payload)\r\n )\r\n const sigB64 = base64urlEncode(new Uint8Array(sig))\r\n return `${base64urlEncode(new TextEncoder().encode(payload))}.${sigB64}`\r\n}\r\n\r\nasync function validateCookie(\r\n secret: string,\r\n cookie: string,\r\n ip: string\r\n): Promise<boolean> {\r\n try {\r\n const [payloadB64, sigB64] = cookie.split('.')\r\n if (!payloadB64 || !sigB64) return false\r\n\r\n const payloadBytes = base64urlDecode(payloadB64)\r\n const sigBytes = base64urlDecode(sigB64)\r\n\r\n const key = await importHmacKey(secret)\r\n const valid = await crypto.subtle.verify(\r\n 'HMAC',\r\n key,\r\n sigBytes,\r\n payloadBytes\r\n )\r\n if (!valid) return false\r\n\r\n const payload = new TextDecoder().decode(payloadBytes)\r\n const [cookieIp, tsStr] = payload.split(':')\r\n\r\n if (cookieIp !== ip) return false\r\n\r\n const ts = parseInt(tsStr, 10)\r\n if (isNaN(ts) || Date.now() - ts > COOKIE_MAX_AGE_SEC * 1000) return false\r\n\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nfunction getClientIp(c: Context<{ Bindings: LeapifyBindings }>): string {\r\n return (\r\n c.req.header('CF-Connecting-IP') ??\r\n c.req.header('X-Real-IP') ??\r\n c.req.header('X-Forwarded-For')?.split(',')[0]?.trim() ??\r\n 'unknown'\r\n )\r\n}\r\n\r\nfunction isExempt(path: string): boolean {\r\n const normalized = path.toLowerCase().replace(/\\/$/, '')\r\n return EXEMPT_PATHS.some((p) => {\r\n const ep = p.toLowerCase().replace(/\\/$/, '')\r\n return normalized === ep || normalized.startsWith(ep + '/')\r\n })\r\n}\r\n\r\nfunction setCookieHeader(c: Context<{ Bindings: LeapifyBindings }>, token: string): void {\r\n const isSecure = c.req.raw.url.startsWith(\"https\") || c.req.header(\"x-forwarded-proto\") === \"https\";\r\n c.header(\r\n \"Set-Cookie\",\r\n `${TURNSTILE_COOKIE_NAME}=${token}; Path=/; Max-Age=${COOKIE_MAX_AGE_SEC}; ${\r\n isSecure ? \"Secure; \" : \"\"\r\n }HttpOnly; SameSite=Lax`,\r\n );\r\n}\r\n\r\n/**\r\n * POST /.well-known/leapify/turnstile/verify\r\n *\r\n * Validates a Turnstile token and issues a signed cookie on success.\r\n */\r\nexport async function handleTurnstileVerify(\r\n c: Context<{ Bindings: LeapifyBindings }>\r\n) {\r\n const body = await c.req.json<{ token?: string }>()\r\n const { token } = body\r\n\r\n if (!token) {\r\n return c.json(\r\n { error: { code: 'VALIDATION_ERROR', message: 'Missing Turnstile token' } },\r\n 422\r\n )\r\n }\r\n\r\n const secret = c.env.TURNSTILE_SECRET_KEY\r\n if (!secret) {\r\n return c.json(\r\n { error: { code: 'CONFIG_ERROR', message: 'Turnstile not configured' } },\r\n 500\r\n )\r\n }\r\n\r\n const ip = getClientIp(c)\r\n const formData = new URLSearchParams()\r\n formData.append('secret', secret)\r\n formData.append('response', token)\r\n if (ip !== 'unknown') {\r\n formData.append('remoteip', ip)\r\n }\r\n\r\n const res = await fetch(VERIFY_URL, {\r\n method: 'POST',\r\n body: formData,\r\n })\r\n const outcome = await res.json() as { success: boolean; 'error-codes'?: string[] }\r\n\r\n if (!outcome.success) {\r\n return c.json(\r\n { error: { code: 'TURNSTILE_FAILED', message: 'Turnstile verification failed', details: outcome['error-codes'] } },\r\n 403\r\n )\r\n }\r\n\r\n const cookieToken = await signCookie(secret, ip)\r\n setCookieHeader(c, cookieToken)\r\n\r\n return c.json({ success: true })\r\n}\r\n\r\n/**\r\n * Turnstile challenge middleware.\r\n *\r\n * Requires a valid Turnstile-signed cookie on all non-exempt requests.\r\n * The client must first solve a Turnstile challenge and POST the token\r\n * to the verify endpoint to obtain the cookie.\r\n *\r\n * Exempt paths: /health, /internal, /api/auth, /api/uploads/images,\r\n * and the verify endpoint itself.\r\n */\r\nexport function createTurnstileMiddleware() {\r\n return createMiddleware<{ Bindings: LeapifyBindings }>(async (c, next) => {\r\n if (isExempt(c.req.path)) return next()\r\n\r\n if (c.req.method === 'OPTIONS') return next()\r\n\r\n // Skip challenge for authenticated requests (Bearer token present)\r\n // The auth middleware will handle session validation instead.\r\n if (c.req.header('Authorization')) return next()\r\n\r\n const secret = c.env.TURNSTILE_SECRET_KEY\r\n if (!secret) return next()\r\n\r\n const cookieHeader = c.req.header('Cookie') ?? ''\r\n const cookieMatch = cookieHeader.match(\r\n new RegExp(`${TURNSTILE_COOKIE_NAME}=([^;]+)`)\r\n )\r\n if (cookieMatch) {\r\n const ip = getClientIp(c)\r\n const valid = await validateCookie(secret, cookieMatch[1], ip)\r\n if (valid) return next()\r\n }\r\n\r\n return c.json(\r\n { error: { code: 'TURNSTILE_REQUIRED', message: 'Turnstile verification required' } },\r\n 401\r\n )\r\n })\r\n}\r\n"]}
@@ -16,6 +16,8 @@ var EXEMPT_PATHS = [
16
16
  "/api/classes",
17
17
  "/api/faqs",
18
18
  "/api/config",
19
+ "/api/themes",
20
+ "/api/organizations",
19
21
  TURNSTILE_VERIFY_PATH
20
22
  ];
21
23
  function base64urlEncode(bytes) {
@@ -163,5 +165,5 @@ exports.TURNSTILE_PATH = TURNSTILE_PATH;
163
165
  exports.TURNSTILE_VERIFY_PATH = TURNSTILE_VERIFY_PATH;
164
166
  exports.createTurnstileMiddleware = createTurnstileMiddleware;
165
167
  exports.handleTurnstileVerify = handleTurnstileVerify;
166
- //# sourceMappingURL=chunk-X4OB4DZ3.cjs.map
167
- //# sourceMappingURL=chunk-X4OB4DZ3.cjs.map
168
+ //# sourceMappingURL=chunk-ZV4TIJXI.cjs.map
169
+ //# sourceMappingURL=chunk-ZV4TIJXI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/middleware/turnstile-challenge.ts"],"names":["createMiddleware"],"mappings":"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","file":"chunk-ZV4TIJXI.cjs","sourcesContent":["import { createMiddleware } from 'hono/factory'\r\nimport type { Context } from 'hono'\r\nimport type { LeapifyBindings } from '../../types'\r\n\r\nexport const TURNSTILE_PATH = '/.well-known/leapify/turnstile'\r\n\r\nexport const TURNSTILE_VERIFY_PATH = `${TURNSTILE_PATH}/verify`\r\n\r\nexport const TURNSTILE_COOKIE_NAME = 'leapify-turnstile'\r\n\r\nconst VERIFY_URL = 'https://challenges.cloudflare.com/turnstile/v0/siteverify'\r\n\r\nconst COOKIE_MAX_AGE_SEC = 86400\r\n\r\nconst EXEMPT_PATHS = [\r\n \"/health\",\r\n \"/internal\",\r\n \"/api/auth\",\r\n \"/api/uploads/images\",\r\n \"/api/classes\",\r\n \"/api/faqs\",\r\n \"/api/config\",\r\n \"/api/themes\",\r\n \"/api/organizations\",\r\n TURNSTILE_VERIFY_PATH,\r\n];\r\n\r\nfunction base64urlEncode(bytes: Uint8Array): string {\r\n let binary = ''\r\n for (const byte of bytes) {\r\n binary += String.fromCharCode(byte)\r\n }\r\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\r\n}\r\n\r\nfunction base64urlDecode(str: string): Uint8Array<ArrayBuffer> {\r\n const padded = str.replace(/-/g, '+').replace(/_/g, '/')\r\n const binary = atob(padded)\r\n const bytes = new Uint8Array(new ArrayBuffer(binary.length))\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\nasync function importHmacKey(secret: string): Promise<CryptoKey> {\r\n return crypto.subtle.importKey(\r\n 'raw',\r\n new TextEncoder().encode(secret),\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign', 'verify']\r\n )\r\n}\r\n\r\nasync function signCookie(secret: string, ip: string): Promise<string> {\r\n const ts = Date.now()\r\n const nonce = base64urlEncode(crypto.getRandomValues(new Uint8Array(8)))\r\n const payload = `${ip}:${ts}:${nonce}`\r\n const key = await importHmacKey(secret)\r\n const sig = await crypto.subtle.sign(\r\n 'HMAC',\r\n key,\r\n new TextEncoder().encode(payload)\r\n )\r\n const sigB64 = base64urlEncode(new Uint8Array(sig))\r\n return `${base64urlEncode(new TextEncoder().encode(payload))}.${sigB64}`\r\n}\r\n\r\nasync function validateCookie(\r\n secret: string,\r\n cookie: string,\r\n ip: string\r\n): Promise<boolean> {\r\n try {\r\n const [payloadB64, sigB64] = cookie.split('.')\r\n if (!payloadB64 || !sigB64) return false\r\n\r\n const payloadBytes = base64urlDecode(payloadB64)\r\n const sigBytes = base64urlDecode(sigB64)\r\n\r\n const key = await importHmacKey(secret)\r\n const valid = await crypto.subtle.verify(\r\n 'HMAC',\r\n key,\r\n sigBytes,\r\n payloadBytes\r\n )\r\n if (!valid) return false\r\n\r\n const payload = new TextDecoder().decode(payloadBytes)\r\n const [cookieIp, tsStr] = payload.split(':')\r\n\r\n if (cookieIp !== ip) return false\r\n\r\n const ts = parseInt(tsStr, 10)\r\n if (isNaN(ts) || Date.now() - ts > COOKIE_MAX_AGE_SEC * 1000) return false\r\n\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nfunction getClientIp(c: Context<{ Bindings: LeapifyBindings }>): string {\r\n return (\r\n c.req.header('CF-Connecting-IP') ??\r\n c.req.header('X-Real-IP') ??\r\n c.req.header('X-Forwarded-For')?.split(',')[0]?.trim() ??\r\n 'unknown'\r\n )\r\n}\r\n\r\nfunction isExempt(path: string): boolean {\r\n const normalized = path.toLowerCase().replace(/\\/$/, '')\r\n return EXEMPT_PATHS.some((p) => {\r\n const ep = p.toLowerCase().replace(/\\/$/, '')\r\n return normalized === ep || normalized.startsWith(ep + '/')\r\n })\r\n}\r\n\r\nfunction setCookieHeader(c: Context<{ Bindings: LeapifyBindings }>, token: string): void {\r\n const isSecure = c.req.raw.url.startsWith(\"https\") || c.req.header(\"x-forwarded-proto\") === \"https\";\r\n c.header(\r\n \"Set-Cookie\",\r\n `${TURNSTILE_COOKIE_NAME}=${token}; Path=/; Max-Age=${COOKIE_MAX_AGE_SEC}; ${\r\n isSecure ? \"Secure; \" : \"\"\r\n }HttpOnly; SameSite=Lax`,\r\n );\r\n}\r\n\r\n/**\r\n * POST /.well-known/leapify/turnstile/verify\r\n *\r\n * Validates a Turnstile token and issues a signed cookie on success.\r\n */\r\nexport async function handleTurnstileVerify(\r\n c: Context<{ Bindings: LeapifyBindings }>\r\n) {\r\n const body = await c.req.json<{ token?: string }>()\r\n const { token } = body\r\n\r\n if (!token) {\r\n return c.json(\r\n { error: { code: 'VALIDATION_ERROR', message: 'Missing Turnstile token' } },\r\n 422\r\n )\r\n }\r\n\r\n const secret = c.env.TURNSTILE_SECRET_KEY\r\n if (!secret) {\r\n return c.json(\r\n { error: { code: 'CONFIG_ERROR', message: 'Turnstile not configured' } },\r\n 500\r\n )\r\n }\r\n\r\n const ip = getClientIp(c)\r\n const formData = new URLSearchParams()\r\n formData.append('secret', secret)\r\n formData.append('response', token)\r\n if (ip !== 'unknown') {\r\n formData.append('remoteip', ip)\r\n }\r\n\r\n const res = await fetch(VERIFY_URL, {\r\n method: 'POST',\r\n body: formData,\r\n })\r\n const outcome = await res.json() as { success: boolean; 'error-codes'?: string[] }\r\n\r\n if (!outcome.success) {\r\n return c.json(\r\n { error: { code: 'TURNSTILE_FAILED', message: 'Turnstile verification failed', details: outcome['error-codes'] } },\r\n 403\r\n )\r\n }\r\n\r\n const cookieToken = await signCookie(secret, ip)\r\n setCookieHeader(c, cookieToken)\r\n\r\n return c.json({ success: true })\r\n}\r\n\r\n/**\r\n * Turnstile challenge middleware.\r\n *\r\n * Requires a valid Turnstile-signed cookie on all non-exempt requests.\r\n * The client must first solve a Turnstile challenge and POST the token\r\n * to the verify endpoint to obtain the cookie.\r\n *\r\n * Exempt paths: /health, /internal, /api/auth, /api/uploads/images,\r\n * and the verify endpoint itself.\r\n */\r\nexport function createTurnstileMiddleware() {\r\n return createMiddleware<{ Bindings: LeapifyBindings }>(async (c, next) => {\r\n if (isExempt(c.req.path)) return next()\r\n\r\n if (c.req.method === 'OPTIONS') return next()\r\n\r\n // Skip challenge for authenticated requests (Bearer token present)\r\n // The auth middleware will handle session validation instead.\r\n if (c.req.header('Authorization')) return next()\r\n\r\n const secret = c.env.TURNSTILE_SECRET_KEY\r\n if (!secret) return next()\r\n\r\n const cookieHeader = c.req.header('Cookie') ?? ''\r\n const cookieMatch = cookieHeader.match(\r\n new RegExp(`${TURNSTILE_COOKIE_NAME}=([^;]+)`)\r\n )\r\n if (cookieMatch) {\r\n const ip = getClientIp(c)\r\n const valid = await validateCookie(secret, cookieMatch[1], ip)\r\n if (valid) return next()\r\n }\r\n\r\n return c.json(\r\n { error: { code: 'TURNSTILE_REQUIRED', message: 'Turnstile verification required' } },\r\n 401\r\n )\r\n })\r\n}\r\n"]}
@@ -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-auth/client").BetterFetchResponse<{
35
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
100
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
135
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<(Omit<{
157
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<Omit<{
218
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
257
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<NonNullable<void | {
273
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
288
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
303
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<Omit<{
320
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
356
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
383
+ }, FetchOptions>> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
400
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
416
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<never, {
434
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<import("better-auth").Prettify<{
443
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
463
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
473
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
483
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
522
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
533
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
556
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
573
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
590
+ }>, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
607
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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-auth/client").BetterFetchResponse<{
624
+ }> | undefined, data_1?: FetchOptions | undefined) => Promise<import("@better-fetch/fetch").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("better-auth/client").Atom<{
649
+ useSession: import("nanostores").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-auth/client").BetterFetchError | null;
671
+ error: import("@better-fetch/fetch").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-auth/client").BetterFetch<{
679
- plugins: (import("better-auth/client").BetterFetchPlugin<Record<string, any>> | {
678
+ $fetch: import("@better-fetch/fetch").BetterFetch<{
679
+ plugins: (import("@better-fetch/fetch").BetterFetchPlugin<Record<string, any>> | {
680
680
  id: string;
681
681
  name: string;
682
682
  hooks: {
683
- onSuccess(context: import("better-auth/client").SuccessContext<any>): void;
683
+ onSuccess(context: import("@better-fetch/fetch").SuccessContext<any>): void;
684
684
  };
685
685
  } | {
686
686
  id: string;
687
687
  name: string;
688
688
  hooks: {
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;
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;
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-auth/client").ResponseContext) => Promise<void> | void) | undefined;
724
+ ?: ((response: import("@better-fetch/fetch").ResponseContext) => Promise<void> | void) | undefined;
725
725
  hookOptions?: {
726
726
  cloneResponse?: boolean;
727
727
  } | undefined;
728
728
  timeout?: number | undefined;
729
- customFetchImpl: import("better-auth/client").FetchEsque;
729
+ customFetchImpl: import("@better-fetch/fetch").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-auth/client").RetryOptions | undefined;
749
+ retry?: import("@better-fetch/fetch").RetryOptions | undefined;
750
750
  retryAttempt?: number | undefined;
751
- output?: (import("better-auth/client").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
752
- errorSchema?: import("better-auth/client").StandardSchemaV1 | undefined;
751
+ output?: (import("@better-fetch/fetch").StandardSchemaV1 | typeof Blob | typeof File) | undefined;
752
+ errorSchema?: import("@better-fetch/fetch").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("better-auth/client").WritableAtom<any>>;
759
+ atoms: Record<string, import("nanostores").WritableAtom<any>>;
760
760
  };
761
761
  $Infer: {
762
762
  Session: {
@@ -147,8 +147,6 @@ var LeapifyApiError = class extends Error {
147
147
  this.code = code;
148
148
  this.name = "LeapifyApiError";
149
149
  }
150
- status;
151
- code;
152
150
  };
153
151
  var LEAPIFY_ERROR_CODES = {
154
152
  UNAUTHORIZED: "UNAUTHORIZED",