clearauth 0.3.0

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/LICENSE +21 -0
  3. package/README.md +417 -0
  4. package/dist/auth/handler.d.ts +38 -0
  5. package/dist/auth/handler.js +483 -0
  6. package/dist/auth/handler.js.map +1 -0
  7. package/dist/auth/login.d.ts +69 -0
  8. package/dist/auth/login.js +103 -0
  9. package/dist/auth/login.js.map +1 -0
  10. package/dist/auth/register.d.ts +72 -0
  11. package/dist/auth/register.js +122 -0
  12. package/dist/auth/register.js.map +1 -0
  13. package/dist/auth/reset-password.d.ts +106 -0
  14. package/dist/auth/reset-password.js +213 -0
  15. package/dist/auth/reset-password.js.map +1 -0
  16. package/dist/auth/utils.d.ts +58 -0
  17. package/dist/auth/utils.js +121 -0
  18. package/dist/auth/utils.js.map +1 -0
  19. package/dist/auth/verify-email.d.ts +70 -0
  20. package/dist/auth/verify-email.js +137 -0
  21. package/dist/auth/verify-email.js.map +1 -0
  22. package/dist/createMechAuth.d.ts +178 -0
  23. package/dist/createMechAuth.js +215 -0
  24. package/dist/createMechAuth.js.map +1 -0
  25. package/dist/database/schema.d.ts +135 -0
  26. package/dist/database/schema.js +37 -0
  27. package/dist/database/schema.js.map +1 -0
  28. package/dist/edge.d.ts +4 -0
  29. package/dist/edge.js +6 -0
  30. package/dist/edge.js.map +1 -0
  31. package/dist/errors.d.ts +25 -0
  32. package/dist/errors.js +44 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/handler.d.ts +100 -0
  35. package/dist/handler.js +213 -0
  36. package/dist/handler.js.map +1 -0
  37. package/dist/index.d.ts +22 -0
  38. package/dist/index.js +28 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/logger.d.ts +22 -0
  41. package/dist/logger.js +40 -0
  42. package/dist/logger.js.map +1 -0
  43. package/dist/mech-kysely.d.ts +22 -0
  44. package/dist/mech-kysely.js +88 -0
  45. package/dist/mech-kysely.js.map +1 -0
  46. package/dist/mech-sql-client.d.ts +85 -0
  47. package/dist/mech-sql-client.js +155 -0
  48. package/dist/mech-sql-client.js.map +1 -0
  49. package/dist/node.d.ts +4 -0
  50. package/dist/node.js +10 -0
  51. package/dist/node.js.map +1 -0
  52. package/dist/oauth/arctic-providers.d.ts +60 -0
  53. package/dist/oauth/arctic-providers.js +94 -0
  54. package/dist/oauth/arctic-providers.js.map +1 -0
  55. package/dist/oauth/callbacks.d.ts +155 -0
  56. package/dist/oauth/callbacks.js +286 -0
  57. package/dist/oauth/callbacks.js.map +1 -0
  58. package/dist/oauth/github.d.ts +47 -0
  59. package/dist/oauth/github.js +136 -0
  60. package/dist/oauth/github.js.map +1 -0
  61. package/dist/oauth/google.d.ts +49 -0
  62. package/dist/oauth/google.js +104 -0
  63. package/dist/oauth/google.js.map +1 -0
  64. package/dist/oauth/handler.d.ts +31 -0
  65. package/dist/oauth/handler.js +277 -0
  66. package/dist/oauth/handler.js.map +1 -0
  67. package/dist/password-hasher-argon2.d.ts +7 -0
  68. package/dist/password-hasher-argon2.js +16 -0
  69. package/dist/password-hasher-argon2.js.map +1 -0
  70. package/dist/password-hasher.d.ts +12 -0
  71. package/dist/password-hasher.js +115 -0
  72. package/dist/password-hasher.js.map +1 -0
  73. package/dist/react.d.ts +152 -0
  74. package/dist/react.js +296 -0
  75. package/dist/react.js.map +1 -0
  76. package/dist/types.d.ts +190 -0
  77. package/dist/types.js +7 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/utils/cors.d.ts +65 -0
  80. package/dist/utils/cors.js +152 -0
  81. package/dist/utils/cors.js.map +1 -0
  82. package/dist/utils/normalize-auth-path.d.ts +1 -0
  83. package/dist/utils/normalize-auth-path.js +8 -0
  84. package/dist/utils/normalize-auth-path.js.map +1 -0
  85. package/dist/validation.d.ts +23 -0
  86. package/dist/validation.js +70 -0
  87. package/dist/validation.js.map +1 -0
  88. package/package.json +93 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Authentication Utilities
3
+ *
4
+ * Shared utilities for email/password authentication including:
5
+ * - Email validation
6
+ * - Password validation
7
+ * - Secure token generation
8
+ */
9
+ import { base64url } from 'oslo/encoding';
10
+ /**
11
+ * Email validation regex (RFC 5322 simplified)
12
+ *
13
+ * Must have:
14
+ * - Local part before @
15
+ * - @ symbol
16
+ * - Domain name
17
+ * - At least one dot (.)
18
+ * - TLD with at least 1 character after the dot
19
+ *
20
+ * Does NOT allow:
21
+ * - Consecutive dots (..)
22
+ * - Leading/trailing dots
23
+ * - @ at start
24
+ * - Spaces
25
+ */
26
+ const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;
27
+ /**
28
+ * Validate email format
29
+ *
30
+ * @param email - Email address to validate
31
+ * @returns True if valid, false otherwise
32
+ */
33
+ export function isValidEmail(email) {
34
+ if (!email || email.length > 254) {
35
+ return false;
36
+ }
37
+ // Check for spaces (not allowed in email addresses)
38
+ if (email.includes(' ')) {
39
+ return false;
40
+ }
41
+ const trimmedEmail = email.toLowerCase().trim();
42
+ // Check for consecutive dots
43
+ if (trimmedEmail.includes('..')) {
44
+ return false;
45
+ }
46
+ // Check for leading/trailing dots
47
+ const localPart = trimmedEmail.split('@')[0];
48
+ if (localPart?.startsWith('.') || localPart?.endsWith('.')) {
49
+ return false;
50
+ }
51
+ return EMAIL_REGEX.test(trimmedEmail);
52
+ }
53
+ /**
54
+ * Validate password strength
55
+ *
56
+ * @param password - Password to validate
57
+ * @param minLength - Minimum password length (default: 8)
58
+ * @returns Error message if invalid, null if valid
59
+ */
60
+ export function validatePassword(password, minLength = 8) {
61
+ if (!password || password.length === 0) {
62
+ return `Password must be at least ${minLength} characters long`;
63
+ }
64
+ if (password.length < minLength) {
65
+ return `Password must be at least ${minLength} characters long`;
66
+ }
67
+ // Optional: Add more password strength requirements
68
+ // - At least one uppercase letter
69
+ // - At least one lowercase letter
70
+ // - At least one number
71
+ // - At least one special character
72
+ return null;
73
+ }
74
+ /**
75
+ * Generate a secure random token
76
+ *
77
+ * Uses cryptographically secure random values from Web Crypto API.
78
+ *
79
+ * @param entropySize - Number of bytes of entropy (default: 32)
80
+ * @returns Base64url-encoded token
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const token = generateSecureToken(32) // 256 bits of entropy
85
+ * ```
86
+ */
87
+ export function generateSecureToken(entropySize = 32) {
88
+ const bytes = new Uint8Array(entropySize);
89
+ crypto.getRandomValues(bytes);
90
+ // Use base64url encoder without padding
91
+ return base64url.encode(bytes).replace(/=/g, '');
92
+ }
93
+ /**
94
+ * Normalize email address
95
+ *
96
+ * Converts email to lowercase for consistent storage and comparison.
97
+ *
98
+ * @param email - Email address to normalize
99
+ * @returns Normalized email address
100
+ */
101
+ export function normalizeEmail(email) {
102
+ return email.toLowerCase().trim();
103
+ }
104
+ /**
105
+ * Authentication error types
106
+ */
107
+ export class AuthError extends Error {
108
+ constructor(message, code, statusCode = 400) {
109
+ super(message);
110
+ this.code = code;
111
+ this.statusCode = statusCode;
112
+ this.name = 'AuthError';
113
+ }
114
+ }
115
+ /**
116
+ * Create a standardized auth error
117
+ */
118
+ export function createAuthError(message, code, statusCode = 400) {
119
+ return new AuthError(message, code, statusCode);
120
+ }
121
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,GAAG,sIAAsI,CAAA;AAE1J;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACjC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,oDAAoD;IACpD,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAE/C,6BAA6B;IAC7B,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,kCAAkC;IAClC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,IAAI,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;AACvC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,YAAoB,CAAC;IACtE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,6BAA6B,SAAS,kBAAkB,CAAA;IACjE,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAChC,OAAO,6BAA6B,SAAS,kBAAkB,CAAA;IACjE,CAAC;IAED,oDAAoD;IACpD,kCAAkC;IAClC,kCAAkC;IAClC,wBAAwB;IACxB,mCAAmC;IAEnC,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,cAAsB,EAAE;IAC1D,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAA;IACzC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;IAC7B,wCAAwC;IACxC,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YACE,OAAe,EACR,IAAY,EACZ,aAAqB,GAAG;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAA;QAHP,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAc;QAG/B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;IACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,IAAY,EACZ,aAAqB,GAAG;IAExB,OAAO,IAAI,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;AACjD,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Email Verification
3
+ *
4
+ * Handles email verification flow:
5
+ * - Token validation and expiration checking
6
+ * - Marking user's email as verified
7
+ * - Token cleanup after use
8
+ * - Resending verification emails
9
+ */
10
+ import type { Kysely } from 'kysely';
11
+ import type { Database } from '../database/schema.js';
12
+ /**
13
+ * Verify user's email address using a verification token
14
+ *
15
+ * Validates the token, checks expiration, and marks the user's email as verified.
16
+ * The token is deleted after successful verification.
17
+ *
18
+ * @param db - Kysely database instance
19
+ * @param token - Email verification token
20
+ * @returns Verification result with user ID if successful
21
+ * @throws {AuthError} If token is invalid or expired
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const result = await verifyEmail(db, 'abc123...')
26
+ * if (result.success) {
27
+ * console.log('Email verified for user:', result.userId)
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function verifyEmail(db: Kysely<Database>, token: string): Promise<{
32
+ success: boolean;
33
+ userId?: string;
34
+ }>;
35
+ /**
36
+ * Resend verification email
37
+ *
38
+ * Generates a new verification token for the user with the given email.
39
+ * Deletes any existing tokens for that user before creating a new one.
40
+ *
41
+ * @param db - Kysely database instance
42
+ * @param email - User's email address
43
+ * @returns New verification token
44
+ * @throws {AuthError} If user not found or email already verified
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const { token } = await resendVerificationEmail(db, 'user@example.com')
49
+ * // Send token to user via email
50
+ * ```
51
+ */
52
+ export declare function resendVerificationEmail(db: Kysely<Database>, email: string): Promise<{
53
+ token: string;
54
+ }>;
55
+ /**
56
+ * Clean up expired verification tokens
57
+ *
58
+ * Removes all expired email verification tokens from the database.
59
+ * This should be run periodically as a background job.
60
+ *
61
+ * @param db - Kysely database instance
62
+ * @returns Number of tokens deleted
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const deleted = await cleanupExpiredVerificationTokens(db)
67
+ * console.log(`Cleaned up ${deleted} expired verification tokens`)
68
+ * ```
69
+ */
70
+ export declare function cleanupExpiredVerificationTokens(db: Kysely<Database>): Promise<number>;
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Email Verification
3
+ *
4
+ * Handles email verification flow:
5
+ * - Token validation and expiration checking
6
+ * - Marking user's email as verified
7
+ * - Token cleanup after use
8
+ * - Resending verification emails
9
+ */
10
+ import { generateSecureToken, createAuthError, normalizeEmail } from './utils.js';
11
+ import { isValidEmailVerificationToken } from '../database/schema.js';
12
+ /**
13
+ * Email verification token expiration (24 hours)
14
+ */
15
+ const VERIFICATION_TOKEN_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
16
+ /**
17
+ * Verify user's email address using a verification token
18
+ *
19
+ * Validates the token, checks expiration, and marks the user's email as verified.
20
+ * The token is deleted after successful verification.
21
+ *
22
+ * @param db - Kysely database instance
23
+ * @param token - Email verification token
24
+ * @returns Verification result with user ID if successful
25
+ * @throws {AuthError} If token is invalid or expired
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const result = await verifyEmail(db, 'abc123...')
30
+ * if (result.success) {
31
+ * console.log('Email verified for user:', result.userId)
32
+ * }
33
+ * ```
34
+ */
35
+ export async function verifyEmail(db, token) {
36
+ if (!token || token.trim() === '') {
37
+ throw createAuthError('Verification token is required', 'INVALID_TOKEN', 400);
38
+ }
39
+ // Look up token in database
40
+ const tokenRecord = await db
41
+ .selectFrom('email_verification_tokens')
42
+ .selectAll()
43
+ .where('token', '=', token)
44
+ .executeTakeFirst();
45
+ if (!tokenRecord) {
46
+ throw createAuthError('Invalid verification token', 'INVALID_TOKEN', 400);
47
+ }
48
+ // Check if token is expired
49
+ if (!isValidEmailVerificationToken(tokenRecord)) {
50
+ // Delete expired token
51
+ await db.deleteFrom('email_verification_tokens').where('token', '=', token).execute();
52
+ throw createAuthError('Verification token has expired', 'TOKEN_EXPIRED', 400);
53
+ }
54
+ // Mark user's email as verified
55
+ await db
56
+ .updateTable('users')
57
+ .set({ email_verified: true })
58
+ .where('id', '=', tokenRecord.user_id)
59
+ .execute();
60
+ // Delete used verification token
61
+ await db.deleteFrom('email_verification_tokens').where('token', '=', token).execute();
62
+ return {
63
+ success: true,
64
+ userId: tokenRecord.user_id,
65
+ };
66
+ }
67
+ /**
68
+ * Resend verification email
69
+ *
70
+ * Generates a new verification token for the user with the given email.
71
+ * Deletes any existing tokens for that user before creating a new one.
72
+ *
73
+ * @param db - Kysely database instance
74
+ * @param email - User's email address
75
+ * @returns New verification token
76
+ * @throws {AuthError} If user not found or email already verified
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const { token } = await resendVerificationEmail(db, 'user@example.com')
81
+ * // Send token to user via email
82
+ * ```
83
+ */
84
+ export async function resendVerificationEmail(db, email) {
85
+ const normalizedEmail = normalizeEmail(email);
86
+ // Look up user by email
87
+ const user = await db
88
+ .selectFrom('users')
89
+ .select(['id', 'email', 'email_verified'])
90
+ .where('email', '=', normalizedEmail)
91
+ .executeTakeFirst();
92
+ if (!user) {
93
+ // Don't reveal whether email exists (security)
94
+ throw createAuthError('If this email exists, a verification link will be sent', 'EMAIL_SENT', 200);
95
+ }
96
+ if (user.email_verified) {
97
+ throw createAuthError('Email is already verified', 'ALREADY_VERIFIED', 400);
98
+ }
99
+ // Delete any existing verification tokens for this user
100
+ await db.deleteFrom('email_verification_tokens').where('user_id', '=', user.id).execute();
101
+ // Generate new verification token
102
+ const verificationToken = generateSecureToken(32); // 256 bits of entropy
103
+ const expiresAt = new Date(Date.now() + VERIFICATION_TOKEN_EXPIRY);
104
+ const newToken = {
105
+ token: verificationToken,
106
+ user_id: user.id,
107
+ email: normalizedEmail,
108
+ expires_at: expiresAt,
109
+ };
110
+ await db.insertInto('email_verification_tokens').values(newToken).execute();
111
+ return {
112
+ token: verificationToken,
113
+ };
114
+ }
115
+ /**
116
+ * Clean up expired verification tokens
117
+ *
118
+ * Removes all expired email verification tokens from the database.
119
+ * This should be run periodically as a background job.
120
+ *
121
+ * @param db - Kysely database instance
122
+ * @returns Number of tokens deleted
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * const deleted = await cleanupExpiredVerificationTokens(db)
127
+ * console.log(`Cleaned up ${deleted} expired verification tokens`)
128
+ * ```
129
+ */
130
+ export async function cleanupExpiredVerificationTokens(db) {
131
+ const result = await db
132
+ .deleteFrom('email_verification_tokens')
133
+ .where('expires_at', '<=', new Date())
134
+ .executeTakeFirst();
135
+ return Number(result.numDeletedRows ?? 0);
136
+ }
137
+ //# sourceMappingURL=verify-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-email.js","sourceRoot":"","sources":["../../src/auth/verify-email.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Factory function to create a complete ClearAuth configuration
3
+ *
4
+ * This module provides a convenient way to create a fully configured ClearAuthConfig
5
+ * with sensible defaults for session management, cookies, and security settings.
6
+ *
7
+ * @module createClearAuth
8
+ */
9
+ import { type MechKyselyConfig } from "./mech-kysely.js";
10
+ import type { ClearAuthConfig } from "./types.js";
11
+ /**
12
+ * Default session configuration
13
+ * - 7 day expiration
14
+ * - Secure cookies in production
15
+ * - SameSite: lax
16
+ */
17
+ export declare const defaultSessionConfig: {
18
+ readonly expiresIn: number;
19
+ readonly cookie: {
20
+ readonly name: "session";
21
+ readonly httpOnly: true;
22
+ readonly sameSite: "lax";
23
+ readonly path: "/";
24
+ };
25
+ };
26
+ /**
27
+ * Short-lived session configuration (for high-security apps)
28
+ * - 1 hour expiration
29
+ * - Strict cookies
30
+ */
31
+ export declare const shortSessionConfig: {
32
+ readonly expiresIn: number;
33
+ readonly cookie: {
34
+ readonly name: "session";
35
+ readonly httpOnly: true;
36
+ readonly sameSite: "strict";
37
+ readonly path: "/";
38
+ };
39
+ };
40
+ /**
41
+ * Long-lived session configuration (for consumer apps)
42
+ * - 30 day expiration
43
+ * - Lax cookies for better UX
44
+ */
45
+ export declare const longSessionConfig: {
46
+ readonly expiresIn: number;
47
+ readonly cookie: {
48
+ readonly name: "session";
49
+ readonly httpOnly: true;
50
+ readonly sameSite: "lax";
51
+ readonly path: "/";
52
+ };
53
+ };
54
+ /**
55
+ * Simplified database configuration
56
+ * Only appId and apiKey are required - everything else has smart defaults
57
+ */
58
+ export type SimpleDatabaseConfig = {
59
+ /** Mech App ID (required) */
60
+ appId: string;
61
+ /** Mech API Key (required) */
62
+ apiKey: string;
63
+ /** Base URL for Mech Storage. Defaults to "https://storage.mechdna.net" */
64
+ baseUrl?: string;
65
+ /** App Schema ID. Defaults to appId */
66
+ appSchemaId?: string;
67
+ /** Request timeout in ms. Defaults to 30000 */
68
+ timeout?: number;
69
+ /** Max retry attempts. Defaults to 2 */
70
+ maxRetries?: number;
71
+ };
72
+ export type CreateClearAuthOptions = {
73
+ /** Secret key for session signing (required) */
74
+ secret: string;
75
+ /**
76
+ * Database configuration. Can be:
77
+ * - Simplified: { appId, apiKey } (recommended)
78
+ * - Full config: { config: MechKyselyConfig }
79
+ */
80
+ database: SimpleDatabaseConfig | {
81
+ config: MechKyselyConfig;
82
+ };
83
+ /** Base URL for your application (required for OAuth redirects) */
84
+ baseUrl: string;
85
+ /** Set to true if running in production */
86
+ isProduction?: boolean;
87
+ /** Session configuration (optional, uses defaults if not provided) */
88
+ session?: ClearAuthConfig['session'];
89
+ /** OAuth provider configuration (optional) */
90
+ oauth?: ClearAuthConfig['oauth'];
91
+ /** Password validation configuration (optional) */
92
+ password?: ClearAuthConfig['password'];
93
+ /** Password hashing implementation (optional) */
94
+ passwordHasher?: ClearAuthConfig['passwordHasher'];
95
+ };
96
+ /**
97
+ * Create a complete ClearAuth configuration
98
+ *
99
+ * All configuration must be provided explicitly - no environment variables are read.
100
+ *
101
+ * Configuration formats:
102
+ *
103
+ * 1. **Simplified config (recommended)**:
104
+ * ```ts
105
+ * const config = createClearAuth({
106
+ * secret: "your-secret-key",
107
+ * baseUrl: "https://yourdomain.com",
108
+ * database: { appId: "...", apiKey: "..." },
109
+ * isProduction: true,
110
+ * oauth: {
111
+ * github: {
112
+ * clientId: env.GITHUB_CLIENT_ID,
113
+ * clientSecret: env.GITHUB_CLIENT_SECRET,
114
+ * redirectUri: 'https://yourdomain.com/auth/callback/github',
115
+ * },
116
+ * },
117
+ * })
118
+ * ```
119
+ *
120
+ * 2. **With session presets**:
121
+ * ```ts
122
+ * const config = createClearAuth({
123
+ * secret: "your-secret-key",
124
+ * baseUrl: "https://yourdomain.com",
125
+ * database: { appId: "...", apiKey: "..." },
126
+ * session: longSessionConfig, // Use 30-day sessions
127
+ * })
128
+ * ```
129
+ *
130
+ * @param options - Configuration options
131
+ * @returns A configured ClearAuthConfig object
132
+ * @throws ClearAuthConfigError if required config is missing or invalid
133
+ *
134
+ * @example Cloudflare Workers setup
135
+ * ```ts
136
+ * import { createClearAuth, defaultSessionConfig } from 'clearauth'
137
+ *
138
+ * const config = createClearAuth({
139
+ * secret: env.AUTH_SECRET,
140
+ * baseUrl: 'https://yourdomain.com',
141
+ * database: {
142
+ * appId: env.MECH_APP_ID,
143
+ * apiKey: env.MECH_API_KEY,
144
+ * },
145
+ * isProduction: true,
146
+ * session: defaultSessionConfig,
147
+ * oauth: {
148
+ * github: {
149
+ * clientId: env.GITHUB_CLIENT_ID,
150
+ * clientSecret: env.GITHUB_CLIENT_SECRET,
151
+ * redirectUri: 'https://yourdomain.com/auth/callback/github',
152
+ * },
153
+ * },
154
+ * })
155
+ * ```
156
+ *
157
+ * @example Next.js setup
158
+ * ```ts
159
+ * import { createClearAuth } from 'clearauth'
160
+ *
161
+ * export const authConfig = createClearAuth({
162
+ * secret: process.env.AUTH_SECRET!,
163
+ * baseUrl: process.env.NEXT_PUBLIC_BASE_URL!,
164
+ * database: {
165
+ * appId: process.env.MECH_APP_ID!,
166
+ * apiKey: process.env.MECH_API_KEY!,
167
+ * },
168
+ * oauth: {
169
+ * github: {
170
+ * clientId: process.env.GITHUB_CLIENT_ID!,
171
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
172
+ * redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/auth/callback/github`,
173
+ * },
174
+ * },
175
+ * })
176
+ * ```
177
+ */
178
+ export declare function createClearAuth(options: CreateClearAuthOptions): ClearAuthConfig;