@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.
- package/dist/auth/auth.d.ts +2 -2
- package/dist/{chunk-2JEY6TSO.js → chunk-WTA2QGY5.js} +4 -2
- package/dist/chunk-WTA2QGY5.js.map +1 -0
- package/dist/{chunk-X4OB4DZ3.cjs → chunk-ZV4TIJXI.cjs} +4 -2
- package/dist/chunk-ZV4TIJXI.cjs.map +1 -0
- package/dist/client/auth.d.ts +41 -41
- package/dist/client/index.cjs +0 -2
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +0 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +4 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/db/schema/themes.d.ts +74 -0
- package/dist/db/schema/themes.d.ts.map +1 -1
- package/dist/index.cjs +30 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +29 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/middleware/turnstile-challenge.cjs +6 -6
- package/dist/lib/middleware/turnstile-challenge.d.ts.map +1 -1
- package/dist/lib/middleware/turnstile-challenge.js +1 -1
- package/dist/routes/themes.d.ts.map +1 -1
- package/dist/worker.js +30 -12
- package/dist/worker.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-2JEY6TSO.js.map +0 -1
- package/dist/chunk-X4OB4DZ3.cjs.map +0 -1
package/dist/auth/auth.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
161
|
-
//# sourceMappingURL=chunk-
|
|
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-
|
|
167
|
-
//# sourceMappingURL=chunk-
|
|
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"]}
|
package/dist/client/auth.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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("
|
|
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-
|
|
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-
|
|
679
|
-
plugins: (import("better-
|
|
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-
|
|
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-
|
|
690
|
-
onError: ((context: import("better-
|
|
691
|
-
onRequest: (<T extends Record<string, any>>(context: import("better-
|
|
692
|
-
onResponse: ((context: import("better-
|
|
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-
|
|
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-
|
|
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-
|
|
749
|
+
retry?: import("@better-fetch/fetch").RetryOptions | undefined;
|
|
750
750
|
retryAttempt?: number | undefined;
|
|
751
|
-
output?: (import("better-
|
|
752
|
-
errorSchema?: import("better-
|
|
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("
|
|
759
|
+
atoms: Record<string, import("nanostores").WritableAtom<any>>;
|
|
760
760
|
};
|
|
761
761
|
$Infer: {
|
|
762
762
|
Session: {
|