better-auth-cloudflare
Version:
Seamlessly integrate better-auth with Cloudflare Workers, D1, Hyperdrive, KV, R2, and geolocation services.
400 lines (397 loc) • 14.4 kB
TypeScript
import * as better_auth from 'better-auth';
import { AuthContext } from 'better-auth';
import { FieldAttribute } from 'better-auth/db';
import { z } from 'zod';
import { R2Config, FileMetadata } from './types.js';
import '@cloudflare/workers-types';
import 'better-auth/adapters/drizzle';
import 'drizzle-orm/d1';
import 'drizzle-orm/mysql2';
import 'drizzle-orm/postgres-js';
declare const R2_ERROR_CODES: {
readonly FILE_TOO_LARGE: "File is too large. Please choose a smaller file";
readonly INVALID_FILE_TYPE: "File type not supported. Please choose a different file";
readonly NO_FILE_PROVIDED: "Please select a file to upload";
readonly INVALID_REQUEST: "Invalid request. Please try again";
readonly R2_STORAGE_NOT_CONFIGURED: "File storage is temporarily unavailable. Please try again later";
readonly UPLOAD_FAILED: "Upload failed. Please check your connection and try again";
readonly FILE_ID_REQUIRED: "File not found";
readonly LIST_FILES_FAILED: "Unable to load your files. Please refresh the page";
readonly INVALID_METADATA: "Invalid file information. Please try uploading again";
readonly UPLOAD_ROLLBACK_FAILED: "Upload failed. Please try again";
readonly INVALID_FILE_RECORD: "File information is corrupted. Please contact support";
readonly DB_OPERATION_FAILED: "Service temporarily unavailable. Please try again later";
};
/**
* Result type for validation operations
*/
type ValidationResult<T> = {
success: true;
data: T;
} | {
success: false;
error: string;
code?: string;
};
/**
* Helper to create success result
*/
declare const success: <T>(data: T) => ValidationResult<T>;
/**
* Helper to create error result
*/
declare const error: (message: string, code?: string) => ValidationResult<never>;
declare const createFileMetadataSchema: (additionalFields?: Record<string, FieldAttribute>) => z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>> | z.ZodOptional<z.ZodObject<{
[x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
}, z.core.$strip>>;
declare const fileIdSchema: z.ZodObject<{
fileId: z.ZodString;
}, z.core.$strip>;
declare const listFilesSchema: z.ZodOptional<z.ZodObject<{
limit: z.ZodOptional<z.ZodNumber>;
cursor: z.ZodOptional<z.ZodString>;
}, z.core.$strip>>;
/**
* Creates upload schema dynamically based on additionalFields configuration
*/
declare const createUploadFileSchema: (additionalFields?: Record<string, FieldAttribute>) => z.ZodObject<{
[x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
}, z.core.$strip>;
/**
* Validates file constraints using Result pattern
*/
declare const createFileValidator: (config: R2Config) => {
validateFile: (file: File, ctx?: AuthContext) => ValidationResult<true>;
validateMetadata: (metadata: Record<string, any>, ctx?: AuthContext) => ValidationResult<Record<string, any> | undefined>;
};
/**
* Creates R2 storage utilities with Better Auth context for error handling and logging
*/
declare const createR2Storage: (config: R2Config, generateId: (options: {
model: string;
size?: number;
}) => string | false) => {
/**
* Uploads a file to R2 and returns metadata
*/
uploadFile(file: File | Blob, originalName: string, userId: string, ctx: AuthContext, customMetadata?: Record<string, any>, modelName?: string): Promise<FileMetadata>;
/**
* Downloads a file from R2
*/
downloadFile(fileMetadata: FileMetadata, ctx: AuthContext): Promise<ReadableStream | null>;
/**
* Deletes a file from R2
*/
deleteFile(fileMetadata: FileMetadata, ctx: AuthContext): Promise<void>;
/**
* Gets file metadata from R2
*/
getFileInfo(r2Key: string): Promise<any>;
/**
* Lists files for a user
*/
listUserFiles(userId: string, ctx: AuthContext): Promise<{
objects: any[];
}>;
};
/**
* Creates R2 endpoints for Better Auth plugin
*/
declare const createR2Endpoints: (getR2Storage: () => ReturnType<typeof createR2Storage> | null, r2Config?: R2Config) => {
upload: {
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0?: ({
body?: undefined;
} & {
method?: "POST" | undefined;
} & {
query?: Record<string, any> | undefined;
} & {
params?: Record<string, any>;
} & {
request?: Request;
} & {
headers?: HeadersInit;
} & {
asResponse?: boolean;
returnHeaders?: boolean;
use?: better_auth.Middleware[];
path?: string;
} & {
asResponse?: AsResponse | undefined;
returnHeaders?: ReturnHeaders | undefined;
}) | undefined): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
headers: Headers;
response: {
success: boolean;
data: FileMetadata;
};
} : {
success: boolean;
data: FileMetadata;
}>;
options: {
method: "POST";
metadata: {
allowedMediaTypes: string[] | undefined;
};
} & {
use: any[];
};
path: "/files/upload-raw";
};
download: {
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
body: {
fileId: string;
};
} & {
method?: "POST" | undefined;
} & {
query?: Record<string, any> | undefined;
} & {
params?: Record<string, any>;
} & {
request?: Request;
} & {
headers?: HeadersInit;
} & {
asResponse?: boolean;
returnHeaders?: boolean;
use?: better_auth.Middleware[];
path?: string;
} & {
asResponse?: AsResponse | undefined;
returnHeaders?: ReturnHeaders | undefined;
}): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
headers: Headers;
response: Response;
} : Response>;
options: {
method: "POST";
use: ((inputContext: better_auth.MiddlewareInputContext<better_auth.MiddlewareOptions>) => Promise<{
session: {
session: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
expiresAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
};
user: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
email: string;
emailVerified: boolean;
name: string;
image?: string | null | undefined;
};
};
}>)[];
body: z.ZodObject<{
fileId: z.ZodString;
}, z.core.$strip>;
} & {
use: any[];
};
path: "/files/download";
};
delete: {
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
body: {
fileId: string;
};
} & {
method?: "POST" | undefined;
} & {
query?: Record<string, any> | undefined;
} & {
params?: Record<string, any>;
} & {
request?: Request;
} & {
headers?: HeadersInit;
} & {
asResponse?: boolean;
returnHeaders?: boolean;
use?: better_auth.Middleware[];
path?: string;
} & {
asResponse?: AsResponse | undefined;
returnHeaders?: ReturnHeaders | undefined;
}): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
headers: Headers;
response: {
message: string;
fileId: string;
};
} : {
message: string;
fileId: string;
}>;
options: {
method: "POST";
use: ((inputContext: better_auth.MiddlewareInputContext<better_auth.MiddlewareOptions>) => Promise<{
session: {
session: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
expiresAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
};
user: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
email: string;
emailVerified: boolean;
name: string;
image?: string | null | undefined;
};
};
}>)[];
body: z.ZodObject<{
fileId: z.ZodString;
}, z.core.$strip>;
} & {
use: any[];
};
path: "/files/delete";
};
list: {
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0?: ({
body?: undefined;
} & {
method?: "GET" | undefined;
} & {
query?: Record<string, any> | undefined;
} & {
params?: Record<string, any>;
} & {
request?: Request;
} & {
headers?: HeadersInit;
} & {
asResponse?: boolean;
returnHeaders?: boolean;
use?: better_auth.Middleware[];
path?: string;
} & {
asResponse?: AsResponse | undefined;
returnHeaders?: ReturnHeaders | undefined;
}) | undefined): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
headers: Headers;
response: {
files: FileMetadata[];
nextCursor: string | null;
hasMore: boolean;
};
} : {
files: FileMetadata[];
nextCursor: string | null;
hasMore: boolean;
}>;
options: {
method: "GET";
use: ((inputContext: better_auth.MiddlewareInputContext<better_auth.MiddlewareOptions>) => Promise<{
session: {
session: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
expiresAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
};
user: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
email: string;
emailVerified: boolean;
name: string;
image?: string | null | undefined;
};
};
}>)[];
} & {
use: any[];
};
path: "/files/list";
};
get: {
<AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0: {
body: {
fileId: string;
};
} & {
method?: "POST" | undefined;
} & {
query?: Record<string, any> | undefined;
} & {
params?: Record<string, any>;
} & {
request?: Request;
} & {
headers?: HeadersInit;
} & {
asResponse?: boolean;
returnHeaders?: boolean;
use?: better_auth.Middleware[];
path?: string;
} & {
asResponse?: AsResponse | undefined;
returnHeaders?: ReturnHeaders | undefined;
}): Promise<[AsResponse] extends [true] ? Response : [ReturnHeaders] extends [true] ? {
headers: Headers;
response: {
data: {};
};
} : {
data: {};
}>;
options: {
method: "POST";
use: ((inputContext: better_auth.MiddlewareInputContext<better_auth.MiddlewareOptions>) => Promise<{
session: {
session: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
expiresAt: Date;
token: string;
ipAddress?: string | null | undefined;
userAgent?: string | null | undefined;
};
user: Record<string, any> & {
id: string;
createdAt: Date;
updatedAt: Date;
email: string;
emailVerified: boolean;
name: string;
image?: string | null | undefined;
};
};
}>)[];
body: z.ZodObject<{
fileId: z.ZodString;
}, z.core.$strip>;
} & {
use: any[];
};
path: "/files/get";
};
};
export { R2_ERROR_CODES, createFileMetadataSchema, createFileValidator, createR2Endpoints, createR2Storage, createUploadFileSchema, error, fileIdSchema, listFilesSchema, success };
export type { ValidationResult };