@ezcoder.dev/sdk 1.4.0 → 1.5.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.
- package/dist/analytics/index.js +4 -4
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +94 -4
- package/dist/auth/index.js.map +1 -1
- package/dist/{chunk-4WGGFJPE.js → chunk-FFMYVTI2.js} +2 -2
- package/dist/{chunk-KKTY5NCR.js → chunk-FPSSXTQG.js} +2 -2
- package/dist/{chunk-NTA3RMYR.js → chunk-HX7IFB7C.js} +15 -4
- package/dist/chunk-HX7IFB7C.js.map +1 -0
- package/dist/{chunk-X4JP7DCK.js → chunk-KWR4PA5I.js} +13 -2
- package/dist/{chunk-X4JP7DCK.js.map → chunk-KWR4PA5I.js.map} +1 -1
- package/dist/{chunk-DU6N3HVQ.js → chunk-OIAKVQGD.js} +2 -2
- package/dist/{chunk-5QYGP7G7.js → chunk-RU2GHN7O.js} +4 -4
- package/dist/cms/index.js +2 -2
- package/dist/{config-D5ajnLCe.d.ts → config-Cb4MMhGa.d.ts} +1 -0
- package/dist/cron/index.js +2 -2
- package/dist/database/index.js +4 -4
- package/dist/email/index.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/notifications/index.js +5 -5
- package/dist/payments/index.js +4 -4
- package/dist/roles/index.js +4 -4
- package/dist/storage/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-NTA3RMYR.js.map +0 -1
- /package/dist/{chunk-4WGGFJPE.js.map → chunk-FFMYVTI2.js.map} +0 -0
- /package/dist/{chunk-KKTY5NCR.js.map → chunk-FPSSXTQG.js.map} +0 -0
- /package/dist/{chunk-DU6N3HVQ.js.map → chunk-OIAKVQGD.js.map} +0 -0
- /package/dist/{chunk-5QYGP7G7.js.map → chunk-RU2GHN7O.js.map} +0 -0
package/dist/analytics/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-HX7IFB7C.js";
|
|
4
4
|
import {
|
|
5
5
|
ezcoder,
|
|
6
6
|
ezcoderAuthIntegration
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-OIAKVQGD.js";
|
|
8
8
|
import {
|
|
9
9
|
isSupabaseConfigured,
|
|
10
10
|
supabase
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-FPSSXTQG.js";
|
|
12
12
|
import {
|
|
13
13
|
env,
|
|
14
14
|
features
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-KWR4PA5I.js";
|
|
16
16
|
|
|
17
17
|
// src/analytics/useAnalytics.ts
|
|
18
18
|
import { useEffect, useRef, useCallback, useContext } from "react";
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as react from 'react';
|
|
|
3
3
|
import { User, Session } from '@supabase/supabase-js';
|
|
4
4
|
import { U as UserProfile, e as SubscriptionTier } from '../types-1uP3V_pe.js';
|
|
5
5
|
import { createAuthClient } from 'better-auth/react';
|
|
6
|
-
export { a as isNeonAuthConfigured } from '../config-
|
|
6
|
+
export { a as isNeonAuthConfigured } from '../config-Cb4MMhGa.js';
|
|
7
7
|
|
|
8
8
|
interface AuthResult<T = unknown> {
|
|
9
9
|
data: T | null;
|
package/dist/auth/index.js
CHANGED
|
@@ -3,14 +3,15 @@ import {
|
|
|
3
3
|
AuthProvider,
|
|
4
4
|
getNeonAuthClient,
|
|
5
5
|
useAuth
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-HX7IFB7C.js";
|
|
7
|
+
import "../chunk-OIAKVQGD.js";
|
|
8
8
|
import {
|
|
9
9
|
supabase
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-FPSSXTQG.js";
|
|
11
11
|
import {
|
|
12
|
+
env,
|
|
12
13
|
isNeonAuthConfigured
|
|
13
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-KWR4PA5I.js";
|
|
14
15
|
|
|
15
16
|
// src/auth/ProtectedRoute.tsx
|
|
16
17
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -428,11 +429,100 @@ function ForgotPasswordForm({ onBack, className = "" }) {
|
|
|
428
429
|
// src/auth/AuthCallback.tsx
|
|
429
430
|
import { useEffect, useState as useState4 } from "react";
|
|
430
431
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
432
|
+
function generateRandomPassword() {
|
|
433
|
+
const bytes = new Uint8Array(32);
|
|
434
|
+
crypto.getRandomValues(bytes);
|
|
435
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
436
|
+
}
|
|
431
437
|
function AuthCallback({ redirectTo = "/", loadingComponent }) {
|
|
432
438
|
const [error, setError] = useState4(null);
|
|
433
439
|
useEffect(() => {
|
|
434
440
|
const handleCallback = async () => {
|
|
435
441
|
try {
|
|
442
|
+
if (isNeonAuthConfigured && typeof window !== "undefined") {
|
|
443
|
+
const hash = window.location.hash;
|
|
444
|
+
const hashParams = new URLSearchParams(hash.startsWith("#") ? hash.slice(1) : hash);
|
|
445
|
+
const proxyCode = hashParams.get("code");
|
|
446
|
+
const proxyError = hashParams.get("error");
|
|
447
|
+
if (proxyError) {
|
|
448
|
+
window.history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
449
|
+
setError(
|
|
450
|
+
proxyError === "email_exists" ? "An account with this email already exists. Please sign in with your original method." : "Sign-in could not be completed. Please try again."
|
|
451
|
+
);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (proxyCode) {
|
|
455
|
+
window.history.replaceState(
|
|
456
|
+
null,
|
|
457
|
+
"",
|
|
458
|
+
window.location.pathname + window.location.search
|
|
459
|
+
);
|
|
460
|
+
const authClient = getNeonAuthClient();
|
|
461
|
+
if (!authClient || !env.EZCODER_API_URL) {
|
|
462
|
+
setError("Auth client not available for proxy exchange");
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const exchangeRes = await fetch(
|
|
466
|
+
`${env.EZCODER_API_URL.replace(/\/$/, "")}/api/app-auth/exchange`,
|
|
467
|
+
{
|
|
468
|
+
method: "POST",
|
|
469
|
+
headers: { "content-type": "application/json" },
|
|
470
|
+
mode: "cors",
|
|
471
|
+
body: JSON.stringify({ code: proxyCode })
|
|
472
|
+
}
|
|
473
|
+
);
|
|
474
|
+
if (!exchangeRes.ok) {
|
|
475
|
+
const msg = await exchangeRes.text().catch(() => exchangeRes.statusText);
|
|
476
|
+
setError(`Auth exchange failed: ${msg}`);
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const { email, password, finalizeToken } = await exchangeRes.json();
|
|
480
|
+
const signInResult = await authClient.signIn.email({ email, password });
|
|
481
|
+
const signInError = signInResult?.error;
|
|
482
|
+
if (signInError) {
|
|
483
|
+
const errObj = signInError instanceof Error ? signInError : new Error(
|
|
484
|
+
typeof signInError?.message === "string" ? signInError.message : "Sign in failed after proxy exchange"
|
|
485
|
+
);
|
|
486
|
+
setError(errObj.message);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
const changePasswordFn = authClient.changePassword;
|
|
491
|
+
if (changePasswordFn) {
|
|
492
|
+
await changePasswordFn({
|
|
493
|
+
currentPassword: password,
|
|
494
|
+
newPassword: generateRandomPassword(),
|
|
495
|
+
revokeOtherSessions: true
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
if (finalizeToken && env.EZCODER_API_URL) {
|
|
501
|
+
try {
|
|
502
|
+
await fetch(
|
|
503
|
+
`${env.EZCODER_API_URL.replace(/\/$/, "")}/api/app-auth/finalize`,
|
|
504
|
+
{
|
|
505
|
+
method: "POST",
|
|
506
|
+
headers: { "content-type": "application/json" },
|
|
507
|
+
mode: "cors",
|
|
508
|
+
body: JSON.stringify({ finalizeToken })
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
} catch {
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (window.opener && window.opener !== window) {
|
|
515
|
+
try {
|
|
516
|
+
window.opener.postMessage({ type: "ezc-auth-complete" }, "*");
|
|
517
|
+
} catch {
|
|
518
|
+
}
|
|
519
|
+
window.close();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
window.location.href = redirectTo;
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
436
526
|
if (isNeonAuthConfigured) {
|
|
437
527
|
if (typeof window !== "undefined" && window.opener && window.opener !== window) {
|
|
438
528
|
try {
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/ProtectedRoute.tsx","../../src/auth/LoginForm.tsx","../../src/auth/SignupForm.tsx","../../src/auth/ForgotPasswordForm.tsx","../../src/auth/AuthCallback.tsx"],"sourcesContent":["import { useAuth } from './AuthProvider';\r\nimport type { SubscriptionTier } from '../core/types';\r\n\r\ninterface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n requiredRoles?: string[];\r\n requiredTier?: SubscriptionTier;\r\n fallback?: React.ReactNode;\r\n unauthorizedFallback?: React.ReactNode;\r\n allowUnconfigured?: boolean;\r\n loadingComponent?: React.ReactNode;\r\n loginPath?: string;\r\n}\r\n\r\nconst TIER_LEVELS: Record<string, number> = {\r\n free: 0,\r\n starter: 1,\r\n creator: 2,\r\n pro: 3,\r\n business: 4,\r\n enterprise: 5,\r\n};\r\n\r\nfunction DefaultLoadingSpinner() {\r\n return (\r\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '200px' }}>\r\n <div style={{\r\n width: '32px', height: '32px',\r\n border: '3px solid #e5e7eb', borderTopColor: '#3b82f6',\r\n borderRadius: '50%',\r\n animation: 'spin 0.6s linear infinite',\r\n }} />\r\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProtectedRoute({\r\n children,\r\n requiredTier,\r\n fallback,\r\n loadingComponent,\r\n allowUnconfigured = false,\r\n loginPath = '/login',\r\n}: ProtectedRouteProps) {\r\n const { user, profile, loading, isConfigured } = useAuth();\r\n\r\n if (loading) {\r\n return <>{loadingComponent || <DefaultLoadingSpinner />}</>;\r\n }\r\n\r\n if (!isConfigured && allowUnconfigured) {\r\n return <>{children}</>;\r\n }\r\n\r\n if (!user) {\r\n if (fallback) return <>{fallback}</>;\r\n if (typeof window !== 'undefined') {\r\n window.location.href = loginPath;\r\n }\r\n return null;\r\n }\r\n\r\n if (requiredTier) {\r\n const userTier = profile?.subscription_tier || 'free';\r\n const userLevel = TIER_LEVELS[userTier] ?? 0;\r\n const requiredLevel = TIER_LEVELS[requiredTier] ?? 0;\r\n\r\n if (userLevel < requiredLevel) {\r\n return (\r\n <div style={{ textAlign: 'center', padding: '40px' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '8px' }}>Upgrade Required</h2>\r\n <p style={{ color: '#6b7280' }}>\r\n This feature requires the {requiredTier} plan or higher.\r\n </p>\r\n </div>\r\n );\r\n }\r\n }\r\n\r\n return <>{children}</>;\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface LoginFormProps {\r\n onSuccess?: () => void;\r\n onForgotPassword?: () => void;\r\n onSignupClick?: () => void;\r\n showOAuth?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function LoginForm({\r\n onSuccess,\r\n onForgotPassword,\r\n onSignupClick,\r\n showOAuth = true,\r\n className = '',\r\n}: LoginFormProps) {\r\n const { signIn, signInWithProvider, isConfigured } = useAuth();\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [error, setError] = useState<string | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await signIn(email, password);\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n onSuccess?.();\r\n }\r\n };\r\n\r\n const handleOAuth = async (provider: string) => {\r\n setError(null);\r\n const result = await signInWithProvider(provider);\r\n if (result.error) {\r\n setError(result.error.message);\r\n }\r\n };\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280' }}>\r\n Authentication is not configured. Connect a database to enable login.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '24px', textAlign: 'center' }}>\r\n Sign In\r\n </h2>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input\r\n type=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }}\r\n />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Password</label>\r\n <input\r\n type=\"password\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }}\r\n />\r\n </div>\r\n\r\n {onForgotPassword && (\r\n <div style={{ marginBottom: '16px', textAlign: 'right' }}>\r\n <button type=\"button\" onClick={onForgotPassword} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Forgot password?\r\n </button>\r\n </div>\r\n )}\r\n\r\n <button\r\n type=\"submit\"\r\n disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}\r\n >\r\n {loading ? 'Signing in...' : 'Sign In'}\r\n </button>\r\n </form>\r\n\r\n {showOAuth && (\r\n <div style={{ marginTop: '24px' }}>\r\n <div style={{ textAlign: 'center', color: '#9ca3af', fontSize: '14px', marginBottom: '16px' }}>or continue with</div>\r\n <div style={{ display: 'flex', gap: '12px' }}>\r\n <button\r\n onClick={() => handleOAuth('google')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}\r\n >\r\n Google\r\n </button>\r\n <button\r\n onClick={() => handleOAuth('github')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}\r\n >\r\n GitHub\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {onSignupClick && (\r\n <div style={{ marginTop: '24px', textAlign: 'center', fontSize: '14px' }}>\r\n Don't have an account?{' '}\r\n <button type=\"button\" onClick={onSignupClick} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontWeight: 500 }}>\r\n Sign up\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface SignupFormProps {\r\n onSuccess?: () => void;\r\n onLoginClick?: () => void;\r\n showOAuth?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function SignupForm({\r\n onSuccess,\r\n onLoginClick,\r\n showOAuth = true,\r\n className = '',\r\n}: SignupFormProps) {\r\n const { signUp, signInWithProvider, isConfigured } = useAuth();\r\n const [name, setName] = useState('');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [agreed, setAgreed] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!agreed) {\r\n setError('Please agree to the Terms of Service');\r\n return;\r\n }\r\n if (password.length < 8) {\r\n setError('Password must be at least 8 characters');\r\n return;\r\n }\r\n\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await signUp(email, password, {\r\n metadata: { display_name: name },\r\n });\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n setSuccess(true);\r\n onSuccess?.();\r\n }\r\n };\r\n\r\n const handleOAuth = async (provider: string) => {\r\n setError(null);\r\n const result = await signInWithProvider(provider);\r\n if (result.error) {\r\n setError(result.error.message);\r\n }\r\n };\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280' }}>\r\n Authentication is not configured. Connect a database to enable signup.\r\n </div>\r\n );\r\n }\r\n\r\n if (success) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center' }}>\r\n <h3 style={{ fontSize: '1.25rem', fontWeight: 600, marginBottom: '8px', color: '#059669' }}>Check your email</h3>\r\n <p style={{ color: '#6b7280' }}>We sent a confirmation link to {email}</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '24px', textAlign: 'center' }}>\r\n Create Account\r\n </h2>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Name</label>\r\n <input type=\"text\" value={name} onChange={(e) => setName(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input type=\"email\" value={email} onChange={(e) => setEmail(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Password</label>\r\n <input type=\"password\" value={password} onChange={(e) => setPassword(e.target.value)} required minLength={8}\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n <span style={{ fontSize: '12px', color: '#9ca3af' }}>Minimum 8 characters</span>\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'flex', alignItems: 'center', gap: '8px', fontSize: '14px', cursor: 'pointer' }}>\r\n <input type=\"checkbox\" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />\r\n I agree to the Terms of Service and Privacy Policy\r\n </label>\r\n </div>\r\n\r\n <button type=\"submit\" disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}>\r\n {loading ? 'Creating account...' : 'Create Account'}\r\n </button>\r\n </form>\r\n\r\n {showOAuth && (\r\n <div style={{ marginTop: '24px' }}>\r\n <div style={{ textAlign: 'center', color: '#9ca3af', fontSize: '14px', marginBottom: '16px' }}>or continue with</div>\r\n <div style={{ display: 'flex', gap: '12px' }}>\r\n <button onClick={() => handleOAuth('google')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}>\r\n Google\r\n </button>\r\n <button onClick={() => handleOAuth('github')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}>\r\n GitHub\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {onLoginClick && (\r\n <div style={{ marginTop: '24px', textAlign: 'center', fontSize: '14px' }}>\r\n Already have an account?{' '}\r\n <button type=\"button\" onClick={onLoginClick} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontWeight: 500 }}>\r\n Sign in\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface ForgotPasswordFormProps {\r\n onBack?: () => void;\r\n className?: string;\r\n}\r\n\r\nexport function ForgotPasswordForm({ onBack, className = '' }: ForgotPasswordFormProps) {\r\n const { resetPassword } = useAuth();\r\n const [email, setEmail] = useState('');\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await resetPassword(email);\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n setSuccess(true);\r\n }\r\n };\r\n\r\n if (success) {\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto', textAlign: 'center', padding: '20px' }}>\r\n <h3 style={{ fontSize: '1.25rem', fontWeight: 600, marginBottom: '8px', color: '#059669' }}>Check your email</h3>\r\n <p style={{ color: '#6b7280', marginBottom: '16px' }}>We sent a password reset link to {email}</p>\r\n {onBack && (\r\n <button type=\"button\" onClick={onBack} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Back to login\r\n </button>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '8px', textAlign: 'center' }}>Reset Password</h2>\r\n <p style={{ color: '#6b7280', textAlign: 'center', marginBottom: '24px', fontSize: '14px' }}>\r\n Enter your email and we'll send you a reset link\r\n </p>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input type=\"email\" value={email} onChange={(e) => setEmail(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <button type=\"submit\" disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}>\r\n {loading ? 'Sending...' : 'Send Reset Link'}\r\n </button>\r\n </form>\r\n\r\n {onBack && (\r\n <div style={{ marginTop: '16px', textAlign: 'center' }}>\r\n <button type=\"button\" onClick={onBack} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Back to login\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport { supabase } from '../core/supabase';\r\nimport { isNeonAuthConfigured } from '../core/config';\r\n\r\ninterface AuthCallbackProps {\r\n redirectTo?: string;\r\n loadingComponent?: React.ReactNode;\r\n}\r\n\r\nexport function AuthCallback({ redirectTo = '/', loadingComponent }: AuthCallbackProps) {\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n useEffect(() => {\r\n const handleCallback = async () => {\r\n try {\r\n // Neon Auth (Better Auth) path: the OAuth flow is completed by the Better\r\n // Auth server, which sets the session cookie and redirects to the app's\r\n // callbackURL. There is no client-side PKCE exchange to perform here.\r\n // Notify any opener (in-editor popup) and either close or land the user.\r\n if (isNeonAuthConfigured) {\r\n if (typeof window !== 'undefined' && window.opener && window.opener !== window) {\r\n try { window.opener.postMessage({ type: 'ezc-auth-complete' }, '*'); } catch { /* cross-origin opener */ }\r\n window.close();\r\n return;\r\n }\r\n if (typeof window !== 'undefined') window.location.href = redirectTo;\r\n return;\r\n }\r\n // With detectSessionInUrl + PKCE the client usually auto-exchanges the\r\n // `?code=` before we run, so getSession() already has it. If not (e.g. a\r\n // build with detectSessionInUrl disabled), exchange explicitly.\r\n let session = null;\r\n const got = await supabase.auth.getSession();\r\n if (got.error) { setError(got.error.message); return; }\r\n session = got.data?.session ?? null;\r\n\r\n if (!session && typeof window !== 'undefined' &&\r\n new URLSearchParams(window.location.search).get('code')) {\r\n const ex = await supabase.auth.exchangeCodeForSession(window.location.href);\r\n if (ex.error) { setError(ex.error.message); return; }\r\n session = ex.data?.session ?? null;\r\n }\r\n\r\n // Popup flow (in-editor / framed sign-in): notify the opener and close,\r\n // rather than navigating. The opener (AuthProvider) picks up the session.\r\n if (typeof window !== 'undefined' && window.opener && window.opener !== window) {\r\n try { window.opener.postMessage({ type: 'ezc-auth-complete' }, '*'); } catch { /* cross-origin opener */ }\r\n window.close();\r\n return;\r\n }\r\n\r\n window.location.href = redirectTo;\r\n } catch (err: unknown) {\r\n setError(err instanceof Error ? err.message : 'Authentication callback failed');\r\n }\r\n };\r\n\r\n handleCallback();\r\n }, [redirectTo]);\r\n\r\n if (error) {\r\n return (\r\n <div style={{ textAlign: 'center', padding: '40px' }}>\r\n <h2 style={{ color: '#dc2626', marginBottom: '8px' }}>Authentication Error</h2>\r\n <p style={{ color: '#6b7280' }}>{error}</p>\r\n <a href=\"/login\" style={{ color: '#3b82f6', marginTop: '16px', display: 'inline-block' }}>\r\n Back to login\r\n </a>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n {loadingComponent || (\r\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '200px' }}>\r\n <p style={{ color: '#6b7280' }}>Completing authentication...</p>\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","useState","jsx","jsxs","useState","useState","jsx","jsxs","useState","useState","Fragment","jsx","jsxs","useState"]}
|
|
1
|
+
{"version":3,"sources":["../../src/auth/ProtectedRoute.tsx","../../src/auth/LoginForm.tsx","../../src/auth/SignupForm.tsx","../../src/auth/ForgotPasswordForm.tsx","../../src/auth/AuthCallback.tsx"],"sourcesContent":["import { useAuth } from './AuthProvider';\r\nimport type { SubscriptionTier } from '../core/types';\r\n\r\ninterface ProtectedRouteProps {\r\n children: React.ReactNode;\r\n requiredRoles?: string[];\r\n requiredTier?: SubscriptionTier;\r\n fallback?: React.ReactNode;\r\n unauthorizedFallback?: React.ReactNode;\r\n allowUnconfigured?: boolean;\r\n loadingComponent?: React.ReactNode;\r\n loginPath?: string;\r\n}\r\n\r\nconst TIER_LEVELS: Record<string, number> = {\r\n free: 0,\r\n starter: 1,\r\n creator: 2,\r\n pro: 3,\r\n business: 4,\r\n enterprise: 5,\r\n};\r\n\r\nfunction DefaultLoadingSpinner() {\r\n return (\r\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '200px' }}>\r\n <div style={{\r\n width: '32px', height: '32px',\r\n border: '3px solid #e5e7eb', borderTopColor: '#3b82f6',\r\n borderRadius: '50%',\r\n animation: 'spin 0.6s linear infinite',\r\n }} />\r\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProtectedRoute({\r\n children,\r\n requiredTier,\r\n fallback,\r\n loadingComponent,\r\n allowUnconfigured = false,\r\n loginPath = '/login',\r\n}: ProtectedRouteProps) {\r\n const { user, profile, loading, isConfigured } = useAuth();\r\n\r\n if (loading) {\r\n return <>{loadingComponent || <DefaultLoadingSpinner />}</>;\r\n }\r\n\r\n if (!isConfigured && allowUnconfigured) {\r\n return <>{children}</>;\r\n }\r\n\r\n if (!user) {\r\n if (fallback) return <>{fallback}</>;\r\n if (typeof window !== 'undefined') {\r\n window.location.href = loginPath;\r\n }\r\n return null;\r\n }\r\n\r\n if (requiredTier) {\r\n const userTier = profile?.subscription_tier || 'free';\r\n const userLevel = TIER_LEVELS[userTier] ?? 0;\r\n const requiredLevel = TIER_LEVELS[requiredTier] ?? 0;\r\n\r\n if (userLevel < requiredLevel) {\r\n return (\r\n <div style={{ textAlign: 'center', padding: '40px' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '8px' }}>Upgrade Required</h2>\r\n <p style={{ color: '#6b7280' }}>\r\n This feature requires the {requiredTier} plan or higher.\r\n </p>\r\n </div>\r\n );\r\n }\r\n }\r\n\r\n return <>{children}</>;\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface LoginFormProps {\r\n onSuccess?: () => void;\r\n onForgotPassword?: () => void;\r\n onSignupClick?: () => void;\r\n showOAuth?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function LoginForm({\r\n onSuccess,\r\n onForgotPassword,\r\n onSignupClick,\r\n showOAuth = true,\r\n className = '',\r\n}: LoginFormProps) {\r\n const { signIn, signInWithProvider, isConfigured } = useAuth();\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [error, setError] = useState<string | null>(null);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await signIn(email, password);\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n onSuccess?.();\r\n }\r\n };\r\n\r\n const handleOAuth = async (provider: string) => {\r\n setError(null);\r\n const result = await signInWithProvider(provider);\r\n if (result.error) {\r\n setError(result.error.message);\r\n }\r\n };\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280' }}>\r\n Authentication is not configured. Connect a database to enable login.\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '24px', textAlign: 'center' }}>\r\n Sign In\r\n </h2>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input\r\n type=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }}\r\n />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Password</label>\r\n <input\r\n type=\"password\"\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }}\r\n />\r\n </div>\r\n\r\n {onForgotPassword && (\r\n <div style={{ marginBottom: '16px', textAlign: 'right' }}>\r\n <button type=\"button\" onClick={onForgotPassword} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Forgot password?\r\n </button>\r\n </div>\r\n )}\r\n\r\n <button\r\n type=\"submit\"\r\n disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}\r\n >\r\n {loading ? 'Signing in...' : 'Sign In'}\r\n </button>\r\n </form>\r\n\r\n {showOAuth && (\r\n <div style={{ marginTop: '24px' }}>\r\n <div style={{ textAlign: 'center', color: '#9ca3af', fontSize: '14px', marginBottom: '16px' }}>or continue with</div>\r\n <div style={{ display: 'flex', gap: '12px' }}>\r\n <button\r\n onClick={() => handleOAuth('google')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}\r\n >\r\n Google\r\n </button>\r\n <button\r\n onClick={() => handleOAuth('github')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}\r\n >\r\n GitHub\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {onSignupClick && (\r\n <div style={{ marginTop: '24px', textAlign: 'center', fontSize: '14px' }}>\r\n Don't have an account?{' '}\r\n <button type=\"button\" onClick={onSignupClick} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontWeight: 500 }}>\r\n Sign up\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface SignupFormProps {\r\n onSuccess?: () => void;\r\n onLoginClick?: () => void;\r\n showOAuth?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function SignupForm({\r\n onSuccess,\r\n onLoginClick,\r\n showOAuth = true,\r\n className = '',\r\n}: SignupFormProps) {\r\n const { signUp, signInWithProvider, isConfigured } = useAuth();\r\n const [name, setName] = useState('');\r\n const [email, setEmail] = useState('');\r\n const [password, setPassword] = useState('');\r\n const [agreed, setAgreed] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!agreed) {\r\n setError('Please agree to the Terms of Service');\r\n return;\r\n }\r\n if (password.length < 8) {\r\n setError('Password must be at least 8 characters');\r\n return;\r\n }\r\n\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await signUp(email, password, {\r\n metadata: { display_name: name },\r\n });\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n setSuccess(true);\r\n onSuccess?.();\r\n }\r\n };\r\n\r\n const handleOAuth = async (provider: string) => {\r\n setError(null);\r\n const result = await signInWithProvider(provider);\r\n if (result.error) {\r\n setError(result.error.message);\r\n }\r\n };\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280' }}>\r\n Authentication is not configured. Connect a database to enable signup.\r\n </div>\r\n );\r\n }\r\n\r\n if (success) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center' }}>\r\n <h3 style={{ fontSize: '1.25rem', fontWeight: 600, marginBottom: '8px', color: '#059669' }}>Check your email</h3>\r\n <p style={{ color: '#6b7280' }}>We sent a confirmation link to {email}</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '24px', textAlign: 'center' }}>\r\n Create Account\r\n </h2>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Name</label>\r\n <input type=\"text\" value={name} onChange={(e) => setName(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input type=\"email\" value={email} onChange={(e) => setEmail(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Password</label>\r\n <input type=\"password\" value={password} onChange={(e) => setPassword(e.target.value)} required minLength={8}\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n <span style={{ fontSize: '12px', color: '#9ca3af' }}>Minimum 8 characters</span>\r\n </div>\r\n\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'flex', alignItems: 'center', gap: '8px', fontSize: '14px', cursor: 'pointer' }}>\r\n <input type=\"checkbox\" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />\r\n I agree to the Terms of Service and Privacy Policy\r\n </label>\r\n </div>\r\n\r\n <button type=\"submit\" disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}>\r\n {loading ? 'Creating account...' : 'Create Account'}\r\n </button>\r\n </form>\r\n\r\n {showOAuth && (\r\n <div style={{ marginTop: '24px' }}>\r\n <div style={{ textAlign: 'center', color: '#9ca3af', fontSize: '14px', marginBottom: '16px' }}>or continue with</div>\r\n <div style={{ display: 'flex', gap: '12px' }}>\r\n <button onClick={() => handleOAuth('google')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}>\r\n Google\r\n </button>\r\n <button onClick={() => handleOAuth('github')}\r\n style={{ flex: 1, padding: '10px', border: '1px solid #d1d5db', borderRadius: '6px', background: 'white', cursor: 'pointer', fontSize: '14px' }}>\r\n GitHub\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {onLoginClick && (\r\n <div style={{ marginTop: '24px', textAlign: 'center', fontSize: '14px' }}>\r\n Already have an account?{' '}\r\n <button type=\"button\" onClick={onLoginClick} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontWeight: 500 }}>\r\n Sign in\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\nimport { useAuth } from './AuthProvider';\r\n\r\ninterface ForgotPasswordFormProps {\r\n onBack?: () => void;\r\n className?: string;\r\n}\r\n\r\nexport function ForgotPasswordForm({ onBack, className = '' }: ForgotPasswordFormProps) {\r\n const { resetPassword } = useAuth();\r\n const [email, setEmail] = useState('');\r\n const [error, setError] = useState<string | null>(null);\r\n const [success, setSuccess] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(null);\r\n setLoading(true);\r\n\r\n const result = await resetPassword(email);\r\n setLoading(false);\r\n\r\n if (result.error) {\r\n setError(result.error.message);\r\n } else {\r\n setSuccess(true);\r\n }\r\n };\r\n\r\n if (success) {\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto', textAlign: 'center', padding: '20px' }}>\r\n <h3 style={{ fontSize: '1.25rem', fontWeight: 600, marginBottom: '8px', color: '#059669' }}>Check your email</h3>\r\n <p style={{ color: '#6b7280', marginBottom: '16px' }}>We sent a password reset link to {email}</p>\r\n {onBack && (\r\n <button type=\"button\" onClick={onBack} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Back to login\r\n </button>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={className} style={{ maxWidth: '400px', margin: '0 auto' }}>\r\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '8px', textAlign: 'center' }}>Reset Password</h2>\r\n <p style={{ color: '#6b7280', textAlign: 'center', marginBottom: '24px', fontSize: '14px' }}>\r\n Enter your email and we'll send you a reset link\r\n </p>\r\n\r\n {error && (\r\n <div style={{ padding: '12px', marginBottom: '16px', backgroundColor: '#fef2f2', color: '#dc2626', borderRadius: '8px', fontSize: '14px' }}>\r\n {error}\r\n </div>\r\n )}\r\n\r\n <form onSubmit={handleSubmit}>\r\n <div style={{ marginBottom: '16px' }}>\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '14px', fontWeight: 500 }}>Email</label>\r\n <input type=\"email\" value={email} onChange={(e) => setEmail(e.target.value)} required\r\n style={{ width: '100%', padding: '8px 12px', border: '1px solid #d1d5db', borderRadius: '6px', fontSize: '14px' }} />\r\n </div>\r\n\r\n <button type=\"submit\" disabled={loading}\r\n style={{\r\n width: '100%', padding: '10px', backgroundColor: '#3b82f6', color: 'white',\r\n border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500,\r\n cursor: loading ? 'not-allowed' : 'pointer', opacity: loading ? 0.7 : 1,\r\n }}>\r\n {loading ? 'Sending...' : 'Send Reset Link'}\r\n </button>\r\n </form>\r\n\r\n {onBack && (\r\n <div style={{ marginTop: '16px', textAlign: 'center' }}>\r\n <button type=\"button\" onClick={onBack} style={{ background: 'none', border: 'none', color: '#3b82f6', cursor: 'pointer', fontSize: '14px' }}>\r\n Back to login\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport { supabase } from '../core/supabase';\r\nimport { env, isNeonAuthConfigured } from '../core/config';\r\nimport { getNeonAuthClient } from './neonAuthClient';\r\n\r\ninterface AuthCallbackProps {\r\n redirectTo?: string;\r\n loadingComponent?: React.ReactNode;\r\n}\r\n\r\n/** Generate a cryptographically-random password of at least 32 characters. */\r\nfunction generateRandomPassword(): string {\r\n const bytes = new Uint8Array(32);\r\n crypto.getRandomValues(bytes);\r\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\r\n}\r\n\r\nexport function AuthCallback({ redirectTo = '/', loadingComponent }: AuthCallbackProps) {\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n useEffect(() => {\r\n const handleCallback = async () => {\r\n try {\r\n // ── Proxy handoff branch (Neon path only) ────────────────────────────\r\n // The central EzCoder auth proxy appended `#code=<singleUse>` to the\r\n // callback URL. We must exchange it before doing anything else, including\r\n // notifying openers, so that the session cookie is established first.\r\n if (isNeonAuthConfigured && typeof window !== 'undefined') {\r\n const hash = window.location.hash;\r\n // Only treat it as a proxy code when the fragment starts with `#code=`\r\n // (or contains `code=` after `#`).\r\n const hashParams = new URLSearchParams(hash.startsWith('#') ? hash.slice(1) : hash);\r\n const proxyCode = hashParams.get('code');\r\n const proxyError = hashParams.get('error');\r\n\r\n // The proxy reports a failed sign-in via `#error=<reason>`. Surface it\r\n // (don't fall through to the success redirect, which would look \"logged in\").\r\n if (proxyError) {\r\n window.history.replaceState(null, '', window.location.pathname + window.location.search);\r\n setError(\r\n proxyError === 'email_exists'\r\n ? 'An account with this email already exists. Please sign in with your original method.'\r\n : 'Sign-in could not be completed. Please try again.'\r\n );\r\n return;\r\n }\r\n\r\n if (proxyCode) {\r\n // Scrub the code from the URL immediately before any async work so it\r\n // cannot be captured by third-party scripts or browser history.\r\n window.history.replaceState(\r\n null,\r\n '',\r\n window.location.pathname + window.location.search\r\n );\r\n\r\n const authClient = getNeonAuthClient();\r\n if (!authClient || !env.EZCODER_API_URL) {\r\n setError('Auth client not available for proxy exchange');\r\n return;\r\n }\r\n\r\n // Exchange the single-use code for ephemeral credentials.\r\n const exchangeRes = await fetch(\r\n `${env.EZCODER_API_URL.replace(/\\/$/, '')}/api/app-auth/exchange`,\r\n {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json' },\r\n mode: 'cors',\r\n body: JSON.stringify({ code: proxyCode }),\r\n }\r\n );\r\n\r\n if (!exchangeRes.ok) {\r\n const msg = await exchangeRes.text().catch(() => exchangeRes.statusText);\r\n setError(`Auth exchange failed: ${msg}`);\r\n return;\r\n }\r\n\r\n const { email, password, finalizeToken } = (await exchangeRes.json()) as {\r\n email: string;\r\n password: string;\r\n finalizeToken?: string;\r\n };\r\n\r\n // Sign in directly against the per-project Neon Auth server so the\r\n // browser gets the native SameSite=None;Partitioned session cookie.\r\n const signInResult = await authClient.signIn.email({ email, password });\r\n const signInError = (signInResult as { error?: unknown })?.error;\r\n if (signInError) {\r\n const errObj =\r\n signInError instanceof Error\r\n ? signInError\r\n : new Error(\r\n typeof (signInError as { message?: string })?.message === 'string'\r\n ? (signInError as { message: string }).message\r\n : 'Sign in failed after proxy exchange'\r\n );\r\n setError(errObj.message);\r\n return;\r\n }\r\n\r\n // Kill the briefly-exposed ephemeral credential via TWO independent paths so a\r\n // same-origin XSS cannot keep a durable password:\r\n // (1) client-side changePassword with revokeOtherSessions:true — also kills any\r\n // session an attacker minted with the captured password;\r\n // (2) server-side finalize — the AUTHORITATIVE rotation; runs even if (1) fails.\r\n // Both are best-effort w.r.t. blocking login (the user is already signed in), but\r\n // (2) is reliable server-side, closing the swallowed-failure gap.\r\n try {\r\n const changePasswordFn = (\r\n authClient as unknown as {\r\n changePassword?: (args: {\r\n currentPassword: string;\r\n newPassword: string;\r\n revokeOtherSessions: boolean;\r\n }) => Promise<unknown>;\r\n }\r\n ).changePassword;\r\n if (changePasswordFn) {\r\n await changePasswordFn({\r\n currentPassword: password,\r\n newPassword: generateRandomPassword(),\r\n revokeOtherSessions: true,\r\n });\r\n }\r\n } catch {\r\n // Client rotation failed — the server-side finalize below is the safety net.\r\n }\r\n\r\n if (finalizeToken && env.EZCODER_API_URL) {\r\n try {\r\n await fetch(\r\n `${env.EZCODER_API_URL.replace(/\\/$/, '')}/api/app-auth/finalize`,\r\n {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json' },\r\n mode: 'cors',\r\n body: JSON.stringify({ finalizeToken }),\r\n }\r\n );\r\n } catch {\r\n // Server rotation network failure — non-fatal; the short-TTL token expires.\r\n }\r\n }\r\n\r\n // Notify any opener (in-editor popup flow) and finish.\r\n if (window.opener && window.opener !== window) {\r\n try {\r\n window.opener.postMessage({ type: 'ezc-auth-complete' }, '*');\r\n } catch {\r\n /* cross-origin opener */\r\n }\r\n window.close();\r\n return;\r\n }\r\n window.location.href = redirectTo;\r\n return;\r\n }\r\n }\r\n\r\n // ── Neon Auth (Better Auth) direct path ───────────────────────────────\r\n // The OAuth flow was completed by the Better Auth server (no proxy), which\r\n // sets the session cookie and redirects to the app's callbackURL. There is\r\n // no client-side PKCE exchange to perform here. Notify any opener\r\n // (in-editor popup) and either close or land the user.\r\n if (isNeonAuthConfigured) {\r\n if (typeof window !== 'undefined' && window.opener && window.opener !== window) {\r\n try { window.opener.postMessage({ type: 'ezc-auth-complete' }, '*'); } catch { /* cross-origin opener */ }\r\n window.close();\r\n return;\r\n }\r\n if (typeof window !== 'undefined') window.location.href = redirectTo;\r\n return;\r\n }\r\n // With detectSessionInUrl + PKCE the client usually auto-exchanges the\r\n // `?code=` before we run, so getSession() already has it. If not (e.g. a\r\n // build with detectSessionInUrl disabled), exchange explicitly.\r\n let session = null;\r\n const got = await supabase.auth.getSession();\r\n if (got.error) { setError(got.error.message); return; }\r\n session = got.data?.session ?? null;\r\n\r\n if (!session && typeof window !== 'undefined' &&\r\n new URLSearchParams(window.location.search).get('code')) {\r\n const ex = await supabase.auth.exchangeCodeForSession(window.location.href);\r\n if (ex.error) { setError(ex.error.message); return; }\r\n session = ex.data?.session ?? null;\r\n }\r\n\r\n // Popup flow (in-editor / framed sign-in): notify the opener and close,\r\n // rather than navigating. The opener (AuthProvider) picks up the session.\r\n if (typeof window !== 'undefined' && window.opener && window.opener !== window) {\r\n try { window.opener.postMessage({ type: 'ezc-auth-complete' }, '*'); } catch { /* cross-origin opener */ }\r\n window.close();\r\n return;\r\n }\r\n\r\n window.location.href = redirectTo;\r\n } catch (err: unknown) {\r\n setError(err instanceof Error ? err.message : 'Authentication callback failed');\r\n }\r\n };\r\n\r\n handleCallback();\r\n }, [redirectTo]);\r\n\r\n if (error) {\r\n return (\r\n <div style={{ textAlign: 'center', padding: '40px' }}>\r\n <h2 style={{ color: '#dc2626', marginBottom: '8px' }}>Authentication Error</h2>\r\n <p style={{ color: '#6b7280' }}>{error}</p>\r\n <a href=\"/login\" style={{ color: '#3b82f6', marginTop: '16px', display: 'inline-block' }}>\r\n Back to login\r\n </a>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n {loadingComponent || (\r\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '200px' }}>\r\n <p style={{ color: '#6b7280' }}>Completing authentication...</p>\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","useState","jsx","jsxs","useState","useState","jsx","jsxs","useState","useState","Fragment","jsx","jsxs","useState"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KWR4PA5I.js";
|
|
4
4
|
|
|
5
5
|
// src/core/projectToken.ts
|
|
6
6
|
function isBrowserRuntime() {
|
|
@@ -41,4 +41,4 @@ function warnLegacyOnce() {
|
|
|
41
41
|
export {
|
|
42
42
|
resolveServerToken
|
|
43
43
|
};
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-FFMYVTI2.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KWR4PA5I.js";
|
|
4
4
|
|
|
5
5
|
// src/core/supabase.ts
|
|
6
6
|
import { createClient } from "@supabase/supabase-js";
|
|
@@ -118,4 +118,4 @@ export {
|
|
|
118
118
|
supabase,
|
|
119
119
|
isSupabaseConfigured
|
|
120
120
|
};
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-FPSSXTQG.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ezcoder,
|
|
3
3
|
ezcoderAuthIntegration
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OIAKVQGD.js";
|
|
5
5
|
import {
|
|
6
6
|
isSupabaseConfigured,
|
|
7
7
|
supabase
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FPSSXTQG.js";
|
|
9
9
|
import {
|
|
10
10
|
env,
|
|
11
11
|
isNeonAuthConfigured
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KWR4PA5I.js";
|
|
13
13
|
|
|
14
14
|
// src/auth/neonAuthClient.ts
|
|
15
15
|
import { createAuthClient } from "better-auth/react";
|
|
@@ -154,6 +154,17 @@ function NeonAuthProvider({ children }) {
|
|
|
154
154
|
const callbackURL = options.redirectTo || origin;
|
|
155
155
|
const framed = typeof window !== "undefined" && window.self !== window.top;
|
|
156
156
|
const social = provider;
|
|
157
|
+
if (env.APP_AUTH_PROXY && env.EZCODER_API_URL && env.EZC_PROJECT_ID) {
|
|
158
|
+
const proxyStartUrl = `${env.EZCODER_API_URL.replace(/\/$/, "")}/api/app-auth/start?provider=${encodeURIComponent(provider)}&projectId=${encodeURIComponent(env.EZC_PROJECT_ID)}&returnUrl=${encodeURIComponent(origin + "/auth/callback")}`;
|
|
159
|
+
if (framed && typeof window !== "undefined") {
|
|
160
|
+
window.open(proxyStartUrl, "ezc-auth", "popup,width=500,height=680");
|
|
161
|
+
return { data: null, error: null };
|
|
162
|
+
}
|
|
163
|
+
if (typeof window !== "undefined") {
|
|
164
|
+
window.location.href = proxyStartUrl;
|
|
165
|
+
}
|
|
166
|
+
return { data: null, error: null };
|
|
167
|
+
}
|
|
157
168
|
if (framed && typeof window !== "undefined") {
|
|
158
169
|
const result2 = await authClient.signIn.social({
|
|
159
170
|
provider: social,
|
|
@@ -542,4 +553,4 @@ export {
|
|
|
542
553
|
AuthProvider,
|
|
543
554
|
useAuth
|
|
544
555
|
};
|
|
545
|
-
//# sourceMappingURL=chunk-
|
|
556
|
+
//# sourceMappingURL=chunk-HX7IFB7C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/neonAuthClient.ts","../src/auth/AuthProvider.tsx"],"sourcesContent":["import { createAuthClient } from 'better-auth/react';\nimport { env, isNeonAuthConfigured } from '../core/config';\n\n/**\n * Per-project Neon Auth (Better Auth) client.\n *\n * A project uses Neon Auth when `env.NEON_AUTH_URL` (the per-project Better Auth\n * `base_url`, e.g. `https://ep-xxx.neonauth.<region>.aws.neon.tech/neondb/auth`)\n * is injected as `VITE_NEON_AUTH_URL`. When present, the SDK authenticates the\n * generated app against its OWN isolated Neon Auth server rather than the shared\n * tenant Supabase.\n *\n * The client is created lazily so that:\n * - non-Neon projects never instantiate it (zero behavioural change), and\n * - SSR/build passes that import the SDK without a base URL don't throw.\n *\n * This is the official Better Auth React client (`createAuthClient` from\n * `better-auth/react`). It owns token storage and cross-origin session handling;\n * do NOT hand-roll fetch against the Better Auth endpoints.\n */\nexport type NeonAuthClient = ReturnType<typeof createAuthClient>;\n\nlet cachedClient: NeonAuthClient | null = null;\n\n/**\n * Returns the lazily-created Better Auth client, or `null` when Neon Auth is not\n * configured for this project. Callers on the Neon path should treat a `null`\n * return as \"not configured\" and surface a clear error.\n */\nexport function getNeonAuthClient(): NeonAuthClient | null {\n if (!isNeonAuthConfigured || !env.NEON_AUTH_URL) {\n return null;\n }\n if (!cachedClient) {\n cachedClient = createAuthClient({\n baseURL: env.NEON_AUTH_URL,\n });\n }\n return cachedClient;\n}\n\n/** True when this project ships its own per-project Neon Auth server. */\nexport { isNeonAuthConfigured };\n","import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { User, Session } from '@supabase/supabase-js';\nimport { supabase, isSupabaseConfigured } from '../core/supabase';\nimport { env, isNeonAuthConfigured } from '../core/config';\nimport { ezcoder, ezcoderAuthIntegration } from '../core/platform';\nimport { getNeonAuthClient } from './neonAuthClient';\nimport type { UserProfile } from '../core/types';\n\ninterface AuthResult<T = unknown> {\n data: T | null;\n error: Error | null;\n}\n\ninterface SignUpOptions {\n metadata?: Record<string, unknown>;\n}\n\ninterface SignInWithProviderOptions {\n redirectTo?: string;\n [key: string]: unknown;\n}\n\nexport interface AuthContextType {\n user: User | null;\n profile: UserProfile | null;\n session: Session | null;\n loading: boolean;\n isConfigured: boolean;\n signUp: (email: string, password: string, options?: SignUpOptions) => Promise<AuthResult>;\n signIn: (email: string, password: string) => Promise<AuthResult>;\n signInWithProvider: (provider: string, options?: SignInWithProviderOptions) => Promise<AuthResult>;\n signOut: () => Promise<{ error: Error | null }>;\n resetPassword: (email: string) => Promise<AuthResult>;\n updatePassword: (newPassword: string) => Promise<AuthResult>;\n updateProfile: (updates: Partial<UserProfile>) => Promise<AuthResult>;\n refetchProfile: (userId: string) => Promise<UserProfile | null>;\n}\n\nconst NOT_CONFIGURED_MSG = 'Authentication is not configured. Ensure EzCoder platform credentials are injected, or connect your own Supabase database in Settings → Databases.';\nfunction notConfiguredError() {\n return new Error(NOT_CONFIGURED_MSG);\n}\n\nexport const AuthContext = createContext<AuthContextType>({\n user: null,\n profile: null,\n session: null,\n loading: true,\n isConfigured: false,\n signUp: async () => ({ data: null, error: null }),\n signIn: async () => ({ data: null, error: null }),\n signInWithProvider: async () => ({ data: null, error: null }),\n signOut: async () => ({ error: null }),\n resetPassword: async () => ({ data: null, error: null }),\n updatePassword: async () => ({ data: null, error: null }),\n updateProfile: async () => ({ data: null, error: null }),\n refetchProfile: async () => null,\n});\n\n// ─── Path selector ──────────────────────────────────────────────────────────\n//\n// A project authenticates against its OWN per-project Neon Auth (Better Auth)\n// server when `VITE_NEON_AUTH_URL` is injected. Otherwise it falls back to the\n// existing shared-tenant Supabase path, which is behaviour-preserved verbatim\n// below in `SupabaseAuthProvider`.\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n if (isNeonAuthConfigured) {\n return <NeonAuthProvider>{children}</NeonAuthProvider>;\n }\n return <SupabaseAuthProvider>{children}</SupabaseAuthProvider>;\n}\n\n// ─── Neon Auth (Better Auth) path ────────────────────────────────────────────\n\n// The Better Auth user shape (subset we rely on). The full object also carries\n// emailVerified, image, role, banned, createdAt, updatedAt, etc.\ninterface BetterAuthUser {\n id?: string;\n email?: string;\n name?: string;\n image?: string | null;\n emailVerified?: boolean;\n role?: string;\n createdAt?: string;\n updatedAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Normalize a Better Auth user into the SDK's `user` shape. The context type\n * declares `User` (Supabase) for backwards compatibility, so we project the\n * Better Auth fields onto a Supabase-User-compatible object: `id`, `email`, and\n * a `user_metadata` carrying the display name + avatar. Consumers that read\n * `user.id`, `user.email`, or `user.user_metadata.full_name` keep working.\n */\nfunction mapNeonUser(u: BetterAuthUser | null | undefined): User | null {\n if (!u || !u.id) return null;\n const nowIso = new Date().toISOString();\n return {\n id: u.id,\n email: u.email,\n app_metadata: { provider: 'neon-auth', ...(u.role ? { role: u.role } : {}) },\n user_metadata: {\n full_name: u.name,\n name: u.name,\n avatar_url: u.image ?? undefined,\n email_verified: u.emailVerified,\n },\n aud: 'authenticated',\n created_at: u.createdAt || nowIso,\n updated_at: u.updatedAt || nowIso,\n role: u.role,\n } as unknown as User;\n}\n\n/**\n * Project the Better Auth session payload onto the SDK's `session` shape. Better\n * Auth manages the real token + cookie internally; this object exists only so\n * consumers reading `session.user` / truthiness keep working. The bearer token\n * (when exposed by useSession) is surfaced as `access_token` best-effort.\n */\nfunction mapNeonSession(rawSession: unknown, user: User | null): Session | null {\n if (!user) return null;\n const s = (rawSession || {}) as Record<string, unknown>;\n const token =\n (s.token as string | undefined) ||\n ((s.session as Record<string, unknown> | undefined)?.token as string | undefined) ||\n '';\n return {\n access_token: token,\n refresh_token: '',\n token_type: 'bearer',\n expires_in: 0,\n expires_at: undefined,\n user,\n } as unknown as Session;\n}\n\nconst NEON_NOT_SUPPORTED = (feature: string) =>\n new Error(`${feature} is not supported on the Neon Auth path yet.`);\n\nfunction NeonAuthProvider({ children }: { children: React.ReactNode }) {\n const authClient = getNeonAuthClient();\n const [user, setUser] = useState<User | null>(null);\n const [profile, setProfile] = useState<UserProfile | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState<boolean>(true);\n const previousUserIdRef = useRef<string | null>(null);\n\n // Drive user/session/loading off Better Auth's reactive session hook. The hook\n // is stable across renders and re-renders the provider on auth state changes.\n const sessionState = authClient?.useSession?.() as\n | { data?: { user?: BetterAuthUser; session?: unknown } | null; isPending?: boolean }\n | undefined;\n\n const rawUser = sessionState?.data?.user ?? null;\n const isPending = sessionState?.isPending ?? false;\n\n useEffect(() => {\n const mappedUser = mapNeonUser(rawUser);\n setUser(mappedUser);\n setSession(mapNeonSession(sessionState?.data?.session ?? sessionState?.data ?? null, mappedUser));\n setLoading(Boolean(isPending));\n\n // Fire login/logout analytics on transitions, mirroring the Supabase path.\n const currentId = mappedUser?.id ?? null;\n const prevId = previousUserIdRef.current;\n if (currentId && currentId !== prevId) {\n ezcoderAuthIntegration.onLogin(mappedUser as unknown as { id: string; email?: string });\n previousUserIdRef.current = currentId;\n } else if (!currentId && prevId) {\n ezcoderAuthIntegration.onLogout(prevId);\n previousUserIdRef.current = null;\n setProfile(null);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rawUser, isPending]);\n\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n const { metadata = {} } = options;\n const name = (metadata.display_name as string | undefined) || (metadata.name as string | undefined) || email;\n try {\n const result = await authClient.signUp.email({ email, password, name });\n const error = (result as { error?: unknown })?.error;\n if (error) {\n return { data: null, error: toError(error, 'Sign up failed') };\n }\n const data = (result as { data?: unknown })?.data ?? result;\n const newUser = (data as { user?: BetterAuthUser })?.user;\n if (newUser?.id) {\n ezcoderAuthIntegration.onSignup({ id: newUser.id, email: newUser.email });\n }\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\n }\n }, [authClient]);\n\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n try {\n const result = await authClient.signIn.email({ email, password });\n const error = (result as { error?: unknown })?.error;\n if (error) {\n return { data: null, error: toError(error, 'Sign in failed') };\n }\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\n }\n }, [authClient]);\n\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n try {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const callbackURL = options.redirectTo || origin;\n const framed = typeof window !== 'undefined' && window.self !== window.top;\n const social = provider as 'google' | 'github';\n\n // ── Proxy path ────────────────────────────────────────────────────────\n // When APP_AUTH_PROXY is enabled AND we have the platform coordinates,\n // delegate social login to the central EzCoder auth proxy instead of\n // hitting the per-project Better Auth server directly. The proxy handles\n // the OAuth handshake and redirects back to <app>/auth/callback#code=<singleUse>.\n // AuthCallback.tsx picks up the fragment and completes the sign-in.\n if (env.APP_AUTH_PROXY && env.EZCODER_API_URL && env.EZC_PROJECT_ID) {\n const proxyStartUrl =\n `${env.EZCODER_API_URL.replace(/\\/$/, '')}/api/app-auth/start` +\n `?provider=${encodeURIComponent(provider)}` +\n `&projectId=${encodeURIComponent(env.EZC_PROJECT_ID)}` +\n `&returnUrl=${encodeURIComponent(origin + '/auth/callback')}`;\n\n if (framed && typeof window !== 'undefined') {\n // Open the proxy start URL in a popup so the framed editor preview\n // doesn't try to navigate inside the iframe.\n window.open(proxyStartUrl, 'ezc-auth', 'popup,width=500,height=680');\n return { data: null, error: null };\n }\n\n // Standalone (deployed app / own tab): full-page redirect to the proxy.\n if (typeof window !== 'undefined') {\n window.location.href = proxyStartUrl;\n }\n return { data: null, error: null };\n }\n\n // ── Direct Better Auth path (proxy disabled) ──────────────────────────\n if (framed && typeof window !== 'undefined') {\n // Provider login pages refuse to render inside an iframe (X-Frame-Options /\n // frame-ancestors). Ask Better Auth for the OAuth URL WITHOUT redirecting\n // (disableRedirect) and open it in a popup. The popup completes on the\n // app origin (callbackURL) and the session cookie is set; Better Auth's\n // useSession picks it up here on the next focus/poll. A small focus poke\n // nudges the hook to refetch promptly.\n const result = await authClient.signIn.social({\n provider: social,\n callbackURL,\n disableRedirect: true,\n });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'OAuth sign in failed') };\n const data = (result as { data?: { url?: string } })?.data ?? null;\n const url = data?.url;\n if (url) window.open(url, 'ezc-auth', 'popup,width=500,height=680');\n return { data, error: null };\n }\n\n // Standalone (deployed app / own tab): let Better Auth do the full-page\n // redirect to the provider.\n const result = await authClient.signIn.social({ provider: social, callbackURL });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'OAuth sign in failed') };\n const data = (result as { data?: unknown })?.data ?? null;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\n }\n }, [authClient]);\n\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\n if (!authClient) return { error: notConfiguredError() };\n const userId = user?.id;\n try {\n const result = await authClient.signOut();\n const error = (result as { error?: unknown })?.error;\n if (error) return { error: toError(error, 'Sign out failed') };\n if (userId) ezcoder.users.trackLogout(userId);\n return { error: null };\n } catch (err: unknown) {\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\n }\n }, [authClient, user]);\n\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n // Better Auth renamed `forgetPassword` → `requestPasswordReset`. Support both\n // so the SDK works regardless of the server's Better Auth version.\n const client = authClient as unknown as {\n requestPasswordReset?: (args: { email: string; redirectTo?: string }) => Promise<unknown>;\n forgetPassword?: (args: { email: string; redirectTo?: string }) => Promise<unknown>;\n };\n const redirectTo = `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`;\n const fn = client.requestPasswordReset || client.forgetPassword;\n if (!fn) {\n return { data: null, error: NEON_NOT_SUPPORTED('Password reset') };\n }\n try {\n const result = await fn({ email, redirectTo });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'Password reset failed') };\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\n }\n }, [authClient]);\n\n const updatePassword = useCallback(async (newPassword: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n // Two distinct Better Auth operations land here:\n // - `resetPassword({ newPassword, token })` after a reset-email link (token in URL)\n // - `changePassword({ newPassword, currentPassword })` for a logged-in user\n // We only have the new password, so we use the token-based reset when a\n // reset token is present in the URL; otherwise there is no safe call to make\n // (changePassword requires the current password we don't have).\n const token = typeof window !== 'undefined'\n ? new URLSearchParams(window.location.search).get('token') ||\n new URLSearchParams(window.location.search).get('reset_token')\n : null;\n const client = authClient as unknown as {\n resetPassword?: (args: { newPassword: string; token: string }) => Promise<unknown>;\n };\n if (token && client.resetPassword) {\n try {\n const result = await client.resetPassword({ newPassword, token });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'Password update failed') };\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password update failed') };\n }\n }\n // TODO(neon-auth): wire changePassword once the UI can collect the current\n // password (Better Auth changePassword requires { newPassword, currentPassword }).\n return { data: null, error: NEON_NOT_SUPPORTED('Updating the password without a reset token') };\n }, [authClient]);\n\n // TODO(neon-auth): the user profile lives in the project's Neon\n // `public.user_profiles` table. Reading it requires the platform DB path\n // (useDatabase / DatabaseClient), which is provider-scoped and not available\n // here without threading a client in. We intentionally do NOT call Supabase on\n // the Neon path. Profile reads/writes no-op gracefully for now.\n const fetchProfile = useCallback(async (_userId: string): Promise<UserProfile | null> => {\n return null;\n }, []);\n\n const updateProfile = useCallback(async (_updates: Partial<UserProfile>): Promise<AuthResult> => {\n if (!user) return { data: null, error: new Error('Not authenticated') };\n return { data: null, error: NEON_NOT_SUPPORTED('Updating the profile') };\n }, [user]);\n\n const value: AuthContextType = {\n user,\n profile,\n session,\n loading,\n isConfigured: Boolean(authClient),\n signUp,\n signIn,\n signInWithProvider,\n signOut,\n resetPassword,\n updatePassword,\n updateProfile,\n refetchProfile: fetchProfile,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nfunction toError(error: unknown, fallback: string): Error {\n if (error instanceof Error) return error;\n if (error && typeof error === 'object') {\n const msg = (error as { message?: string; statusText?: string }).message\n || (error as { statusText?: string }).statusText;\n if (msg) return new Error(msg);\n }\n if (typeof error === 'string') return new Error(error);\n return new Error(fallback);\n}\n\n// ─── Supabase path (UNCHANGED behaviour) ─────────────────────────────────────\n\nfunction SupabaseAuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null);\n const [profile, setProfile] = useState<UserProfile | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState<boolean>(true);\n const previousUserIdRef = useRef<string | null>(null);\n\n const fetchProfile = useCallback(async (userId: string): Promise<UserProfile | null> => {\n if (!userId) return null;\n\n try {\n let query = supabase\n .from('user_profiles')\n .select('*')\n .eq('id', userId);\n\n if (env.EZC_PROJECT_ID) {\n query = query.eq('project_id', env.EZC_PROJECT_ID);\n }\n\n const result = await query.single();\n\n const { data, error } = result || { data: null, error: null };\n\n if (error) {\n return null;\n }\n\n setProfile(data as UserProfile);\n return data as UserProfile;\n } catch {\n return null;\n }\n }, []);\n\n // SEC-1: bind the end-user to THIS project server-side (authoritative; app_metadata\n // is service-role-only). OAuth users have no signup metadata so the migration-226\n // trigger can't bind them — this is what stops migration 227 from locking them out.\n // No-ops if already bound. Non-blocking.\n const bindProjectIfNeeded = useCallback(async (currentUser: User | null): Promise<void> => {\n if (!currentUser || !env.EZC_PROJECT_ID || !env.EZCODER_API_URL) return;\n const appMeta = currentUser.app_metadata as Record<string, unknown> | undefined;\n if (appMeta?.bound_project_id) return;\n try {\n const { data } = await supabase.auth.getSession();\n const token = data?.session?.access_token;\n if (!token) return;\n const res = await fetch(`${env.EZCODER_API_URL.replace(/\\/$/, '')}/api/managed-auth/bind`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(env.EZC_PROJECT_TOKEN_PUBLIC ? { Authorization: `Bearer ${env.EZC_PROJECT_TOKEN_PUBLIC}` } : {}),\n 'X-EZC-User-Token': token,\n },\n body: JSON.stringify({ projectId: env.EZC_PROJECT_ID }),\n });\n const j = await res.json().catch(() => ({}));\n if (j?.changed) {\n // The new bound_project_id claim only appears after a token refresh.\n await supabase.auth.refreshSession();\n }\n } catch {\n // non-blocking — login still works; binding reconciles on next load / via backfill\n }\n }, []);\n\n useEffect(() => {\n supabase.auth.getSession().then(async ({ data: { session: initialSession } }) => {\n setSession(initialSession);\n setUser(initialSession?.user ?? null);\n\n if (initialSession?.user) {\n await fetchProfile(initialSession.user.id);\n bindProjectIfNeeded(initialSession.user);\n }\n\n setLoading(false);\n });\n\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange(async (event, currentSession) => {\n setSession(currentSession);\n setUser(currentSession?.user ?? null);\n\n if (event === 'SIGNED_IN' && currentSession?.user) {\n await fetchProfile(currentSession.user.id);\n bindProjectIfNeeded(currentSession.user);\n ezcoderAuthIntegration.onLogin(currentSession.user);\n previousUserIdRef.current = currentSession.user.id;\n } else if (event === 'SIGNED_OUT') {\n setProfile(null);\n if (previousUserIdRef.current) {\n ezcoderAuthIntegration.onLogout(previousUserIdRef.current);\n previousUserIdRef.current = null;\n }\n } else if (event === 'USER_UPDATED' && currentSession?.user) {\n ezcoder.analytics.identify(currentSession.user.id, {\n email: currentSession.user.email,\n name: currentSession.user.user_metadata?.full_name,\n });\n }\n });\n\n // In-editor popup sign-in: the /auth/callback popup postMessages on completion;\n // the storage event is a same-origin fallback for the popup's localStorage write.\n const refreshFromExternal = () => {\n supabase.auth.getSession().then(({ data }) => {\n const s = data?.session ?? null;\n setSession(s);\n setUser(s?.user ?? null);\n if (s?.user) { fetchProfile(s.user.id); bindProjectIfNeeded(s.user); }\n });\n };\n const onMsg = (e: MessageEvent) => { if (e?.data?.type === 'ezc-auth-complete') refreshFromExternal(); };\n const onStorage = (e: StorageEvent) => { if (e.key && /auth-token/.test(e.key)) refreshFromExternal(); };\n if (typeof window !== 'undefined') {\n window.addEventListener('message', onMsg);\n window.addEventListener('storage', onStorage);\n }\n\n return () => {\n subscription.unsubscribe();\n if (typeof window !== 'undefined') {\n window.removeEventListener('message', onMsg);\n window.removeEventListener('storage', onStorage);\n }\n };\n }, [fetchProfile, bindProjectIfNeeded]);\n\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n const { metadata = {} } = options;\n\n try {\n const signUpMetadata = { ...metadata };\n if (env.EZC_PROJECT_ID) {\n signUpMetadata.project_id = env.EZC_PROJECT_ID;\n signUpMetadata.bound_project_id = env.EZC_PROJECT_ID;\n }\n\n const result = await supabase.auth.signUp({\n email,\n password,\n options: { data: signUpMetadata },\n });\n\n const { data, error } = result || { data: null, error: new Error('Sign up failed') };\n\n if (error) {\n return { data: null, error };\n }\n\n if (data?.user) {\n const profileData: Record<string, unknown> = {\n id: data.user.id,\n email,\n };\n if (metadata.display_name) {\n profileData.display_name = metadata.display_name;\n }\n if (env.EZC_PROJECT_ID) {\n profileData.project_id = env.EZC_PROJECT_ID;\n }\n if (metadata.display_name || env.EZC_PROJECT_ID) {\n await supabase.from('user_profiles').upsert(profileData);\n }\n try {\n await supabase.rpc('assign_default_role', { user_uuid: data.user.id });\n } catch {\n // Non-blocking — role tables may not exist in all projects\n }\n ezcoderAuthIntegration.onSignup(data.user);\n }\n\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\n }\n }, []);\n\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.signInWithPassword({ email, password });\n const { data, error } = result || { data: null, error: new Error('Sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\n }\n }, []);\n\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const provider2 = provider as 'google' | 'github' | 'facebook' | 'apple' | 'twitter';\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const framed = typeof window !== 'undefined' && window.self !== window.top;\n\n if (framed && typeof window !== 'undefined') {\n // Provider login pages refuse to render inside an iframe (X-Frame-Options /\n // frame-ancestors), so we cannot do a full-page redirect in the editor preview.\n // Open the flow in a popup; the /auth/callback page completes PKCE and\n // postMessages back (storage event is the fallback). Land on the callback route.\n const redirectTo = options.redirectTo || (origin ? `${origin}/auth/callback` : '');\n const result = await supabase.auth.signInWithOAuth({\n provider: provider2,\n options: { redirectTo, skipBrowserRedirect: true, ...options },\n });\n if (result?.error) return { data: null, error: result.error };\n const url = (result?.data as { url?: string } | null)?.url;\n if (url) window.open(url, 'ezc-auth', 'popup,width=500,height=680');\n return { data: result?.data ?? null, error: null };\n }\n\n // Standalone (deployed app / own tab): full-page redirect. Default to the app\n // origin (root) so apps without a scaffolded callback route still complete via\n // detectSessionInUrl; new apps pass /auth/callback explicitly.\n const result = await supabase.auth.signInWithOAuth({\n provider: provider2,\n options: {\n redirectTo: options.redirectTo || origin,\n ...options,\n },\n });\n const { data, error } = result || { data: null, error: new Error('OAuth sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\n }\n }, []);\n\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\n const userId = user?.id;\n try {\n const result = await supabase.auth.signOut();\n const { error } = result || { error: null };\n if (!error && userId) {\n ezcoder.users.trackLogout(userId);\n }\n return { error };\n } catch (err: unknown) {\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\n }\n }, [user]);\n\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\n try {\n const result = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo: `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`,\n });\n const { data, error } = result || { data: null, error: new Error('Password reset failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\n }\n }, []);\n\n // Set a new password. Used on the /auth/reset-password landing page, where the\n // recovery link has already established a (recovery) session via detectSessionInUrl.\n const updatePassword = useCallback(async (newPassword: string): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.updateUser({ password: newPassword });\n const { data, error } = result || { data: null, error: new Error('Password update failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password update failed') };\n }\n }, []);\n\n const updateProfile = useCallback(\n async (updates: Partial<UserProfile>): Promise<AuthResult> => {\n if (!user) {\n return { data: null, error: new Error('Not authenticated') };\n }\n try {\n let query = supabase\n .from('user_profiles')\n .update(updates)\n .eq('id', user.id);\n\n if (env.EZC_PROJECT_ID) {\n query = query.eq('project_id', env.EZC_PROJECT_ID);\n }\n\n const result = await query.select().single();\n const { data, error } = result || { data: null, error: null };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Update failed') };\n }\n },\n [user]\n );\n\n const value: AuthContextType = {\n user,\n profile,\n session,\n loading,\n isConfigured: isSupabaseConfigured,\n signUp,\n signIn,\n signInWithProvider,\n signOut,\n resetPassword,\n updatePassword,\n updateProfile,\n refetchProfile: fetchProfile,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nexport function useAuth(): AuthContextType {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport type { AuthResult, SignUpOptions, SignInWithProviderOptions };\n"],"mappings":"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","names":["result","error","data"]}
|
|
@@ -54,7 +54,18 @@ var env = {
|
|
|
54
54
|
S3_BUCKET: getEnv("VITE_S3_BUCKET", "S3_BUCKET"),
|
|
55
55
|
CLOUDINARY_URL: getEnv("VITE_CLOUDINARY_URL", "CLOUDINARY_URL"),
|
|
56
56
|
STORAGE_BUCKET_PUBLIC: getEnv("VITE_STORAGE_BUCKET_PUBLIC", "NEXT_PUBLIC_STORAGE_BUCKET_PUBLIC"),
|
|
57
|
-
STORAGE_BUCKET_PRIVATE: getEnv("VITE_STORAGE_BUCKET_PRIVATE", "NEXT_PUBLIC_STORAGE_BUCKET_PRIVATE")
|
|
57
|
+
STORAGE_BUCKET_PRIVATE: getEnv("VITE_STORAGE_BUCKET_PRIVATE", "NEXT_PUBLIC_STORAGE_BUCKET_PRIVATE"),
|
|
58
|
+
// When true, social login in the Neon Auth path is handled via the central
|
|
59
|
+
// EzCoder auth proxy instead of calling the per-project Better Auth server
|
|
60
|
+
// directly. The proxy redirects back to <app>/auth/callback#code=<singleUse>;
|
|
61
|
+
// AuthCallback exchanges the code for an ephemeral credential, calls
|
|
62
|
+
// authClient.signIn.email directly (so Neon sets the native session cookie),
|
|
63
|
+
// then rotates the password to kill the exposed credential.
|
|
64
|
+
// Set VITE_APP_AUTH_PROXY=1 (Vite) or NEXT_PUBLIC_APP_AUTH_PROXY=1 (Next).
|
|
65
|
+
APP_AUTH_PROXY: (() => {
|
|
66
|
+
const v = getEnv("VITE_APP_AUTH_PROXY", "NEXT_PUBLIC_APP_AUTH_PROXY");
|
|
67
|
+
return v === "1" || v === "true";
|
|
68
|
+
})()
|
|
58
69
|
};
|
|
59
70
|
var isNeonAuthConfigured = Boolean(env.NEON_AUTH_URL);
|
|
60
71
|
var features = {
|
|
@@ -78,4 +89,4 @@ export {
|
|
|
78
89
|
features,
|
|
79
90
|
isFeatureConfigured
|
|
80
91
|
};
|
|
81
|
-
//# sourceMappingURL=chunk-
|
|
92
|
+
//# sourceMappingURL=chunk-KWR4PA5I.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts"],"sourcesContent":["const getEnv = (viteKey: string, nextKey?: string): string => {\r\n try {\r\n if (typeof import.meta !== 'undefined' && import.meta.env) {\r\n return (import.meta.env[viteKey] as string) || '';\r\n }\r\n } catch {\r\n // import.meta not available\r\n }\r\n try {\r\n if (typeof process !== 'undefined' && process.env) {\r\n return process.env[nextKey || viteKey] || '';\r\n }\r\n } catch {\r\n // process not available\r\n }\r\n return '';\r\n};\r\n\r\nexport const env = {\r\n SUPABASE_URL: getEnv('VITE_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_URL'),\r\n SUPABASE_ANON_KEY: getEnv('VITE_SUPABASE_ANON_KEY', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'),\r\n EZCODER_AUTH_URL: getEnv('VITE_EZCODER_AUTH_URL', 'NEXT_PUBLIC_EZCODER_AUTH_URL'),\r\n EZCODER_AUTH_ANON_KEY: getEnv('VITE_EZCODER_AUTH_ANON_KEY', 'NEXT_PUBLIC_EZCODER_AUTH_ANON_KEY'),\r\n // Per-project Neon Auth (Better Auth) server base URL. When present, the app\r\n // authenticates against its OWN isolated Neon Auth server (e.g.\r\n // https://ep-xxx.neonauth.<region>.aws.neon.tech/neondb/auth) instead of the\r\n // shared tenant Supabase. Injected at provision time as VITE_NEON_AUTH_URL;\r\n // NEON_AUTH_BASE_URL is the server/Next fallback name. Presence of this value\r\n // is the sole trigger for the Better Auth code path in AuthProvider.\r\n NEON_AUTH_URL: getEnv('VITE_NEON_AUTH_URL', 'NEON_AUTH_BASE_URL'),\r\n STRIPE_PUBLISHABLE_KEY: getEnv('VITE_STRIPE_PUBLISHABLE_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'),\r\n EZC_PROJECT_ID: getEnv('VITE_EZC_PROJECT_ID', 'NEXT_PUBLIC_EZC_PROJECT_ID'),\r\n EZCODER_API_URL: getEnv('VITE_EZCODER_API_URL', 'NEXT_PUBLIC_EZCODER_API_URL'),\r\n // Server-only secret for Stripe + authenticated platform API calls. Deployment\r\n // injects this as `EZCODER_SECRET_KEY` (see lib/deployment/fetch-project-env-vars.js);\r\n // resolve that name first, then fall back to the legacy `EZC_SECRET_KEY` so older\r\n // deploys keep working. Both are non-VITE/non-NEXT_PUBLIC (never exposed to the browser).\r\n EZC_SECRET_KEY: getEnv('EZCODER_SECRET_KEY', 'EZCODER_SECRET_KEY') || getEnv('EZC_SECRET_KEY', 'EZC_SECRET_KEY'),\r\n // B1: two-class project token model.\r\n //\r\n // EZC_PROJECT_TOKEN_PUBLIC — browser-safe. Read-only endpoints (manifest,\r\n // list, etc). Available in both server and\r\n // browser bundles via NEXT_PUBLIC_/VITE_\r\n // prefixes.\r\n // EZC_PROJECT_TOKEN_SERVER — server-only. Authenticates write APIs\r\n // (email send, cron register, notifications\r\n // send). NEVER prefixed with NEXT_PUBLIC_ or\r\n // VITE_; accessing it from a browser bundle\r\n // returns '' and the calling SDK function\r\n // must error out with a clear message.\r\n EZC_PROJECT_TOKEN_PUBLIC: getEnv('VITE_EZC_PROJECT_TOKEN_PUBLIC', 'NEXT_PUBLIC_EZC_PROJECT_TOKEN_PUBLIC'),\r\n EZC_PROJECT_TOKEN_SERVER: getEnv('EZC_PROJECT_TOKEN_SERVER', 'EZC_PROJECT_TOKEN_SERVER'),\r\n // Legacy single-class token. Deprecated, kept for backwards compat during\r\n // Phase 1 of the rollout. New code MUST use the split pair above.\r\n EZC_PROJECT_TOKEN_LEGACY: getEnv('VITE_EZC_PROJECT_TOKEN', 'NEXT_PUBLIC_EZC_PROJECT_TOKEN'),\r\n S3_BUCKET: getEnv('VITE_S3_BUCKET', 'S3_BUCKET'),\r\n CLOUDINARY_URL: getEnv('VITE_CLOUDINARY_URL', 'CLOUDINARY_URL'),\r\n STORAGE_BUCKET_PUBLIC: getEnv('VITE_STORAGE_BUCKET_PUBLIC', 'NEXT_PUBLIC_STORAGE_BUCKET_PUBLIC'),\r\n STORAGE_BUCKET_PRIVATE: getEnv('VITE_STORAGE_BUCKET_PRIVATE', 'NEXT_PUBLIC_STORAGE_BUCKET_PRIVATE'),\r\n};\r\n\r\n// True when the project ships its own per-project Neon Auth (Better Auth)\r\n// server. This is authoritative for which auth backend AuthProvider uses.\r\nexport const isNeonAuthConfigured: boolean = Boolean(env.NEON_AUTH_URL);\r\n\r\nexport const features = {\r\n auth: Boolean(\r\n isNeonAuthConfigured ||\r\n (env.SUPABASE_URL && env.SUPABASE_ANON_KEY) ||\r\n (env.EZCODER_AUTH_URL && env.EZCODER_AUTH_ANON_KEY)\r\n ),\r\n payments: Boolean(env.STRIPE_PUBLISHABLE_KEY),\r\n analytics: Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID),\r\n storage: Boolean(env.SUPABASE_URL || env.EZCODER_AUTH_URL || env.S3_BUCKET || env.CLOUDINARY_URL),\r\n database: Boolean(\r\n (env.EZCODER_AUTH_URL || env.SUPABASE_URL) && env.EZC_PROJECT_ID\r\n ),\r\n};\r\n\r\nexport function isFeatureConfigured(feature: keyof typeof features): boolean {\r\n return features[feature];\r\n}\r\n"],"mappings":";AAAA,IAAM,SAAS,CAAC,SAAiB,YAA6B;AAC5D,MAAI;AACF,QAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,aAAQ,YAAY,IAAI,OAAO,KAAgB;AAAA,IACjD;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI;AACF,QAAI,OAAO,YAAY,eAAe,QAAQ,KAAK;AACjD,aAAO,QAAQ,IAAI,WAAW,OAAO,KAAK;AAAA,IAC5C;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,IAAM,MAAM;AAAA,EACjB,cAAc,OAAO,qBAAqB,0BAA0B;AAAA,EACpE,mBAAmB,OAAO,0BAA0B,+BAA+B;AAAA,EACnF,kBAAkB,OAAO,yBAAyB,8BAA8B;AAAA,EAChF,uBAAuB,OAAO,8BAA8B,mCAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/F,eAAe,OAAO,sBAAsB,oBAAoB;AAAA,EAChE,wBAAwB,OAAO,+BAA+B,oCAAoC;AAAA,EAClG,gBAAgB,OAAO,uBAAuB,4BAA4B;AAAA,EAC1E,iBAAiB,OAAO,wBAAwB,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7E,gBAAgB,OAAO,sBAAsB,oBAAoB,KAAK,OAAO,kBAAkB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa/G,0BAA0B,OAAO,iCAAiC,sCAAsC;AAAA,EACxG,0BAA0B,OAAO,4BAA4B,0BAA0B;AAAA;AAAA;AAAA,EAGvF,0BAA0B,OAAO,0BAA0B,+BAA+B;AAAA,EAC1F,WAAW,OAAO,kBAAkB,WAAW;AAAA,EAC/C,gBAAgB,OAAO,uBAAuB,gBAAgB;AAAA,EAC9D,uBAAuB,OAAO,8BAA8B,mCAAmC;AAAA,EAC/F,wBAAwB,OAAO,+BAA+B,oCAAoC;
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts"],"sourcesContent":["const getEnv = (viteKey: string, nextKey?: string): string => {\r\n try {\r\n if (typeof import.meta !== 'undefined' && import.meta.env) {\r\n return (import.meta.env[viteKey] as string) || '';\r\n }\r\n } catch {\r\n // import.meta not available\r\n }\r\n try {\r\n if (typeof process !== 'undefined' && process.env) {\r\n return process.env[nextKey || viteKey] || '';\r\n }\r\n } catch {\r\n // process not available\r\n }\r\n return '';\r\n};\r\n\r\nexport const env = {\r\n SUPABASE_URL: getEnv('VITE_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_URL'),\r\n SUPABASE_ANON_KEY: getEnv('VITE_SUPABASE_ANON_KEY', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'),\r\n EZCODER_AUTH_URL: getEnv('VITE_EZCODER_AUTH_URL', 'NEXT_PUBLIC_EZCODER_AUTH_URL'),\r\n EZCODER_AUTH_ANON_KEY: getEnv('VITE_EZCODER_AUTH_ANON_KEY', 'NEXT_PUBLIC_EZCODER_AUTH_ANON_KEY'),\r\n // Per-project Neon Auth (Better Auth) server base URL. When present, the app\r\n // authenticates against its OWN isolated Neon Auth server (e.g.\r\n // https://ep-xxx.neonauth.<region>.aws.neon.tech/neondb/auth) instead of the\r\n // shared tenant Supabase. Injected at provision time as VITE_NEON_AUTH_URL;\r\n // NEON_AUTH_BASE_URL is the server/Next fallback name. Presence of this value\r\n // is the sole trigger for the Better Auth code path in AuthProvider.\r\n NEON_AUTH_URL: getEnv('VITE_NEON_AUTH_URL', 'NEON_AUTH_BASE_URL'),\r\n STRIPE_PUBLISHABLE_KEY: getEnv('VITE_STRIPE_PUBLISHABLE_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'),\r\n EZC_PROJECT_ID: getEnv('VITE_EZC_PROJECT_ID', 'NEXT_PUBLIC_EZC_PROJECT_ID'),\r\n EZCODER_API_URL: getEnv('VITE_EZCODER_API_URL', 'NEXT_PUBLIC_EZCODER_API_URL'),\r\n // Server-only secret for Stripe + authenticated platform API calls. Deployment\r\n // injects this as `EZCODER_SECRET_KEY` (see lib/deployment/fetch-project-env-vars.js);\r\n // resolve that name first, then fall back to the legacy `EZC_SECRET_KEY` so older\r\n // deploys keep working. Both are non-VITE/non-NEXT_PUBLIC (never exposed to the browser).\r\n EZC_SECRET_KEY: getEnv('EZCODER_SECRET_KEY', 'EZCODER_SECRET_KEY') || getEnv('EZC_SECRET_KEY', 'EZC_SECRET_KEY'),\r\n // B1: two-class project token model.\r\n //\r\n // EZC_PROJECT_TOKEN_PUBLIC — browser-safe. Read-only endpoints (manifest,\r\n // list, etc). Available in both server and\r\n // browser bundles via NEXT_PUBLIC_/VITE_\r\n // prefixes.\r\n // EZC_PROJECT_TOKEN_SERVER — server-only. Authenticates write APIs\r\n // (email send, cron register, notifications\r\n // send). NEVER prefixed with NEXT_PUBLIC_ or\r\n // VITE_; accessing it from a browser bundle\r\n // returns '' and the calling SDK function\r\n // must error out with a clear message.\r\n EZC_PROJECT_TOKEN_PUBLIC: getEnv('VITE_EZC_PROJECT_TOKEN_PUBLIC', 'NEXT_PUBLIC_EZC_PROJECT_TOKEN_PUBLIC'),\r\n EZC_PROJECT_TOKEN_SERVER: getEnv('EZC_PROJECT_TOKEN_SERVER', 'EZC_PROJECT_TOKEN_SERVER'),\r\n // Legacy single-class token. Deprecated, kept for backwards compat during\r\n // Phase 1 of the rollout. New code MUST use the split pair above.\r\n EZC_PROJECT_TOKEN_LEGACY: getEnv('VITE_EZC_PROJECT_TOKEN', 'NEXT_PUBLIC_EZC_PROJECT_TOKEN'),\r\n S3_BUCKET: getEnv('VITE_S3_BUCKET', 'S3_BUCKET'),\r\n CLOUDINARY_URL: getEnv('VITE_CLOUDINARY_URL', 'CLOUDINARY_URL'),\r\n STORAGE_BUCKET_PUBLIC: getEnv('VITE_STORAGE_BUCKET_PUBLIC', 'NEXT_PUBLIC_STORAGE_BUCKET_PUBLIC'),\r\n STORAGE_BUCKET_PRIVATE: getEnv('VITE_STORAGE_BUCKET_PRIVATE', 'NEXT_PUBLIC_STORAGE_BUCKET_PRIVATE'),\r\n // When true, social login in the Neon Auth path is handled via the central\r\n // EzCoder auth proxy instead of calling the per-project Better Auth server\r\n // directly. The proxy redirects back to <app>/auth/callback#code=<singleUse>;\r\n // AuthCallback exchanges the code for an ephemeral credential, calls\r\n // authClient.signIn.email directly (so Neon sets the native session cookie),\r\n // then rotates the password to kill the exposed credential.\r\n // Set VITE_APP_AUTH_PROXY=1 (Vite) or NEXT_PUBLIC_APP_AUTH_PROXY=1 (Next).\r\n APP_AUTH_PROXY: ((): boolean => {\r\n const v = getEnv('VITE_APP_AUTH_PROXY', 'NEXT_PUBLIC_APP_AUTH_PROXY');\r\n return v === '1' || v === 'true';\r\n })(),\r\n};\r\n\r\n// True when the project ships its own per-project Neon Auth (Better Auth)\r\n// server. This is authoritative for which auth backend AuthProvider uses.\r\nexport const isNeonAuthConfigured: boolean = Boolean(env.NEON_AUTH_URL);\r\n\r\nexport const features = {\r\n auth: Boolean(\r\n isNeonAuthConfigured ||\r\n (env.SUPABASE_URL && env.SUPABASE_ANON_KEY) ||\r\n (env.EZCODER_AUTH_URL && env.EZCODER_AUTH_ANON_KEY)\r\n ),\r\n payments: Boolean(env.STRIPE_PUBLISHABLE_KEY),\r\n analytics: Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID),\r\n storage: Boolean(env.SUPABASE_URL || env.EZCODER_AUTH_URL || env.S3_BUCKET || env.CLOUDINARY_URL),\r\n database: Boolean(\r\n (env.EZCODER_AUTH_URL || env.SUPABASE_URL) && env.EZC_PROJECT_ID\r\n ),\r\n};\r\n\r\nexport function isFeatureConfigured(feature: keyof typeof features): boolean {\r\n return features[feature];\r\n}\r\n"],"mappings":";AAAA,IAAM,SAAS,CAAC,SAAiB,YAA6B;AAC5D,MAAI;AACF,QAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,aAAQ,YAAY,IAAI,OAAO,KAAgB;AAAA,IACjD;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI;AACF,QAAI,OAAO,YAAY,eAAe,QAAQ,KAAK;AACjD,aAAO,QAAQ,IAAI,WAAW,OAAO,KAAK;AAAA,IAC5C;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,IAAM,MAAM;AAAA,EACjB,cAAc,OAAO,qBAAqB,0BAA0B;AAAA,EACpE,mBAAmB,OAAO,0BAA0B,+BAA+B;AAAA,EACnF,kBAAkB,OAAO,yBAAyB,8BAA8B;AAAA,EAChF,uBAAuB,OAAO,8BAA8B,mCAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/F,eAAe,OAAO,sBAAsB,oBAAoB;AAAA,EAChE,wBAAwB,OAAO,+BAA+B,oCAAoC;AAAA,EAClG,gBAAgB,OAAO,uBAAuB,4BAA4B;AAAA,EAC1E,iBAAiB,OAAO,wBAAwB,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7E,gBAAgB,OAAO,sBAAsB,oBAAoB,KAAK,OAAO,kBAAkB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa/G,0BAA0B,OAAO,iCAAiC,sCAAsC;AAAA,EACxG,0BAA0B,OAAO,4BAA4B,0BAA0B;AAAA;AAAA;AAAA,EAGvF,0BAA0B,OAAO,0BAA0B,+BAA+B;AAAA,EAC1F,WAAW,OAAO,kBAAkB,WAAW;AAAA,EAC/C,gBAAgB,OAAO,uBAAuB,gBAAgB;AAAA,EAC9D,uBAAuB,OAAO,8BAA8B,mCAAmC;AAAA,EAC/F,wBAAwB,OAAO,+BAA+B,oCAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlG,iBAAiB,MAAe;AAC9B,UAAM,IAAI,OAAO,uBAAuB,4BAA4B;AACpE,WAAO,MAAM,OAAO,MAAM;AAAA,EAC5B,GAAG;AACL;AAIO,IAAM,uBAAgC,QAAQ,IAAI,aAAa;AAE/D,IAAM,WAAW;AAAA,EACtB,MAAM;AAAA,IACJ,wBACC,IAAI,gBAAgB,IAAI,qBACxB,IAAI,oBAAoB,IAAI;AAAA,EAC/B;AAAA,EACA,UAAU,QAAQ,IAAI,sBAAsB;AAAA,EAC5C,WAAW,QAAQ,IAAI,mBAAmB,IAAI,cAAc;AAAA,EAC5D,SAAS,QAAQ,IAAI,gBAAgB,IAAI,oBAAoB,IAAI,aAAa,IAAI,cAAc;AAAA,EAChG,UAAU;AAAA,KACP,IAAI,oBAAoB,IAAI,iBAAiB,IAAI;AAAA,EACpD;AACF;AAEO,SAAS,oBAAoB,SAAyC;AAC3E,SAAO,SAAS,OAAO;AACzB;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KWR4PA5I.js";
|
|
4
4
|
|
|
5
5
|
// src/core/platform.ts
|
|
6
6
|
var isConfigured = () => Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID);
|
|
@@ -386,4 +386,4 @@ export {
|
|
|
386
386
|
ezcoder,
|
|
387
387
|
ezcoderAuthIntegration
|
|
388
388
|
};
|
|
389
|
-
//# sourceMappingURL=chunk-
|
|
389
|
+
//# sourceMappingURL=chunk-OIAKVQGD.js.map
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ezcoder
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OIAKVQGD.js";
|
|
4
4
|
import {
|
|
5
5
|
isSupabaseConfigured,
|
|
6
6
|
supabase
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FPSSXTQG.js";
|
|
8
8
|
import {
|
|
9
9
|
env,
|
|
10
10
|
features
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-KWR4PA5I.js";
|
|
12
12
|
|
|
13
13
|
// src/database/DatabaseProvider.tsx
|
|
14
14
|
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
@@ -623,4 +623,4 @@ export {
|
|
|
623
623
|
useIsDatabaseConfigured,
|
|
624
624
|
useRealtime
|
|
625
625
|
};
|
|
626
|
-
//# sourceMappingURL=chunk-
|
|
626
|
+
//# sourceMappingURL=chunk-RU2GHN7O.js.map
|
package/dist/cms/index.js
CHANGED
package/dist/cron/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveServerToken
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-FFMYVTI2.js";
|
|
4
4
|
import {
|
|
5
5
|
env
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-KWR4PA5I.js";
|
|
7
7
|
|
|
8
8
|
// src/cron/registerJob.ts
|
|
9
9
|
async function registerCronJob(name, cronExpression, endpointUrl, options = {}) {
|
package/dist/database/index.js
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
useDatabaseOptional,
|
|
12
12
|
useIsDatabaseConfigured,
|
|
13
13
|
useRealtime
|
|
14
|
-
} from "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-RU2GHN7O.js";
|
|
15
|
+
import "../chunk-OIAKVQGD.js";
|
|
16
|
+
import "../chunk-FPSSXTQG.js";
|
|
17
|
+
import "../chunk-KWR4PA5I.js";
|
|
18
18
|
export {
|
|
19
19
|
ConnectionError,
|
|
20
20
|
DatabaseClient,
|
package/dist/email/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveServerToken
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-FFMYVTI2.js";
|
|
4
4
|
import {
|
|
5
5
|
env
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-KWR4PA5I.js";
|
|
7
7
|
|
|
8
8
|
// src/email/sendEmail.ts
|
|
9
9
|
async function sendEmail(to, subject, html, options = {}) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { e as env, f as features, i as isFeatureConfigured, a as isNeonAuthConfigured } from './config-
|
|
1
|
+
export { e as env, f as features, i as isFeatureConfigured, a as isNeonAuthConfigured } from './config-Cb4MMhGa.js';
|
|
2
2
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
3
|
import { E as EzcoderClient, A as AuthIntegration } from './types-1uP3V_pe.js';
|
|
4
4
|
export { a as AnalyticsResult, b as AuthUser, C as CheckoutOptions, S as StorageFile, c as StorageResult, d as SubscriptionStatus, e as SubscriptionTier, U as UserProfile } from './types-1uP3V_pe.js';
|
package/dist/index.js
CHANGED
|
@@ -5,21 +5,21 @@ import {
|
|
|
5
5
|
getRuntimeConfig,
|
|
6
6
|
loadBootstrap,
|
|
7
7
|
useDatabase
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RU2GHN7O.js";
|
|
9
9
|
import {
|
|
10
10
|
ezcoder,
|
|
11
11
|
ezcoderAuthIntegration
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OIAKVQGD.js";
|
|
13
13
|
import {
|
|
14
14
|
isSupabaseConfigured,
|
|
15
15
|
supabase
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-FPSSXTQG.js";
|
|
17
17
|
import {
|
|
18
18
|
env,
|
|
19
19
|
features,
|
|
20
20
|
isFeatureConfigured,
|
|
21
21
|
isNeonAuthConfigured
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-KWR4PA5I.js";
|
|
23
23
|
|
|
24
24
|
// src/manifest-consumer.ts
|
|
25
25
|
var manifestCache = /* @__PURE__ */ new Map();
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveServerToken
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-FFMYVTI2.js";
|
|
4
4
|
import {
|
|
5
5
|
AuthContext
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-HX7IFB7C.js";
|
|
7
|
+
import "../chunk-OIAKVQGD.js";
|
|
8
8
|
import {
|
|
9
9
|
supabase
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-FPSSXTQG.js";
|
|
11
11
|
import {
|
|
12
12
|
env,
|
|
13
13
|
features
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-KWR4PA5I.js";
|
|
15
15
|
|
|
16
16
|
// src/notifications/useNotifications.ts
|
|
17
17
|
import { useState, useEffect, useCallback, useContext } from "react";
|
package/dist/payments/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-HX7IFB7C.js";
|
|
4
4
|
import {
|
|
5
5
|
ezcoder
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-OIAKVQGD.js";
|
|
7
7
|
import {
|
|
8
8
|
supabase
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-FPSSXTQG.js";
|
|
10
10
|
import {
|
|
11
11
|
features
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-KWR4PA5I.js";
|
|
13
13
|
|
|
14
14
|
// src/payments/useSubscription.ts
|
|
15
15
|
import { useState, useEffect, useCallback, useContext } from "react";
|
package/dist/roles/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-HX7IFB7C.js";
|
|
4
|
+
import "../chunk-OIAKVQGD.js";
|
|
5
5
|
import {
|
|
6
6
|
supabase
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-FPSSXTQG.js";
|
|
8
8
|
import {
|
|
9
9
|
features
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-KWR4PA5I.js";
|
|
11
11
|
|
|
12
12
|
// src/roles/useRoles.ts
|
|
13
13
|
import { useState, useEffect, useCallback, useContext } from "react";
|
package/dist/storage/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-HX7IFB7C.js";
|
|
4
|
+
import "../chunk-OIAKVQGD.js";
|
|
5
5
|
import {
|
|
6
6
|
supabase
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-FPSSXTQG.js";
|
|
8
8
|
import {
|
|
9
9
|
env,
|
|
10
10
|
features
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-KWR4PA5I.js";
|
|
12
12
|
|
|
13
13
|
// src/storage/useStorage.ts
|
|
14
14
|
import { useState, useCallback, useContext } from "react";
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/neonAuthClient.ts","../src/auth/AuthProvider.tsx"],"sourcesContent":["import { createAuthClient } from 'better-auth/react';\nimport { env, isNeonAuthConfigured } from '../core/config';\n\n/**\n * Per-project Neon Auth (Better Auth) client.\n *\n * A project uses Neon Auth when `env.NEON_AUTH_URL` (the per-project Better Auth\n * `base_url`, e.g. `https://ep-xxx.neonauth.<region>.aws.neon.tech/neondb/auth`)\n * is injected as `VITE_NEON_AUTH_URL`. When present, the SDK authenticates the\n * generated app against its OWN isolated Neon Auth server rather than the shared\n * tenant Supabase.\n *\n * The client is created lazily so that:\n * - non-Neon projects never instantiate it (zero behavioural change), and\n * - SSR/build passes that import the SDK without a base URL don't throw.\n *\n * This is the official Better Auth React client (`createAuthClient` from\n * `better-auth/react`). It owns token storage and cross-origin session handling;\n * do NOT hand-roll fetch against the Better Auth endpoints.\n */\nexport type NeonAuthClient = ReturnType<typeof createAuthClient>;\n\nlet cachedClient: NeonAuthClient | null = null;\n\n/**\n * Returns the lazily-created Better Auth client, or `null` when Neon Auth is not\n * configured for this project. Callers on the Neon path should treat a `null`\n * return as \"not configured\" and surface a clear error.\n */\nexport function getNeonAuthClient(): NeonAuthClient | null {\n if (!isNeonAuthConfigured || !env.NEON_AUTH_URL) {\n return null;\n }\n if (!cachedClient) {\n cachedClient = createAuthClient({\n baseURL: env.NEON_AUTH_URL,\n });\n }\n return cachedClient;\n}\n\n/** True when this project ships its own per-project Neon Auth server. */\nexport { isNeonAuthConfigured };\n","import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { User, Session } from '@supabase/supabase-js';\nimport { supabase, isSupabaseConfigured } from '../core/supabase';\nimport { env, isNeonAuthConfigured } from '../core/config';\nimport { ezcoder, ezcoderAuthIntegration } from '../core/platform';\nimport { getNeonAuthClient } from './neonAuthClient';\nimport type { UserProfile } from '../core/types';\n\ninterface AuthResult<T = unknown> {\n data: T | null;\n error: Error | null;\n}\n\ninterface SignUpOptions {\n metadata?: Record<string, unknown>;\n}\n\ninterface SignInWithProviderOptions {\n redirectTo?: string;\n [key: string]: unknown;\n}\n\nexport interface AuthContextType {\n user: User | null;\n profile: UserProfile | null;\n session: Session | null;\n loading: boolean;\n isConfigured: boolean;\n signUp: (email: string, password: string, options?: SignUpOptions) => Promise<AuthResult>;\n signIn: (email: string, password: string) => Promise<AuthResult>;\n signInWithProvider: (provider: string, options?: SignInWithProviderOptions) => Promise<AuthResult>;\n signOut: () => Promise<{ error: Error | null }>;\n resetPassword: (email: string) => Promise<AuthResult>;\n updatePassword: (newPassword: string) => Promise<AuthResult>;\n updateProfile: (updates: Partial<UserProfile>) => Promise<AuthResult>;\n refetchProfile: (userId: string) => Promise<UserProfile | null>;\n}\n\nconst NOT_CONFIGURED_MSG = 'Authentication is not configured. Ensure EzCoder platform credentials are injected, or connect your own Supabase database in Settings → Databases.';\nfunction notConfiguredError() {\n return new Error(NOT_CONFIGURED_MSG);\n}\n\nexport const AuthContext = createContext<AuthContextType>({\n user: null,\n profile: null,\n session: null,\n loading: true,\n isConfigured: false,\n signUp: async () => ({ data: null, error: null }),\n signIn: async () => ({ data: null, error: null }),\n signInWithProvider: async () => ({ data: null, error: null }),\n signOut: async () => ({ error: null }),\n resetPassword: async () => ({ data: null, error: null }),\n updatePassword: async () => ({ data: null, error: null }),\n updateProfile: async () => ({ data: null, error: null }),\n refetchProfile: async () => null,\n});\n\n// ─── Path selector ──────────────────────────────────────────────────────────\n//\n// A project authenticates against its OWN per-project Neon Auth (Better Auth)\n// server when `VITE_NEON_AUTH_URL` is injected. Otherwise it falls back to the\n// existing shared-tenant Supabase path, which is behaviour-preserved verbatim\n// below in `SupabaseAuthProvider`.\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n if (isNeonAuthConfigured) {\n return <NeonAuthProvider>{children}</NeonAuthProvider>;\n }\n return <SupabaseAuthProvider>{children}</SupabaseAuthProvider>;\n}\n\n// ─── Neon Auth (Better Auth) path ────────────────────────────────────────────\n\n// The Better Auth user shape (subset we rely on). The full object also carries\n// emailVerified, image, role, banned, createdAt, updatedAt, etc.\ninterface BetterAuthUser {\n id?: string;\n email?: string;\n name?: string;\n image?: string | null;\n emailVerified?: boolean;\n role?: string;\n createdAt?: string;\n updatedAt?: string;\n [key: string]: unknown;\n}\n\n/**\n * Normalize a Better Auth user into the SDK's `user` shape. The context type\n * declares `User` (Supabase) for backwards compatibility, so we project the\n * Better Auth fields onto a Supabase-User-compatible object: `id`, `email`, and\n * a `user_metadata` carrying the display name + avatar. Consumers that read\n * `user.id`, `user.email`, or `user.user_metadata.full_name` keep working.\n */\nfunction mapNeonUser(u: BetterAuthUser | null | undefined): User | null {\n if (!u || !u.id) return null;\n const nowIso = new Date().toISOString();\n return {\n id: u.id,\n email: u.email,\n app_metadata: { provider: 'neon-auth', ...(u.role ? { role: u.role } : {}) },\n user_metadata: {\n full_name: u.name,\n name: u.name,\n avatar_url: u.image ?? undefined,\n email_verified: u.emailVerified,\n },\n aud: 'authenticated',\n created_at: u.createdAt || nowIso,\n updated_at: u.updatedAt || nowIso,\n role: u.role,\n } as unknown as User;\n}\n\n/**\n * Project the Better Auth session payload onto the SDK's `session` shape. Better\n * Auth manages the real token + cookie internally; this object exists only so\n * consumers reading `session.user` / truthiness keep working. The bearer token\n * (when exposed by useSession) is surfaced as `access_token` best-effort.\n */\nfunction mapNeonSession(rawSession: unknown, user: User | null): Session | null {\n if (!user) return null;\n const s = (rawSession || {}) as Record<string, unknown>;\n const token =\n (s.token as string | undefined) ||\n ((s.session as Record<string, unknown> | undefined)?.token as string | undefined) ||\n '';\n return {\n access_token: token,\n refresh_token: '',\n token_type: 'bearer',\n expires_in: 0,\n expires_at: undefined,\n user,\n } as unknown as Session;\n}\n\nconst NEON_NOT_SUPPORTED = (feature: string) =>\n new Error(`${feature} is not supported on the Neon Auth path yet.`);\n\nfunction NeonAuthProvider({ children }: { children: React.ReactNode }) {\n const authClient = getNeonAuthClient();\n const [user, setUser] = useState<User | null>(null);\n const [profile, setProfile] = useState<UserProfile | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState<boolean>(true);\n const previousUserIdRef = useRef<string | null>(null);\n\n // Drive user/session/loading off Better Auth's reactive session hook. The hook\n // is stable across renders and re-renders the provider on auth state changes.\n const sessionState = authClient?.useSession?.() as\n | { data?: { user?: BetterAuthUser; session?: unknown } | null; isPending?: boolean }\n | undefined;\n\n const rawUser = sessionState?.data?.user ?? null;\n const isPending = sessionState?.isPending ?? false;\n\n useEffect(() => {\n const mappedUser = mapNeonUser(rawUser);\n setUser(mappedUser);\n setSession(mapNeonSession(sessionState?.data?.session ?? sessionState?.data ?? null, mappedUser));\n setLoading(Boolean(isPending));\n\n // Fire login/logout analytics on transitions, mirroring the Supabase path.\n const currentId = mappedUser?.id ?? null;\n const prevId = previousUserIdRef.current;\n if (currentId && currentId !== prevId) {\n ezcoderAuthIntegration.onLogin(mappedUser as unknown as { id: string; email?: string });\n previousUserIdRef.current = currentId;\n } else if (!currentId && prevId) {\n ezcoderAuthIntegration.onLogout(prevId);\n previousUserIdRef.current = null;\n setProfile(null);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rawUser, isPending]);\n\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n const { metadata = {} } = options;\n const name = (metadata.display_name as string | undefined) || (metadata.name as string | undefined) || email;\n try {\n const result = await authClient.signUp.email({ email, password, name });\n const error = (result as { error?: unknown })?.error;\n if (error) {\n return { data: null, error: toError(error, 'Sign up failed') };\n }\n const data = (result as { data?: unknown })?.data ?? result;\n const newUser = (data as { user?: BetterAuthUser })?.user;\n if (newUser?.id) {\n ezcoderAuthIntegration.onSignup({ id: newUser.id, email: newUser.email });\n }\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\n }\n }, [authClient]);\n\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n try {\n const result = await authClient.signIn.email({ email, password });\n const error = (result as { error?: unknown })?.error;\n if (error) {\n return { data: null, error: toError(error, 'Sign in failed') };\n }\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\n }\n }, [authClient]);\n\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n try {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const callbackURL = options.redirectTo || origin;\n const framed = typeof window !== 'undefined' && window.self !== window.top;\n const social = provider as 'google' | 'github';\n\n if (framed && typeof window !== 'undefined') {\n // Provider login pages refuse to render inside an iframe (X-Frame-Options /\n // frame-ancestors). Ask Better Auth for the OAuth URL WITHOUT redirecting\n // (disableRedirect) and open it in a popup. The popup completes on the\n // app origin (callbackURL) and the session cookie is set; Better Auth's\n // useSession picks it up here on the next focus/poll. A small focus poke\n // nudges the hook to refetch promptly.\n const result = await authClient.signIn.social({\n provider: social,\n callbackURL,\n disableRedirect: true,\n });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'OAuth sign in failed') };\n const data = (result as { data?: { url?: string } })?.data ?? null;\n const url = data?.url;\n if (url) window.open(url, 'ezc-auth', 'popup,width=500,height=680');\n return { data, error: null };\n }\n\n // Standalone (deployed app / own tab): let Better Auth do the full-page\n // redirect to the provider.\n const result = await authClient.signIn.social({ provider: social, callbackURL });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'OAuth sign in failed') };\n const data = (result as { data?: unknown })?.data ?? null;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\n }\n }, [authClient]);\n\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\n if (!authClient) return { error: notConfiguredError() };\n const userId = user?.id;\n try {\n const result = await authClient.signOut();\n const error = (result as { error?: unknown })?.error;\n if (error) return { error: toError(error, 'Sign out failed') };\n if (userId) ezcoder.users.trackLogout(userId);\n return { error: null };\n } catch (err: unknown) {\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\n }\n }, [authClient, user]);\n\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n // Better Auth renamed `forgetPassword` → `requestPasswordReset`. Support both\n // so the SDK works regardless of the server's Better Auth version.\n const client = authClient as unknown as {\n requestPasswordReset?: (args: { email: string; redirectTo?: string }) => Promise<unknown>;\n forgetPassword?: (args: { email: string; redirectTo?: string }) => Promise<unknown>;\n };\n const redirectTo = `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`;\n const fn = client.requestPasswordReset || client.forgetPassword;\n if (!fn) {\n return { data: null, error: NEON_NOT_SUPPORTED('Password reset') };\n }\n try {\n const result = await fn({ email, redirectTo });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'Password reset failed') };\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\n }\n }, [authClient]);\n\n const updatePassword = useCallback(async (newPassword: string): Promise<AuthResult> => {\n if (!authClient) return { data: null, error: notConfiguredError() };\n // Two distinct Better Auth operations land here:\n // - `resetPassword({ newPassword, token })` after a reset-email link (token in URL)\n // - `changePassword({ newPassword, currentPassword })` for a logged-in user\n // We only have the new password, so we use the token-based reset when a\n // reset token is present in the URL; otherwise there is no safe call to make\n // (changePassword requires the current password we don't have).\n const token = typeof window !== 'undefined'\n ? new URLSearchParams(window.location.search).get('token') ||\n new URLSearchParams(window.location.search).get('reset_token')\n : null;\n const client = authClient as unknown as {\n resetPassword?: (args: { newPassword: string; token: string }) => Promise<unknown>;\n };\n if (token && client.resetPassword) {\n try {\n const result = await client.resetPassword({ newPassword, token });\n const error = (result as { error?: unknown })?.error;\n if (error) return { data: null, error: toError(error, 'Password update failed') };\n const data = (result as { data?: unknown })?.data ?? result;\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password update failed') };\n }\n }\n // TODO(neon-auth): wire changePassword once the UI can collect the current\n // password (Better Auth changePassword requires { newPassword, currentPassword }).\n return { data: null, error: NEON_NOT_SUPPORTED('Updating the password without a reset token') };\n }, [authClient]);\n\n // TODO(neon-auth): the user profile lives in the project's Neon\n // `public.user_profiles` table. Reading it requires the platform DB path\n // (useDatabase / DatabaseClient), which is provider-scoped and not available\n // here without threading a client in. We intentionally do NOT call Supabase on\n // the Neon path. Profile reads/writes no-op gracefully for now.\n const fetchProfile = useCallback(async (_userId: string): Promise<UserProfile | null> => {\n return null;\n }, []);\n\n const updateProfile = useCallback(async (_updates: Partial<UserProfile>): Promise<AuthResult> => {\n if (!user) return { data: null, error: new Error('Not authenticated') };\n return { data: null, error: NEON_NOT_SUPPORTED('Updating the profile') };\n }, [user]);\n\n const value: AuthContextType = {\n user,\n profile,\n session,\n loading,\n isConfigured: Boolean(authClient),\n signUp,\n signIn,\n signInWithProvider,\n signOut,\n resetPassword,\n updatePassword,\n updateProfile,\n refetchProfile: fetchProfile,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nfunction toError(error: unknown, fallback: string): Error {\n if (error instanceof Error) return error;\n if (error && typeof error === 'object') {\n const msg = (error as { message?: string; statusText?: string }).message\n || (error as { statusText?: string }).statusText;\n if (msg) return new Error(msg);\n }\n if (typeof error === 'string') return new Error(error);\n return new Error(fallback);\n}\n\n// ─── Supabase path (UNCHANGED behaviour) ─────────────────────────────────────\n\nfunction SupabaseAuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null);\n const [profile, setProfile] = useState<UserProfile | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState<boolean>(true);\n const previousUserIdRef = useRef<string | null>(null);\n\n const fetchProfile = useCallback(async (userId: string): Promise<UserProfile | null> => {\n if (!userId) return null;\n\n try {\n let query = supabase\n .from('user_profiles')\n .select('*')\n .eq('id', userId);\n\n if (env.EZC_PROJECT_ID) {\n query = query.eq('project_id', env.EZC_PROJECT_ID);\n }\n\n const result = await query.single();\n\n const { data, error } = result || { data: null, error: null };\n\n if (error) {\n return null;\n }\n\n setProfile(data as UserProfile);\n return data as UserProfile;\n } catch {\n return null;\n }\n }, []);\n\n // SEC-1: bind the end-user to THIS project server-side (authoritative; app_metadata\n // is service-role-only). OAuth users have no signup metadata so the migration-226\n // trigger can't bind them — this is what stops migration 227 from locking them out.\n // No-ops if already bound. Non-blocking.\n const bindProjectIfNeeded = useCallback(async (currentUser: User | null): Promise<void> => {\n if (!currentUser || !env.EZC_PROJECT_ID || !env.EZCODER_API_URL) return;\n const appMeta = currentUser.app_metadata as Record<string, unknown> | undefined;\n if (appMeta?.bound_project_id) return;\n try {\n const { data } = await supabase.auth.getSession();\n const token = data?.session?.access_token;\n if (!token) return;\n const res = await fetch(`${env.EZCODER_API_URL.replace(/\\/$/, '')}/api/managed-auth/bind`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(env.EZC_PROJECT_TOKEN_PUBLIC ? { Authorization: `Bearer ${env.EZC_PROJECT_TOKEN_PUBLIC}` } : {}),\n 'X-EZC-User-Token': token,\n },\n body: JSON.stringify({ projectId: env.EZC_PROJECT_ID }),\n });\n const j = await res.json().catch(() => ({}));\n if (j?.changed) {\n // The new bound_project_id claim only appears after a token refresh.\n await supabase.auth.refreshSession();\n }\n } catch {\n // non-blocking — login still works; binding reconciles on next load / via backfill\n }\n }, []);\n\n useEffect(() => {\n supabase.auth.getSession().then(async ({ data: { session: initialSession } }) => {\n setSession(initialSession);\n setUser(initialSession?.user ?? null);\n\n if (initialSession?.user) {\n await fetchProfile(initialSession.user.id);\n bindProjectIfNeeded(initialSession.user);\n }\n\n setLoading(false);\n });\n\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange(async (event, currentSession) => {\n setSession(currentSession);\n setUser(currentSession?.user ?? null);\n\n if (event === 'SIGNED_IN' && currentSession?.user) {\n await fetchProfile(currentSession.user.id);\n bindProjectIfNeeded(currentSession.user);\n ezcoderAuthIntegration.onLogin(currentSession.user);\n previousUserIdRef.current = currentSession.user.id;\n } else if (event === 'SIGNED_OUT') {\n setProfile(null);\n if (previousUserIdRef.current) {\n ezcoderAuthIntegration.onLogout(previousUserIdRef.current);\n previousUserIdRef.current = null;\n }\n } else if (event === 'USER_UPDATED' && currentSession?.user) {\n ezcoder.analytics.identify(currentSession.user.id, {\n email: currentSession.user.email,\n name: currentSession.user.user_metadata?.full_name,\n });\n }\n });\n\n // In-editor popup sign-in: the /auth/callback popup postMessages on completion;\n // the storage event is a same-origin fallback for the popup's localStorage write.\n const refreshFromExternal = () => {\n supabase.auth.getSession().then(({ data }) => {\n const s = data?.session ?? null;\n setSession(s);\n setUser(s?.user ?? null);\n if (s?.user) { fetchProfile(s.user.id); bindProjectIfNeeded(s.user); }\n });\n };\n const onMsg = (e: MessageEvent) => { if (e?.data?.type === 'ezc-auth-complete') refreshFromExternal(); };\n const onStorage = (e: StorageEvent) => { if (e.key && /auth-token/.test(e.key)) refreshFromExternal(); };\n if (typeof window !== 'undefined') {\n window.addEventListener('message', onMsg);\n window.addEventListener('storage', onStorage);\n }\n\n return () => {\n subscription.unsubscribe();\n if (typeof window !== 'undefined') {\n window.removeEventListener('message', onMsg);\n window.removeEventListener('storage', onStorage);\n }\n };\n }, [fetchProfile, bindProjectIfNeeded]);\n\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n const { metadata = {} } = options;\n\n try {\n const signUpMetadata = { ...metadata };\n if (env.EZC_PROJECT_ID) {\n signUpMetadata.project_id = env.EZC_PROJECT_ID;\n signUpMetadata.bound_project_id = env.EZC_PROJECT_ID;\n }\n\n const result = await supabase.auth.signUp({\n email,\n password,\n options: { data: signUpMetadata },\n });\n\n const { data, error } = result || { data: null, error: new Error('Sign up failed') };\n\n if (error) {\n return { data: null, error };\n }\n\n if (data?.user) {\n const profileData: Record<string, unknown> = {\n id: data.user.id,\n email,\n };\n if (metadata.display_name) {\n profileData.display_name = metadata.display_name;\n }\n if (env.EZC_PROJECT_ID) {\n profileData.project_id = env.EZC_PROJECT_ID;\n }\n if (metadata.display_name || env.EZC_PROJECT_ID) {\n await supabase.from('user_profiles').upsert(profileData);\n }\n try {\n await supabase.rpc('assign_default_role', { user_uuid: data.user.id });\n } catch {\n // Non-blocking — role tables may not exist in all projects\n }\n ezcoderAuthIntegration.onSignup(data.user);\n }\n\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\n }\n }, []);\n\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.signInWithPassword({ email, password });\n const { data, error } = result || { data: null, error: new Error('Sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\n }\n }, []);\n\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const provider2 = provider as 'google' | 'github' | 'facebook' | 'apple' | 'twitter';\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const framed = typeof window !== 'undefined' && window.self !== window.top;\n\n if (framed && typeof window !== 'undefined') {\n // Provider login pages refuse to render inside an iframe (X-Frame-Options /\n // frame-ancestors), so we cannot do a full-page redirect in the editor preview.\n // Open the flow in a popup; the /auth/callback page completes PKCE and\n // postMessages back (storage event is the fallback). Land on the callback route.\n const redirectTo = options.redirectTo || (origin ? `${origin}/auth/callback` : '');\n const result = await supabase.auth.signInWithOAuth({\n provider: provider2,\n options: { redirectTo, skipBrowserRedirect: true, ...options },\n });\n if (result?.error) return { data: null, error: result.error };\n const url = (result?.data as { url?: string } | null)?.url;\n if (url) window.open(url, 'ezc-auth', 'popup,width=500,height=680');\n return { data: result?.data ?? null, error: null };\n }\n\n // Standalone (deployed app / own tab): full-page redirect. Default to the app\n // origin (root) so apps without a scaffolded callback route still complete via\n // detectSessionInUrl; new apps pass /auth/callback explicitly.\n const result = await supabase.auth.signInWithOAuth({\n provider: provider2,\n options: {\n redirectTo: options.redirectTo || origin,\n ...options,\n },\n });\n const { data, error } = result || { data: null, error: new Error('OAuth sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\n }\n }, []);\n\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\n const userId = user?.id;\n try {\n const result = await supabase.auth.signOut();\n const { error } = result || { error: null };\n if (!error && userId) {\n ezcoder.users.trackLogout(userId);\n }\n return { error };\n } catch (err: unknown) {\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\n }\n }, [user]);\n\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\n try {\n const result = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo: `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`,\n });\n const { data, error } = result || { data: null, error: new Error('Password reset failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\n }\n }, []);\n\n // Set a new password. Used on the /auth/reset-password landing page, where the\n // recovery link has already established a (recovery) session via detectSessionInUrl.\n const updatePassword = useCallback(async (newPassword: string): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.updateUser({ password: newPassword });\n const { data, error } = result || { data: null, error: new Error('Password update failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password update failed') };\n }\n }, []);\n\n const updateProfile = useCallback(\n async (updates: Partial<UserProfile>): Promise<AuthResult> => {\n if (!user) {\n return { data: null, error: new Error('Not authenticated') };\n }\n try {\n let query = supabase\n .from('user_profiles')\n .update(updates)\n .eq('id', user.id);\n\n if (env.EZC_PROJECT_ID) {\n query = query.eq('project_id', env.EZC_PROJECT_ID);\n }\n\n const result = await query.select().single();\n const { data, error } = result || { data: null, error: null };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Update failed') };\n }\n },\n [user]\n );\n\n const value: AuthContextType = {\n user,\n profile,\n session,\n loading,\n isConfigured: isSupabaseConfigured,\n signUp,\n signIn,\n signInWithProvider,\n signOut,\n resetPassword,\n updatePassword,\n updateProfile,\n refetchProfile: fetchProfile,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nexport function useAuth(): AuthContextType {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport type { AuthResult, SignUpOptions, SignInWithProviderOptions };\n"],"mappings":";;;;;;;;;;;;;;AAAA,SAAS,wBAAwB;AAsBjC,IAAI,eAAsC;AAOnC,SAAS,oBAA2C;AACzD,MAAI,CAAC,wBAAwB,CAAC,IAAI,eAAe;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,CAAC,cAAc;AACjB,mBAAe,iBAAiB;AAAA,MAC9B,SAAS,IAAI;AAAA,IACf,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;ACvCA,SAAS,eAAe,YAAY,UAAU,WAAW,aAAa,cAAc;AAmEzE;AA7BX,IAAM,qBAAqB;AAC3B,SAAS,qBAAqB;AAC5B,SAAO,IAAI,MAAM,kBAAkB;AACrC;AAEO,IAAM,cAAc,cAA+B;AAAA,EACxD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EAC/C,QAAQ,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EAC/C,oBAAoB,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EAC3D,SAAS,aAAa,EAAE,OAAO,KAAK;AAAA,EACpC,eAAe,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EACtD,gBAAgB,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EACvD,eAAe,aAAa,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,EACtD,gBAAgB,YAAY;AAC9B,CAAC;AAQM,SAAS,aAAa,EAAE,SAAS,GAAkC;AACxE,MAAI,sBAAsB;AACxB,WAAO,oBAAC,oBAAkB,UAAS;AAAA,EACrC;AACA,SAAO,oBAAC,wBAAsB,UAAS;AACzC;AAyBA,SAAS,YAAY,GAAmD;AACtE,MAAI,CAAC,KAAK,CAAC,EAAE,GAAI,QAAO;AACxB,QAAM,UAAS,oBAAI,KAAK,GAAE,YAAY;AACtC,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,OAAO,EAAE;AAAA,IACT,cAAc,EAAE,UAAU,aAAa,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,EAAG;AAAA,IAC3E,eAAe;AAAA,MACb,WAAW,EAAE;AAAA,MACb,MAAM,EAAE;AAAA,MACR,YAAY,EAAE,SAAS;AAAA,MACvB,gBAAgB,EAAE;AAAA,IACpB;AAAA,IACA,KAAK;AAAA,IACL,YAAY,EAAE,aAAa;AAAA,IAC3B,YAAY,EAAE,aAAa;AAAA,IAC3B,MAAM,EAAE;AAAA,EACV;AACF;AAQA,SAAS,eAAe,YAAqB,MAAmC;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,IAAK,cAAc,CAAC;AAC1B,QAAM,QACH,EAAE,SACD,EAAE,SAAiD,SACrD;AACF,SAAO;AAAA,IACL,cAAc;AAAA,IACd,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,qBAAqB,CAAC,YAC1B,IAAI,MAAM,GAAG,OAAO,8CAA8C;AAEpE,SAAS,iBAAiB,EAAE,SAAS,GAAkC;AACrE,QAAM,aAAa,kBAAkB;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAA6B,IAAI;AAC/D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAyB,IAAI;AAC3D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,IAAI;AACpD,QAAM,oBAAoB,OAAsB,IAAI;AAIpD,QAAM,eAAe,YAAY,aAAa;AAI9C,QAAM,UAAU,cAAc,MAAM,QAAQ;AAC5C,QAAM,YAAY,cAAc,aAAa;AAE7C,YAAU,MAAM;AACd,UAAM,aAAa,YAAY,OAAO;AACtC,YAAQ,UAAU;AAClB,eAAW,eAAe,cAAc,MAAM,WAAW,cAAc,QAAQ,MAAM,UAAU,CAAC;AAChG,eAAW,QAAQ,SAAS,CAAC;AAG7B,UAAM,YAAY,YAAY,MAAM;AACpC,UAAM,SAAS,kBAAkB;AACjC,QAAI,aAAa,cAAc,QAAQ;AACrC,6BAAuB,QAAQ,UAAuD;AACtF,wBAAkB,UAAU;AAAA,IAC9B,WAAW,CAAC,aAAa,QAAQ;AAC/B,6BAAuB,SAAS,MAAM;AACtC,wBAAkB,UAAU;AAC5B,iBAAW,IAAI;AAAA,IACjB;AAAA,EAEF,GAAG,CAAC,SAAS,SAAS,CAAC;AAEvB,QAAM,SAAS,YAAY,OAAO,OAAe,UAAkB,UAAyB,CAAC,MAA2B;AACtH,QAAI,CAAC,WAAY,QAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAClE,UAAM,EAAE,WAAW,CAAC,EAAE,IAAI;AAC1B,UAAM,OAAQ,SAAS,gBAAwC,SAAS,QAA+B;AACvG,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,OAAO,MAAM,EAAE,OAAO,UAAU,KAAK,CAAC;AACtE,YAAM,QAAS,QAAgC;AAC/C,UAAI,OAAO;AACT,eAAO,EAAE,MAAM,MAAM,OAAO,QAAQ,OAAO,gBAAgB,EAAE;AAAA,MAC/D;AACA,YAAM,OAAQ,QAA+B,QAAQ;AACrD,YAAM,UAAW,MAAoC;AACrD,UAAI,SAAS,IAAI;AACf,+BAAuB,SAAS,EAAE,IAAI,QAAQ,IAAI,OAAO,QAAQ,MAAM,CAAC;AAAA,MAC1E;AACA,aAAO,EAAE,MAAM,OAAO,KAAK;AAAA,IAC7B,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB,EAAE;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,SAAS,YAAY,OAAO,OAAe,aAA0C;AACzF,QAAI,CAAC,WAAY,QAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAClE,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,OAAO,MAAM,EAAE,OAAO,SAAS,CAAC;AAChE,YAAM,QAAS,QAAgC;AAC/C,UAAI,OAAO;AACT,eAAO,EAAE,MAAM,MAAM,OAAO,QAAQ,OAAO,gBAAgB,EAAE;AAAA,MAC/D;AACA,YAAM,OAAQ,QAA+B,QAAQ;AACrD,aAAO,EAAE,MAAM,OAAO,KAAK;AAAA,IAC7B,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB,EAAE;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,qBAAqB,YAAY,OAAO,UAAkB,UAAqC,CAAC,MAA2B;AAC/H,QAAI,CAAC,WAAY,QAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAClE,QAAI;AACF,YAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,YAAM,cAAc,QAAQ,cAAc;AAC1C,YAAM,SAAS,OAAO,WAAW,eAAe,OAAO,SAAS,OAAO;AACvE,YAAM,SAAS;AAEf,UAAI,UAAU,OAAO,WAAW,aAAa;AAO3C,cAAMA,UAAS,MAAM,WAAW,OAAO,OAAO;AAAA,UAC5C,UAAU;AAAA,UACV;AAAA,UACA,iBAAiB;AAAA,QACnB,CAAC;AACD,cAAMC,SAASD,SAAgC;AAC/C,YAAIC,OAAO,QAAO,EAAE,MAAM,MAAM,OAAO,QAAQA,QAAO,sBAAsB,EAAE;AAC9E,cAAMC,QAAQF,SAAwC,QAAQ;AAC9D,cAAM,MAAME,OAAM;AAClB,YAAI,IAAK,QAAO,KAAK,KAAK,YAAY,4BAA4B;AAClE,eAAO,EAAE,MAAAA,OAAM,OAAO,KAAK;AAAA,MAC7B;AAIA,YAAM,SAAS,MAAM,WAAW,OAAO,OAAO,EAAE,UAAU,QAAQ,YAAY,CAAC;AAC/E,YAAM,QAAS,QAAgC;AAC/C,UAAI,MAAO,QAAO,EAAE,MAAM,MAAM,OAAO,QAAQ,OAAO,sBAAsB,EAAE;AAC9E,YAAM,OAAQ,QAA+B,QAAQ;AACrD,aAAO,EAAE,MAAM,OAAO,KAAK;AAAA,IAC7B,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,sBAAsB,EAAE;AAAA,IAC7F;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,UAAU,YAAY,YAA8C;AACxE,QAAI,CAAC,WAAY,QAAO,EAAE,OAAO,mBAAmB,EAAE;AACtD,UAAM,SAAS,MAAM;AACrB,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,YAAM,QAAS,QAAgC;AAC/C,UAAI,MAAO,QAAO,EAAE,OAAO,QAAQ,OAAO,iBAAiB,EAAE;AAC7D,UAAI,OAAQ,SAAQ,MAAM,YAAY,MAAM;AAC5C,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB,SAAS,KAAc;AACrB,aAAO,EAAE,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,iBAAiB,EAAE;AAAA,IAC5E;AAAA,EACF,GAAG,CAAC,YAAY,IAAI,CAAC;AAErB,QAAM,gBAAgB,YAAY,OAAO,UAAuC;AAC9E,QAAI,CAAC,WAAY,QAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAGlE,UAAM,SAAS;AAIf,UAAM,aAAa,GAAG,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,EAAE;AACjF,UAAM,KAAK,OAAO,wBAAwB,OAAO;AACjD,QAAI,CAAC,IAAI;AACP,aAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,gBAAgB,EAAE;AAAA,IACnE;AACA,QAAI;AACF,YAAM,SAAS,MAAM,GAAG,EAAE,OAAO,WAAW,CAAC;AAC7C,YAAM,QAAS,QAAgC;AAC/C,UAAI,MAAO,QAAO,EAAE,MAAM,MAAM,OAAO,QAAQ,OAAO,uBAAuB,EAAE;AAC/E,YAAM,OAAQ,QAA+B,QAAQ;AACrD,aAAO,EAAE,MAAM,OAAO,KAAK;AAAA,IAC7B,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,uBAAuB,EAAE;AAAA,IAC9F;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAiB,YAAY,OAAO,gBAA6C;AACrF,QAAI,CAAC,WAAY,QAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAOlE,UAAM,QAAQ,OAAO,WAAW,cAC5B,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,IAAI,OAAO,KACvD,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,IAAI,aAAa,IAC7D;AACJ,UAAM,SAAS;AAGf,QAAI,SAAS,OAAO,eAAe;AACjC,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,cAAc,EAAE,aAAa,MAAM,CAAC;AAChE,cAAM,QAAS,QAAgC;AAC/C,YAAI,MAAO,QAAO,EAAE,MAAM,MAAM,OAAO,QAAQ,OAAO,wBAAwB,EAAE;AAChF,cAAM,OAAQ,QAA+B,QAAQ;AACrD,eAAO,EAAE,MAAM,OAAO,KAAK;AAAA,MAC7B,SAAS,KAAc;AACrB,eAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,wBAAwB,EAAE;AAAA,MAC/F;AAAA,IACF;AAGA,WAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,6CAA6C,EAAE;AAAA,EAChG,GAAG,CAAC,UAAU,CAAC;AAOf,QAAM,eAAe,YAAY,OAAO,YAAiD;AACvF,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,YAAY,OAAO,aAAwD;AAC/F,QAAI,CAAC,KAAM,QAAO,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,mBAAmB,EAAE;AACtE,WAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,sBAAsB,EAAE;AAAA,EACzE,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,QAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc,QAAQ,UAAU;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,EAClB;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEA,SAAS,QAAQ,OAAgB,UAAyB;AACxD,MAAI,iBAAiB,MAAO,QAAO;AACnC,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,MAAO,MAAoD,WAC3D,MAAkC;AACxC,QAAI,IAAK,QAAO,IAAI,MAAM,GAAG;AAAA,EAC/B;AACA,MAAI,OAAO,UAAU,SAAU,QAAO,IAAI,MAAM,KAAK;AACrD,SAAO,IAAI,MAAM,QAAQ;AAC3B;AAIA,SAAS,qBAAqB,EAAE,SAAS,GAAkC;AACzE,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAA6B,IAAI;AAC/D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAyB,IAAI;AAC3D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAkB,IAAI;AACpD,QAAM,oBAAoB,OAAsB,IAAI;AAEpD,QAAM,eAAe,YAAY,OAAO,WAAgD;AACtF,QAAI,CAAC,OAAQ,QAAO;AAEpB,QAAI;AACF,UAAI,QAAQ,SACT,KAAK,eAAe,EACpB,OAAO,GAAG,EACV,GAAG,MAAM,MAAM;AAElB,UAAI,IAAI,gBAAgB;AACtB,gBAAQ,MAAM,GAAG,cAAc,IAAI,cAAc;AAAA,MACnD;AAEA,YAAM,SAAS,MAAM,MAAM,OAAO;AAElC,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,KAAK;AAE5D,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAEA,iBAAW,IAAmB;AAC9B,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,CAAC;AAML,QAAM,sBAAsB,YAAY,OAAO,gBAA4C;AACzF,QAAI,CAAC,eAAe,CAAC,IAAI,kBAAkB,CAAC,IAAI,gBAAiB;AACjE,UAAM,UAAU,YAAY;AAC5B,QAAI,SAAS,iBAAkB;AAC/B,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,MAAM,SAAS,KAAK,WAAW;AAChD,YAAM,QAAQ,MAAM,SAAS;AAC7B,UAAI,CAAC,MAAO;AACZ,YAAM,MAAM,MAAM,MAAM,GAAG,IAAI,gBAAgB,QAAQ,OAAO,EAAE,CAAC,0BAA0B;AAAA,QACzF,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAI,IAAI,2BAA2B,EAAE,eAAe,UAAU,IAAI,wBAAwB,GAAG,IAAI,CAAC;AAAA,UAClG,oBAAoB;AAAA,QACtB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,WAAW,IAAI,eAAe,CAAC;AAAA,MACxD,CAAC;AACD,YAAM,IAAI,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC3C,UAAI,GAAG,SAAS;AAEd,cAAM,SAAS,KAAK,eAAe;AAAA,MACrC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,aAAS,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,EAAE,SAAS,eAAe,EAAE,MAAM;AAC/E,iBAAW,cAAc;AACzB,cAAQ,gBAAgB,QAAQ,IAAI;AAEpC,UAAI,gBAAgB,MAAM;AACxB,cAAM,aAAa,eAAe,KAAK,EAAE;AACzC,4BAAoB,eAAe,IAAI;AAAA,MACzC;AAEA,iBAAW,KAAK;AAAA,IAClB,CAAC;AAED,UAAM;AAAA,MACJ,MAAM,EAAE,aAAa;AAAA,IACvB,IAAI,SAAS,KAAK,kBAAkB,OAAO,OAAO,mBAAmB;AACnE,iBAAW,cAAc;AACzB,cAAQ,gBAAgB,QAAQ,IAAI;AAEpC,UAAI,UAAU,eAAe,gBAAgB,MAAM;AACjD,cAAM,aAAa,eAAe,KAAK,EAAE;AACzC,4BAAoB,eAAe,IAAI;AACvC,+BAAuB,QAAQ,eAAe,IAAI;AAClD,0BAAkB,UAAU,eAAe,KAAK;AAAA,MAClD,WAAW,UAAU,cAAc;AACjC,mBAAW,IAAI;AACf,YAAI,kBAAkB,SAAS;AAC7B,iCAAuB,SAAS,kBAAkB,OAAO;AACzD,4BAAkB,UAAU;AAAA,QAC9B;AAAA,MACF,WAAW,UAAU,kBAAkB,gBAAgB,MAAM;AAC3D,gBAAQ,UAAU,SAAS,eAAe,KAAK,IAAI;AAAA,UACjD,OAAO,eAAe,KAAK;AAAA,UAC3B,MAAM,eAAe,KAAK,eAAe;AAAA,QAC3C,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAID,UAAM,sBAAsB,MAAM;AAChC,eAAS,KAAK,WAAW,EAAE,KAAK,CAAC,EAAE,KAAK,MAAM;AAC5C,cAAM,IAAI,MAAM,WAAW;AAC3B,mBAAW,CAAC;AACZ,gBAAQ,GAAG,QAAQ,IAAI;AACvB,YAAI,GAAG,MAAM;AAAE,uBAAa,EAAE,KAAK,EAAE;AAAG,8BAAoB,EAAE,IAAI;AAAA,QAAG;AAAA,MACvE,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,CAAC,MAAoB;AAAE,UAAI,GAAG,MAAM,SAAS,oBAAqB,qBAAoB;AAAA,IAAG;AACvG,UAAM,YAAY,CAAC,MAAoB;AAAE,UAAI,EAAE,OAAO,aAAa,KAAK,EAAE,GAAG,EAAG,qBAAoB;AAAA,IAAG;AACvG,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,iBAAiB,WAAW,KAAK;AACxC,aAAO,iBAAiB,WAAW,SAAS;AAAA,IAC9C;AAEA,WAAO,MAAM;AACX,mBAAa,YAAY;AACzB,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO,oBAAoB,WAAW,KAAK;AAC3C,eAAO,oBAAoB,WAAW,SAAS;AAAA,MACjD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,cAAc,mBAAmB,CAAC;AAEtC,QAAM,SAAS,YAAY,OAAO,OAAe,UAAkB,UAAyB,CAAC,MAA2B;AACtH,QAAI,CAAC,sBAAsB;AACzB,aAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAAA,IACnD;AACA,UAAM,EAAE,WAAW,CAAC,EAAE,IAAI;AAE1B,QAAI;AACF,YAAM,iBAAiB,EAAE,GAAG,SAAS;AACrC,UAAI,IAAI,gBAAgB;AACtB,uBAAe,aAAa,IAAI;AAChC,uBAAe,mBAAmB,IAAI;AAAA,MACxC;AAEA,YAAM,SAAS,MAAM,SAAS,KAAK,OAAO;AAAA,QACxC;AAAA,QACA;AAAA,QACA,SAAS,EAAE,MAAM,eAAe;AAAA,MAClC,CAAC;AAED,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,gBAAgB,EAAE;AAEnF,UAAI,OAAO;AACT,eAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B;AAEA,UAAI,MAAM,MAAM;AACd,cAAM,cAAuC;AAAA,UAC3C,IAAI,KAAK,KAAK;AAAA,UACd;AAAA,QACF;AACA,YAAI,SAAS,cAAc;AACzB,sBAAY,eAAe,SAAS;AAAA,QACtC;AACA,YAAI,IAAI,gBAAgB;AACtB,sBAAY,aAAa,IAAI;AAAA,QAC/B;AACA,YAAI,SAAS,gBAAgB,IAAI,gBAAgB;AAC/C,gBAAM,SAAS,KAAK,eAAe,EAAE,OAAO,WAAW;AAAA,QACzD;AACA,YAAI;AACF,gBAAM,SAAS,IAAI,uBAAuB,EAAE,WAAW,KAAK,KAAK,GAAG,CAAC;AAAA,QACvE,QAAQ;AAAA,QAER;AACA,+BAAuB,SAAS,KAAK,IAAI;AAAA,MAC3C;AAEA,aAAO,EAAE,MAAM,OAAO,KAAK;AAAA,IAC7B,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB,EAAE;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,OAAO,OAAe,aAA0C;AACzF,QAAI,CAAC,sBAAsB;AACzB,aAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAAA,IACnD;AACA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,KAAK,mBAAmB,EAAE,OAAO,SAAS,CAAC;AACzE,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,gBAAgB,EAAE;AACnF,aAAO,EAAE,MAAM,MAAM;AAAA,IACvB,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,gBAAgB,EAAE;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,YAAY,OAAO,UAAkB,UAAqC,CAAC,MAA2B;AAC/H,QAAI,CAAC,sBAAsB;AACzB,aAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAAA,IACnD;AACA,QAAI;AACF,YAAM,YAAY;AAClB,YAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AACxE,YAAM,SAAS,OAAO,WAAW,eAAe,OAAO,SAAS,OAAO;AAEvE,UAAI,UAAU,OAAO,WAAW,aAAa;AAK3C,cAAM,aAAa,QAAQ,eAAe,SAAS,GAAG,MAAM,mBAAmB;AAC/E,cAAMF,UAAS,MAAM,SAAS,KAAK,gBAAgB;AAAA,UACjD,UAAU;AAAA,UACV,SAAS,EAAE,YAAY,qBAAqB,MAAM,GAAG,QAAQ;AAAA,QAC/D,CAAC;AACD,YAAIA,SAAQ,MAAO,QAAO,EAAE,MAAM,MAAM,OAAOA,QAAO,MAAM;AAC5D,cAAM,MAAOA,SAAQ,MAAkC;AACvD,YAAI,IAAK,QAAO,KAAK,KAAK,YAAY,4BAA4B;AAClE,eAAO,EAAE,MAAMA,SAAQ,QAAQ,MAAM,OAAO,KAAK;AAAA,MACnD;AAKA,YAAM,SAAS,MAAM,SAAS,KAAK,gBAAgB;AAAA,QACjD,UAAU;AAAA,QACV,SAAS;AAAA,UACP,YAAY,QAAQ,cAAc;AAAA,UAClC,GAAG;AAAA,QACL;AAAA,MACF,CAAC;AACD,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,sBAAsB,EAAE;AACzF,aAAO,EAAE,MAAM,MAAM;AAAA,IACvB,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,sBAAsB,EAAE;AAAA,IAC7F;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,YAA8C;AACxE,UAAM,SAAS,MAAM;AACrB,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,KAAK,QAAQ;AAC3C,YAAM,EAAE,MAAM,IAAI,UAAU,EAAE,OAAO,KAAK;AAC1C,UAAI,CAAC,SAAS,QAAQ;AACpB,gBAAQ,MAAM,YAAY,MAAM;AAAA,MAClC;AACA,aAAO,EAAE,MAAM;AAAA,IACjB,SAAS,KAAc;AACrB,aAAO,EAAE,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,iBAAiB,EAAE;AAAA,IAC5E;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,gBAAgB,YAAY,OAAO,UAAuC;AAC9E,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,KAAK,sBAAsB,OAAO;AAAA,QAC9D,YAAY,GAAG,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,EAAE;AAAA,MAC5E,CAAC;AACD,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,uBAAuB,EAAE;AAC1F,aAAO,EAAE,MAAM,MAAM;AAAA,IACvB,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,uBAAuB,EAAE;AAAA,IAC9F;AAAA,EACF,GAAG,CAAC,CAAC;AAIL,QAAM,iBAAiB,YAAY,OAAO,gBAA6C;AACrF,QAAI,CAAC,sBAAsB;AACzB,aAAO,EAAE,MAAM,MAAM,OAAO,mBAAmB,EAAE;AAAA,IACnD;AACA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,KAAK,WAAW,EAAE,UAAU,YAAY,CAAC;AACvE,YAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,wBAAwB,EAAE;AAC3F,aAAO,EAAE,MAAM,MAAM;AAAA,IACvB,SAAS,KAAc;AACrB,aAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,wBAAwB,EAAE;AAAA,IAC/F;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB;AAAA,IACpB,OAAO,YAAuD;AAC5D,UAAI,CAAC,MAAM;AACT,eAAO,EAAE,MAAM,MAAM,OAAO,IAAI,MAAM,mBAAmB,EAAE;AAAA,MAC7D;AACA,UAAI;AACF,YAAI,QAAQ,SACT,KAAK,eAAe,EACpB,OAAO,OAAO,EACd,GAAG,MAAM,KAAK,EAAE;AAEnB,YAAI,IAAI,gBAAgB;AACtB,kBAAQ,MAAM,GAAG,cAAc,IAAI,cAAc;AAAA,QACnD;AAEA,cAAM,SAAS,MAAM,MAAM,OAAO,EAAE,OAAO;AAC3C,cAAM,EAAE,MAAM,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,OAAO,KAAK;AAC5D,eAAO,EAAE,MAAM,MAAM;AAAA,MACvB,SAAS,KAAc;AACrB,eAAO,EAAE,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,eAAe,EAAE;AAAA,MACtF;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,QAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,EAClB;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEO,SAAS,UAA2B;AACzC,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;","names":["result","error","data"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|