@atlasauth/react 0.13.0 → 0.15.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/CHANGELOG.md +28 -0
- package/dist/AtlasProvider.d.ts +8 -1
- package/dist/AtlasProvider.js +54 -4
- package/dist/AtlasProvider.js.map +1 -1
- package/dist/account.d.ts +19 -1
- package/dist/account.js +121 -16
- package/dist/account.js.map +1 -1
- package/dist/active-atlas.d.ts +29 -0
- package/dist/active-atlas.js +40 -0
- package/dist/active-atlas.js.map +1 -0
- package/dist/billing.d.ts +55 -1
- package/dist/billing.js +115 -8
- package/dist/billing.js.map +1 -1
- package/dist/captcha.js +1 -1
- package/dist/captcha.js.map +1 -1
- package/dist/compat.d.ts +307 -0
- package/dist/compat.js +387 -0
- package/dist/compat.js.map +1 -0
- package/dist/components.d.ts +10 -4
- package/dist/components.js +15 -1
- package/dist/components.js.map +1 -1
- package/dist/device-authorization.d.ts +42 -0
- package/dist/device-authorization.js +137 -0
- package/dist/device-authorization.js.map +1 -0
- package/dist/flow.d.ts +33 -9
- package/dist/flow.js +130 -11
- package/dist/flow.js.map +1 -1
- package/dist/i18n.js +68 -0
- package/dist/i18n.js.map +1 -1
- package/dist/impersonation.d.ts +25 -0
- package/dist/impersonation.js +52 -0
- package/dist/impersonation.js.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mfa-steps.d.ts +53 -0
- package/dist/mfa-steps.js +148 -0
- package/dist/mfa-steps.js.map +1 -0
- package/dist/organization.d.ts +82 -1
- package/dist/organization.js +222 -4
- package/dist/organization.js.map +1 -1
- package/dist/reverification.d.ts +19 -0
- package/dist/reverification.js +49 -1
- package/dist/reverification.js.map +1 -1
- package/dist/sign-in.js +2 -2
- package/dist/sign-in.js.map +1 -1
- package/dist/sign-up.d.ts +6 -0
- package/dist/sign-up.js +69 -13
- package/dist/sign-up.js.map +1 -1
- package/dist/styles.js +8 -0
- package/dist/styles.js.map +1 -1
- package/dist/types.d.ts +52 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -4
package/dist/compat.d.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drop-in compatibility helpers for apps moving to Atlas from Auth.js (NextAuth),
|
|
3
|
+
* Auth0 (auth0-react / nextjs-auth0), Supabase Auth and Better Auth.
|
|
4
|
+
*
|
|
5
|
+
* `atlas migrate code --from <vendor>` rewrites an app's imports onto these, so
|
|
6
|
+
* the migrated code keeps the shapes it was written against (`{ data, status }`
|
|
7
|
+
* from `useSession`, `{ isAuthenticated, user }` from `useAuth0`, …) and compiles
|
|
8
|
+
* and runs on day one. Each helper is a thin projection over the native hooks
|
|
9
|
+
* (`useUser`, `useAuth`); once migrated, move call sites to those at your own pace.
|
|
10
|
+
*
|
|
11
|
+
* The imperative helpers (`nextAuthSignOut()`, `getSupabaseUserCompat()`, …) work
|
|
12
|
+
* outside React components too: they act on the `<AtlasProvider>` mounted on the
|
|
13
|
+
* page. Calling one with no provider mounted throws a clear error.
|
|
14
|
+
*/
|
|
15
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
16
|
+
import type { AtlasUser, SessionClaims } from './types';
|
|
17
|
+
import { type ActiveAtlas } from './active-atlas';
|
|
18
|
+
export { getActiveAtlas, type ActiveAtlas } from './active-atlas';
|
|
19
|
+
/** The primary email address, else the first verified one, else any. */
|
|
20
|
+
export declare function primaryEmail(user: AtlasUser | null): {
|
|
21
|
+
address: string;
|
|
22
|
+
verified: boolean;
|
|
23
|
+
} | null;
|
|
24
|
+
/** A display name: first + last, else the username, else null. */
|
|
25
|
+
export declare function displayName(user: AtlasUser | null): string | null;
|
|
26
|
+
/** Send the browser to your sign-in page, returning to `redirectUrl` afterwards. */
|
|
27
|
+
export declare function signInRedirect(options?: {
|
|
28
|
+
signInUrl?: string;
|
|
29
|
+
redirectUrl?: string;
|
|
30
|
+
}): void;
|
|
31
|
+
/** The `session` object `next-auth`'s `useSession()` / `getSession()` resolve to. */
|
|
32
|
+
export interface NextAuthCompatSession {
|
|
33
|
+
user: {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string | null;
|
|
36
|
+
email: string | null;
|
|
37
|
+
image: string | null;
|
|
38
|
+
};
|
|
39
|
+
expires: string;
|
|
40
|
+
}
|
|
41
|
+
export type NextAuthCompatStatus = 'loading' | 'authenticated' | 'unauthenticated';
|
|
42
|
+
/** Pure projection of the provider state onto next-auth's session shape. */
|
|
43
|
+
export declare function nextAuthSessionFrom(state: Pick<ActiveAtlas, 'status' | 'user' | 'claims'>): {
|
|
44
|
+
data: NextAuthCompatSession | null;
|
|
45
|
+
status: NextAuthCompatStatus;
|
|
46
|
+
};
|
|
47
|
+
/** `useSession()` from `next-auth/react`, on Atlas: `{ data, status, update }`. */
|
|
48
|
+
export declare function useNextAuthSession(): {
|
|
49
|
+
data: NextAuthCompatSession | null;
|
|
50
|
+
status: NextAuthCompatStatus;
|
|
51
|
+
update: () => Promise<NextAuthCompatSession | null>;
|
|
52
|
+
};
|
|
53
|
+
/** `getSession()` from `next-auth/react` (client side): the current session or null. */
|
|
54
|
+
export declare function getNextAuthSession(): Promise<NextAuthCompatSession | null>;
|
|
55
|
+
/**
|
|
56
|
+
* `signIn()` from `next-auth/react`: opens your Atlas sign-in page. The provider
|
|
57
|
+
* argument is accepted for compatibility; the sign-in page lists every enabled
|
|
58
|
+
* method (render `<SocialSignInButton provider="github" />` to go straight to one).
|
|
59
|
+
*/
|
|
60
|
+
export declare function nextAuthSignIn(_provider?: string, options?: {
|
|
61
|
+
callbackUrl?: string;
|
|
62
|
+
redirectTo?: string;
|
|
63
|
+
signInUrl?: string;
|
|
64
|
+
}): Promise<void>;
|
|
65
|
+
/** `signOut()` from `next-auth/react`: signs out, then goes to `callbackUrl` (default `/`). */
|
|
66
|
+
export declare function nextAuthSignOut(options?: {
|
|
67
|
+
callbackUrl?: string;
|
|
68
|
+
redirectTo?: string;
|
|
69
|
+
redirect?: boolean;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
/** The OIDC-profile user `useAuth0()` / nextjs-auth0's `useUser()` expose. */
|
|
72
|
+
export interface Auth0CompatUser {
|
|
73
|
+
sub: string;
|
|
74
|
+
name?: string;
|
|
75
|
+
given_name?: string;
|
|
76
|
+
family_name?: string;
|
|
77
|
+
nickname?: string;
|
|
78
|
+
picture?: string;
|
|
79
|
+
email?: string;
|
|
80
|
+
email_verified?: boolean;
|
|
81
|
+
org_id?: string;
|
|
82
|
+
[claim: string]: unknown;
|
|
83
|
+
}
|
|
84
|
+
/** Project an Atlas user onto the OIDC profile shape Auth0 SDKs return. */
|
|
85
|
+
export declare function auth0UserFrom(user: AtlasUser | null, claims?: SessionClaims | null): Auth0CompatUser | undefined;
|
|
86
|
+
/** `loginWithRedirect()` options this helper understands (others are ignored). */
|
|
87
|
+
export interface Auth0CompatLoginOptions {
|
|
88
|
+
appState?: {
|
|
89
|
+
returnTo?: string;
|
|
90
|
+
[key: string]: unknown;
|
|
91
|
+
};
|
|
92
|
+
/** Where your Atlas sign-in page lives (default `/sign-in`). */
|
|
93
|
+
signInUrl?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface Auth0CompatLogoutOptions {
|
|
96
|
+
logoutParams?: {
|
|
97
|
+
returnTo?: string;
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
};
|
|
100
|
+
/** `false` skips the redirect, like auth0-react's `openUrl: false`. */
|
|
101
|
+
openUrl?: false;
|
|
102
|
+
}
|
|
103
|
+
/** Thrown by `getAccessTokenSilently()` when nobody is signed in (Auth0's `login_required`). */
|
|
104
|
+
export declare class LoginRequiredError extends Error {
|
|
105
|
+
readonly error = "login_required";
|
|
106
|
+
constructor();
|
|
107
|
+
}
|
|
108
|
+
/** `useAuth0()` from `@auth0/auth0-react`, on Atlas. */
|
|
109
|
+
export declare function useAuth0Compat<TUser extends Auth0CompatUser = Auth0CompatUser>(): {
|
|
110
|
+
isLoading: boolean;
|
|
111
|
+
isAuthenticated: boolean;
|
|
112
|
+
user: TUser | undefined;
|
|
113
|
+
error: undefined;
|
|
114
|
+
loginWithRedirect(options?: Auth0CompatLoginOptions): Promise<void>;
|
|
115
|
+
logout(options?: Auth0CompatLogoutOptions): Promise<void>;
|
|
116
|
+
getAccessTokenSilently(options?: {
|
|
117
|
+
template?: string;
|
|
118
|
+
}): Promise<string>;
|
|
119
|
+
getIdTokenClaims(): Promise<(SessionClaims & {
|
|
120
|
+
__raw?: string;
|
|
121
|
+
}) | undefined>;
|
|
122
|
+
};
|
|
123
|
+
/** `useUser()` from `@auth0/nextjs-auth0/client` (v3) or `@auth0/nextjs-auth0` (v4). */
|
|
124
|
+
export declare function useAuth0UserCompat<TUser extends Auth0CompatUser = Auth0CompatUser>(): {
|
|
125
|
+
user: TUser | undefined;
|
|
126
|
+
error: undefined;
|
|
127
|
+
isLoading: boolean;
|
|
128
|
+
checkSession(): Promise<void>;
|
|
129
|
+
invalidate(): Promise<void>;
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* `withAuthenticationRequired(Component, options)` from `@auth0/auth0-react` (and
|
|
133
|
+
* nextjs-auth0's client `withPageAuthRequired`): renders the component only for a
|
|
134
|
+
* signed-in user and sends everyone else to your sign-in page.
|
|
135
|
+
*/
|
|
136
|
+
export declare function withAuthenticationRequiredCompat<P extends object>(Component: ComponentType<P>, options?: {
|
|
137
|
+
onRedirecting?: () => ReactNode;
|
|
138
|
+
returnTo?: string | (() => string);
|
|
139
|
+
signInUrl?: string;
|
|
140
|
+
}): ComponentType<P>;
|
|
141
|
+
/** The `User` object `supabase.auth.getUser()` resolves to (the fields apps read). */
|
|
142
|
+
export interface SupabaseCompatUser {
|
|
143
|
+
id: string;
|
|
144
|
+
aud: 'authenticated';
|
|
145
|
+
role: 'authenticated';
|
|
146
|
+
email?: string;
|
|
147
|
+
email_confirmed_at?: string;
|
|
148
|
+
phone?: string;
|
|
149
|
+
user_metadata: Record<string, unknown>;
|
|
150
|
+
app_metadata: Record<string, unknown>;
|
|
151
|
+
}
|
|
152
|
+
export declare function supabaseUserFrom(user: AtlasUser | null): SupabaseCompatUser | null;
|
|
153
|
+
type SupabaseResult<T> = {
|
|
154
|
+
data: T;
|
|
155
|
+
error: null;
|
|
156
|
+
};
|
|
157
|
+
/** `supabase.auth.getUser()` in the browser. */
|
|
158
|
+
export declare function getSupabaseUserCompat(): Promise<SupabaseResult<{
|
|
159
|
+
user: SupabaseCompatUser | null;
|
|
160
|
+
}>>;
|
|
161
|
+
/** `supabase.auth.getSession()` in the browser; `access_token` is the Atlas session JWT. */
|
|
162
|
+
export declare function getSupabaseSessionCompat(): Promise<SupabaseResult<{
|
|
163
|
+
session: {
|
|
164
|
+
access_token: string;
|
|
165
|
+
expires_at: number | undefined;
|
|
166
|
+
user: SupabaseCompatUser;
|
|
167
|
+
} | null;
|
|
168
|
+
}>>;
|
|
169
|
+
/** `useUser()` from `@supabase/auth-helpers-react`: the user, or null. */
|
|
170
|
+
export declare function useSupabaseUserCompat(): SupabaseCompatUser | null;
|
|
171
|
+
/** `useSession()` from `@supabase/auth-helpers-react`: `{ user, expires_at }`, or null. */
|
|
172
|
+
export declare function useSupabaseSessionCompat(): {
|
|
173
|
+
user: SupabaseCompatUser;
|
|
174
|
+
expires_at: number | undefined;
|
|
175
|
+
} | null;
|
|
176
|
+
/** `supabase.auth.signOut()` in the browser. */
|
|
177
|
+
export declare function supabaseSignOutCompat(): Promise<{
|
|
178
|
+
error: null;
|
|
179
|
+
}>;
|
|
180
|
+
/** `supabase.auth.signInWithOAuth({ provider, options: { redirectTo } })`: opens your sign-in page. */
|
|
181
|
+
export declare function supabaseSignInWithOAuthCompat(credentials?: {
|
|
182
|
+
provider?: string;
|
|
183
|
+
options?: {
|
|
184
|
+
redirectTo?: string;
|
|
185
|
+
signInUrl?: string;
|
|
186
|
+
};
|
|
187
|
+
}): Promise<{
|
|
188
|
+
data: {
|
|
189
|
+
provider?: string;
|
|
190
|
+
url: string;
|
|
191
|
+
};
|
|
192
|
+
error: null;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* `supabase.auth.onAuthStateChange(callback)`: the callback fires with
|
|
196
|
+
* `SIGNED_IN` / `SIGNED_OUT` / `USER_UPDATED` as the Atlas session changes.
|
|
197
|
+
*/
|
|
198
|
+
export declare function onSupabaseAuthStateChangeCompat(callback: (event: 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT' | 'USER_UPDATED', session: {
|
|
199
|
+
user: SupabaseCompatUser;
|
|
200
|
+
} | null) => void): {
|
|
201
|
+
data: {
|
|
202
|
+
subscription: {
|
|
203
|
+
unsubscribe(): void;
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
/** The `{ user, session }` pair Better Auth's `useSession()` / `getSession()` return. */
|
|
208
|
+
export interface BetterAuthCompatSession {
|
|
209
|
+
user: {
|
|
210
|
+
id: string;
|
|
211
|
+
email: string | null;
|
|
212
|
+
emailVerified: boolean;
|
|
213
|
+
name: string | null;
|
|
214
|
+
image: string | null;
|
|
215
|
+
};
|
|
216
|
+
session: {
|
|
217
|
+
id: string;
|
|
218
|
+
userId: string;
|
|
219
|
+
expiresAt: Date;
|
|
220
|
+
activeOrganizationId: string | null;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
export declare function betterAuthSessionFrom(state: Pick<ActiveAtlas, 'status' | 'user' | 'claims'>): BetterAuthCompatSession | null;
|
|
224
|
+
export interface BetterAuthCompatClientOptions {
|
|
225
|
+
/** Where your Atlas sign-in page lives (default `/sign-in`). */
|
|
226
|
+
signInUrl?: string;
|
|
227
|
+
/** Where your Atlas sign-up page lives (default `/sign-up`). */
|
|
228
|
+
signUpUrl?: string;
|
|
229
|
+
/** Accepted (and ignored) so `createAuthClient({ baseURL })` call sites keep compiling. */
|
|
230
|
+
baseURL?: string;
|
|
231
|
+
[option: string]: unknown;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* `createAuthClient()` from `better-auth/react`, on Atlas. The returned object has
|
|
235
|
+
* the same `useSession`, `getSession`, `signIn.social`, `signIn.email`, `signUp.email`
|
|
236
|
+
* and `signOut` members. The sign-in/up members open your Atlas pages (Atlas
|
|
237
|
+
* collects credentials on its own forms, never in app code).
|
|
238
|
+
*/
|
|
239
|
+
export declare function createBetterAuthCompatClient(options?: BetterAuthCompatClientOptions): {
|
|
240
|
+
/** Type-only, like Better Auth's `authClient.$Infer.Session`. */
|
|
241
|
+
$Infer: {
|
|
242
|
+
Session: BetterAuthCompatSession;
|
|
243
|
+
};
|
|
244
|
+
useSession(): {
|
|
245
|
+
data: BetterAuthCompatSession | null;
|
|
246
|
+
isPending: boolean;
|
|
247
|
+
error: null;
|
|
248
|
+
refetch: () => Promise<void>;
|
|
249
|
+
};
|
|
250
|
+
getSession(): Promise<{
|
|
251
|
+
data: BetterAuthCompatSession | null;
|
|
252
|
+
error: null;
|
|
253
|
+
}>;
|
|
254
|
+
signIn: {
|
|
255
|
+
social(input?: {
|
|
256
|
+
provider?: string;
|
|
257
|
+
callbackURL?: string;
|
|
258
|
+
}): Promise<{
|
|
259
|
+
data: {
|
|
260
|
+
redirect: boolean;
|
|
261
|
+
};
|
|
262
|
+
error: null;
|
|
263
|
+
}>;
|
|
264
|
+
email(input?: {
|
|
265
|
+
callbackURL?: string;
|
|
266
|
+
}): Promise<{
|
|
267
|
+
data: {
|
|
268
|
+
redirect: boolean;
|
|
269
|
+
};
|
|
270
|
+
error: null;
|
|
271
|
+
}>;
|
|
272
|
+
magicLink(input?: {
|
|
273
|
+
callbackURL?: string;
|
|
274
|
+
}): Promise<{
|
|
275
|
+
data: {
|
|
276
|
+
redirect: boolean;
|
|
277
|
+
};
|
|
278
|
+
error: null;
|
|
279
|
+
}>;
|
|
280
|
+
passkey(): Promise<{
|
|
281
|
+
data: {
|
|
282
|
+
redirect: boolean;
|
|
283
|
+
};
|
|
284
|
+
error: null;
|
|
285
|
+
}>;
|
|
286
|
+
};
|
|
287
|
+
signUp: {
|
|
288
|
+
email(input?: {
|
|
289
|
+
callbackURL?: string;
|
|
290
|
+
}): Promise<{
|
|
291
|
+
data: {
|
|
292
|
+
redirect: boolean;
|
|
293
|
+
};
|
|
294
|
+
error: null;
|
|
295
|
+
}>;
|
|
296
|
+
};
|
|
297
|
+
signOut(input?: {
|
|
298
|
+
fetchOptions?: {
|
|
299
|
+
onSuccess?: () => void;
|
|
300
|
+
};
|
|
301
|
+
}): Promise<{
|
|
302
|
+
data: {
|
|
303
|
+
success: boolean;
|
|
304
|
+
};
|
|
305
|
+
error: null;
|
|
306
|
+
}>;
|
|
307
|
+
};
|
package/dist/compat.js
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.LoginRequiredError = exports.getActiveAtlas = void 0;
|
|
5
|
+
exports.primaryEmail = primaryEmail;
|
|
6
|
+
exports.displayName = displayName;
|
|
7
|
+
exports.signInRedirect = signInRedirect;
|
|
8
|
+
exports.nextAuthSessionFrom = nextAuthSessionFrom;
|
|
9
|
+
exports.useNextAuthSession = useNextAuthSession;
|
|
10
|
+
exports.getNextAuthSession = getNextAuthSession;
|
|
11
|
+
exports.nextAuthSignIn = nextAuthSignIn;
|
|
12
|
+
exports.nextAuthSignOut = nextAuthSignOut;
|
|
13
|
+
exports.auth0UserFrom = auth0UserFrom;
|
|
14
|
+
exports.useAuth0Compat = useAuth0Compat;
|
|
15
|
+
exports.useAuth0UserCompat = useAuth0UserCompat;
|
|
16
|
+
exports.withAuthenticationRequiredCompat = withAuthenticationRequiredCompat;
|
|
17
|
+
exports.supabaseUserFrom = supabaseUserFrom;
|
|
18
|
+
exports.getSupabaseUserCompat = getSupabaseUserCompat;
|
|
19
|
+
exports.getSupabaseSessionCompat = getSupabaseSessionCompat;
|
|
20
|
+
exports.useSupabaseUserCompat = useSupabaseUserCompat;
|
|
21
|
+
exports.useSupabaseSessionCompat = useSupabaseSessionCompat;
|
|
22
|
+
exports.supabaseSignOutCompat = supabaseSignOutCompat;
|
|
23
|
+
exports.supabaseSignInWithOAuthCompat = supabaseSignInWithOAuthCompat;
|
|
24
|
+
exports.onSupabaseAuthStateChangeCompat = onSupabaseAuthStateChangeCompat;
|
|
25
|
+
exports.betterAuthSessionFrom = betterAuthSessionFrom;
|
|
26
|
+
exports.createBetterAuthCompatClient = createBetterAuthCompatClient;
|
|
27
|
+
/**
|
|
28
|
+
* Drop-in compatibility helpers for apps moving to Atlas from Auth.js (NextAuth),
|
|
29
|
+
* Auth0 (auth0-react / nextjs-auth0), Supabase Auth and Better Auth.
|
|
30
|
+
*
|
|
31
|
+
* `atlas migrate code --from <vendor>` rewrites an app's imports onto these, so
|
|
32
|
+
* the migrated code keeps the shapes it was written against (`{ data, status }`
|
|
33
|
+
* from `useSession`, `{ isAuthenticated, user }` from `useAuth0`, …) and compiles
|
|
34
|
+
* and runs on day one. Each helper is a thin projection over the native hooks
|
|
35
|
+
* (`useUser`, `useAuth`); once migrated, move call sites to those at your own pace.
|
|
36
|
+
*
|
|
37
|
+
* The imperative helpers (`nextAuthSignOut()`, `getSupabaseUserCompat()`, …) work
|
|
38
|
+
* outside React components too: they act on the `<AtlasProvider>` mounted on the
|
|
39
|
+
* page. Calling one with no provider mounted throws a clear error.
|
|
40
|
+
*/
|
|
41
|
+
const react_1 = require("react");
|
|
42
|
+
const AtlasProvider_1 = require("./AtlasProvider");
|
|
43
|
+
const components_shared_1 = require("./components-shared");
|
|
44
|
+
const active_atlas_1 = require("./active-atlas");
|
|
45
|
+
var active_atlas_2 = require("./active-atlas");
|
|
46
|
+
Object.defineProperty(exports, "getActiveAtlas", { enumerable: true, get: function () { return active_atlas_2.getActiveAtlas; } });
|
|
47
|
+
// ---- shared user projection --------------------------------------------------
|
|
48
|
+
/** The primary email address, else the first verified one, else any. */
|
|
49
|
+
function primaryEmail(user) {
|
|
50
|
+
const list = user?.email_addresses ?? [];
|
|
51
|
+
const pick = list.find((e) => e.primary) ?? list.find((e) => e.verified) ?? list[0];
|
|
52
|
+
return pick ? { address: pick.email_address, verified: pick.verified } : null;
|
|
53
|
+
}
|
|
54
|
+
/** A display name: first + last, else the username, else null. */
|
|
55
|
+
function displayName(user) {
|
|
56
|
+
if (!user)
|
|
57
|
+
return null;
|
|
58
|
+
const full = [user.first_name, user.last_name].filter(Boolean).join(' ').trim();
|
|
59
|
+
return full || user.username || null;
|
|
60
|
+
}
|
|
61
|
+
function expiresIso(claims) {
|
|
62
|
+
const exp = typeof claims?.exp === 'number' ? claims.exp * 1000 : Date.now() + 60_000;
|
|
63
|
+
return new Date(exp).toISOString();
|
|
64
|
+
}
|
|
65
|
+
function signInUrlWith(options = {}) {
|
|
66
|
+
return (0, components_shared_1.withRedirect)(options.signInUrl ?? '/sign-in', options.redirectUrl);
|
|
67
|
+
}
|
|
68
|
+
/** Send the browser to your sign-in page, returning to `redirectUrl` afterwards. */
|
|
69
|
+
function signInRedirect(options = {}) {
|
|
70
|
+
(0, components_shared_1.navigateTo)(signInUrlWith(options));
|
|
71
|
+
}
|
|
72
|
+
async function signOutThenGo(helper, returnTo) {
|
|
73
|
+
await (0, active_atlas_1.requireActive)(helper).signOut();
|
|
74
|
+
if (returnTo !== false)
|
|
75
|
+
(0, components_shared_1.navigateTo)(returnTo ?? '/');
|
|
76
|
+
}
|
|
77
|
+
/** Pure projection of the provider state onto next-auth's session shape. */
|
|
78
|
+
function nextAuthSessionFrom(state) {
|
|
79
|
+
if (state.status === 'loading')
|
|
80
|
+
return { data: null, status: 'loading' };
|
|
81
|
+
if (state.status !== 'signed_in' || !state.user)
|
|
82
|
+
return { data: null, status: 'unauthenticated' };
|
|
83
|
+
const email = primaryEmail(state.user);
|
|
84
|
+
return {
|
|
85
|
+
data: {
|
|
86
|
+
user: {
|
|
87
|
+
id: state.user.id,
|
|
88
|
+
name: displayName(state.user),
|
|
89
|
+
email: email?.address ?? null,
|
|
90
|
+
image: state.user.image_url,
|
|
91
|
+
},
|
|
92
|
+
expires: expiresIso(state.claims),
|
|
93
|
+
},
|
|
94
|
+
status: 'authenticated',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** `useSession()` from `next-auth/react`, on Atlas: `{ data, status, update }`. */
|
|
98
|
+
function useNextAuthSession() {
|
|
99
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
100
|
+
const projected = nextAuthSessionFrom(atlas);
|
|
101
|
+
return {
|
|
102
|
+
...projected,
|
|
103
|
+
update: async () => {
|
|
104
|
+
await atlas.reload();
|
|
105
|
+
const now = (0, active_atlas_1.getActiveAtlas)() ?? atlas;
|
|
106
|
+
return nextAuthSessionFrom(now).data;
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** `getSession()` from `next-auth/react` (client side): the current session or null. */
|
|
111
|
+
async function getNextAuthSession() {
|
|
112
|
+
return nextAuthSessionFrom((0, active_atlas_1.requireActive)('getNextAuthSession')).data;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* `signIn()` from `next-auth/react`: opens your Atlas sign-in page. The provider
|
|
116
|
+
* argument is accepted for compatibility; the sign-in page lists every enabled
|
|
117
|
+
* method (render `<SocialSignInButton provider="github" />` to go straight to one).
|
|
118
|
+
*/
|
|
119
|
+
async function nextAuthSignIn(_provider, options = {}) {
|
|
120
|
+
signInRedirect({ signInUrl: options.signInUrl, redirectUrl: options.redirectTo ?? options.callbackUrl });
|
|
121
|
+
}
|
|
122
|
+
/** `signOut()` from `next-auth/react`: signs out, then goes to `callbackUrl` (default `/`). */
|
|
123
|
+
async function nextAuthSignOut(options = {}) {
|
|
124
|
+
await signOutThenGo('nextAuthSignOut', options.redirect === false ? false : (options.redirectTo ?? options.callbackUrl));
|
|
125
|
+
}
|
|
126
|
+
/** Project an Atlas user onto the OIDC profile shape Auth0 SDKs return. */
|
|
127
|
+
function auth0UserFrom(user, claims = null) {
|
|
128
|
+
if (!user)
|
|
129
|
+
return undefined;
|
|
130
|
+
const email = primaryEmail(user);
|
|
131
|
+
const out = { sub: user.id };
|
|
132
|
+
const name = displayName(user);
|
|
133
|
+
if (name)
|
|
134
|
+
out.name = name;
|
|
135
|
+
if (user.first_name)
|
|
136
|
+
out.given_name = user.first_name;
|
|
137
|
+
if (user.last_name)
|
|
138
|
+
out.family_name = user.last_name;
|
|
139
|
+
if (user.username)
|
|
140
|
+
out.nickname = user.username;
|
|
141
|
+
if (user.image_url)
|
|
142
|
+
out.picture = user.image_url;
|
|
143
|
+
if (email) {
|
|
144
|
+
out.email = email.address;
|
|
145
|
+
out.email_verified = email.verified;
|
|
146
|
+
}
|
|
147
|
+
if (claims?.org_id)
|
|
148
|
+
out.org_id = claims.org_id;
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/** Thrown by `getAccessTokenSilently()` when nobody is signed in (Auth0's `login_required`). */
|
|
152
|
+
class LoginRequiredError extends Error {
|
|
153
|
+
error = 'login_required';
|
|
154
|
+
constructor() {
|
|
155
|
+
super('Login required');
|
|
156
|
+
this.name = 'LoginRequiredError';
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.LoginRequiredError = LoginRequiredError;
|
|
160
|
+
/** `useAuth0()` from `@auth0/auth0-react`, on Atlas. */
|
|
161
|
+
function useAuth0Compat() {
|
|
162
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
163
|
+
return {
|
|
164
|
+
isLoading: atlas.status === 'loading',
|
|
165
|
+
isAuthenticated: atlas.status === 'signed_in',
|
|
166
|
+
user: atlas.status === 'signed_in' ? auth0UserFrom(atlas.user, atlas.claims) : undefined,
|
|
167
|
+
error: undefined,
|
|
168
|
+
loginWithRedirect: async (options = {}) => signInRedirect({ signInUrl: options.signInUrl, redirectUrl: options.appState?.returnTo }),
|
|
169
|
+
logout: async (options = {}) => {
|
|
170
|
+
await atlas.signOut();
|
|
171
|
+
if (options.openUrl !== false)
|
|
172
|
+
(0, components_shared_1.navigateTo)(options.logoutParams?.returnTo ?? '/');
|
|
173
|
+
},
|
|
174
|
+
getAccessTokenSilently: async (options) => {
|
|
175
|
+
const token = await atlas.getToken(options);
|
|
176
|
+
if (!token)
|
|
177
|
+
throw new LoginRequiredError();
|
|
178
|
+
return token;
|
|
179
|
+
},
|
|
180
|
+
getIdTokenClaims: async () => atlas.claims ?? undefined,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/** `useUser()` from `@auth0/nextjs-auth0/client` (v3) or `@auth0/nextjs-auth0` (v4). */
|
|
184
|
+
function useAuth0UserCompat() {
|
|
185
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
186
|
+
const refresh = async () => {
|
|
187
|
+
await atlas.reload();
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
user: atlas.status === 'signed_in' ? auth0UserFrom(atlas.user, atlas.claims) : undefined,
|
|
191
|
+
error: undefined,
|
|
192
|
+
isLoading: atlas.status === 'loading',
|
|
193
|
+
checkSession: refresh,
|
|
194
|
+
invalidate: refresh,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* `withAuthenticationRequired(Component, options)` from `@auth0/auth0-react` (and
|
|
199
|
+
* nextjs-auth0's client `withPageAuthRequired`): renders the component only for a
|
|
200
|
+
* signed-in user and sends everyone else to your sign-in page.
|
|
201
|
+
*/
|
|
202
|
+
function withAuthenticationRequiredCompat(Component, options = {}) {
|
|
203
|
+
function Guarded(props) {
|
|
204
|
+
const { status } = (0, AtlasProvider_1.useAtlas)();
|
|
205
|
+
(0, react_1.useEffect)(() => {
|
|
206
|
+
if (status !== 'signed_out')
|
|
207
|
+
return;
|
|
208
|
+
const returnTo = typeof options.returnTo === 'function'
|
|
209
|
+
? options.returnTo()
|
|
210
|
+
: (options.returnTo ?? (typeof window === 'undefined' ? undefined : window.location.href));
|
|
211
|
+
signInRedirect({ signInUrl: options.signInUrl, redirectUrl: returnTo });
|
|
212
|
+
}, [status]);
|
|
213
|
+
if (status === 'signed_in')
|
|
214
|
+
return (0, react_1.createElement)(Component, props);
|
|
215
|
+
return (0, react_1.createElement)(react_1.Fragment, null, options.onRedirecting?.() ?? null);
|
|
216
|
+
}
|
|
217
|
+
Guarded.displayName = `withAuthenticationRequired(${Component.displayName ?? Component.name ?? 'Component'})`;
|
|
218
|
+
return Guarded;
|
|
219
|
+
}
|
|
220
|
+
function supabaseUserFrom(user) {
|
|
221
|
+
if (!user)
|
|
222
|
+
return null;
|
|
223
|
+
const email = primaryEmail(user);
|
|
224
|
+
const phone = (user.phone_numbers ?? []).find((p) => p.primary) ?? user.phone_numbers?.[0];
|
|
225
|
+
const name = displayName(user);
|
|
226
|
+
return {
|
|
227
|
+
id: user.id,
|
|
228
|
+
aud: 'authenticated',
|
|
229
|
+
role: 'authenticated',
|
|
230
|
+
...(email ? { email: email.address } : {}),
|
|
231
|
+
...(email?.verified ? { email_confirmed_at: new Date(0).toISOString() } : {}),
|
|
232
|
+
...(phone ? { phone: phone.phone_number } : {}),
|
|
233
|
+
user_metadata: {
|
|
234
|
+
...user.unsafe_metadata,
|
|
235
|
+
...(name ? { full_name: name, name } : {}),
|
|
236
|
+
...(user.image_url ? { avatar_url: user.image_url } : {}),
|
|
237
|
+
},
|
|
238
|
+
app_metadata: { ...user.public_metadata },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/** `supabase.auth.getUser()` in the browser. */
|
|
242
|
+
async function getSupabaseUserCompat() {
|
|
243
|
+
const atlas = (0, active_atlas_1.requireActive)('getSupabaseUserCompat');
|
|
244
|
+
return { data: { user: atlas.status === 'signed_in' ? supabaseUserFrom(atlas.user) : null }, error: null };
|
|
245
|
+
}
|
|
246
|
+
/** `supabase.auth.getSession()` in the browser; `access_token` is the Atlas session JWT. */
|
|
247
|
+
async function getSupabaseSessionCompat() {
|
|
248
|
+
const atlas = (0, active_atlas_1.requireActive)('getSupabaseSessionCompat');
|
|
249
|
+
const user = atlas.status === 'signed_in' ? supabaseUserFrom(atlas.user) : null;
|
|
250
|
+
const token = user ? await atlas.getToken() : null;
|
|
251
|
+
if (!user || !token)
|
|
252
|
+
return { data: { session: null }, error: null };
|
|
253
|
+
return { data: { session: { access_token: token, expires_at: atlas.claims?.exp, user } }, error: null };
|
|
254
|
+
}
|
|
255
|
+
/** `useUser()` from `@supabase/auth-helpers-react`: the user, or null. */
|
|
256
|
+
function useSupabaseUserCompat() {
|
|
257
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
258
|
+
return atlas.status === 'signed_in' ? supabaseUserFrom(atlas.user) : null;
|
|
259
|
+
}
|
|
260
|
+
/** `useSession()` from `@supabase/auth-helpers-react`: `{ user, expires_at }`, or null. */
|
|
261
|
+
function useSupabaseSessionCompat() {
|
|
262
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
263
|
+
const user = atlas.status === 'signed_in' ? supabaseUserFrom(atlas.user) : null;
|
|
264
|
+
return user ? { user, expires_at: atlas.claims?.exp } : null;
|
|
265
|
+
}
|
|
266
|
+
/** `supabase.auth.signOut()` in the browser. */
|
|
267
|
+
async function supabaseSignOutCompat() {
|
|
268
|
+
await (0, active_atlas_1.requireActive)('supabaseSignOutCompat').signOut();
|
|
269
|
+
return { error: null };
|
|
270
|
+
}
|
|
271
|
+
/** `supabase.auth.signInWithOAuth({ provider, options: { redirectTo } })`: opens your sign-in page. */
|
|
272
|
+
async function supabaseSignInWithOAuthCompat(credentials = {}) {
|
|
273
|
+
const url = signInUrlWith({ signInUrl: credentials.options?.signInUrl, redirectUrl: credentials.options?.redirectTo });
|
|
274
|
+
(0, components_shared_1.navigateTo)(url);
|
|
275
|
+
return { data: { provider: credentials.provider, url }, error: null };
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* `supabase.auth.onAuthStateChange(callback)`: the callback fires with
|
|
279
|
+
* `SIGNED_IN` / `SIGNED_OUT` / `USER_UPDATED` as the Atlas session changes.
|
|
280
|
+
*/
|
|
281
|
+
function onSupabaseAuthStateChangeCompat(callback) {
|
|
282
|
+
let last = { status: null, user: null };
|
|
283
|
+
const listener = (atlas) => {
|
|
284
|
+
const status = atlas?.status ?? null;
|
|
285
|
+
if (status === 'loading' || status === null)
|
|
286
|
+
return;
|
|
287
|
+
const current = status === 'signed_in' ? (atlas.user ?? null) : null;
|
|
288
|
+
let event = null;
|
|
289
|
+
if (last.status === null)
|
|
290
|
+
event = 'INITIAL_SESSION';
|
|
291
|
+
else if (status === 'signed_out')
|
|
292
|
+
event = last.status === 'signed_in' ? 'SIGNED_OUT' : null;
|
|
293
|
+
else if (last.status !== 'signed_in' || last.user?.id !== current?.id)
|
|
294
|
+
event = 'SIGNED_IN';
|
|
295
|
+
// Same user, new profile object: the provider reloaded the user.
|
|
296
|
+
else if (current !== last.user)
|
|
297
|
+
event = 'USER_UPDATED';
|
|
298
|
+
last = { status, user: current };
|
|
299
|
+
const mapped = supabaseUserFrom(current);
|
|
300
|
+
if (event)
|
|
301
|
+
callback(event, mapped ? { user: mapped } : null);
|
|
302
|
+
};
|
|
303
|
+
const unsubscribe = (0, active_atlas_1.onActiveAtlasChange)(listener);
|
|
304
|
+
const current = (0, active_atlas_1.getActiveAtlas)();
|
|
305
|
+
if (current)
|
|
306
|
+
listener(current);
|
|
307
|
+
return { data: { subscription: { unsubscribe } } };
|
|
308
|
+
}
|
|
309
|
+
function betterAuthSessionFrom(state) {
|
|
310
|
+
if (state.status !== 'signed_in' || !state.user)
|
|
311
|
+
return null;
|
|
312
|
+
const email = primaryEmail(state.user);
|
|
313
|
+
return {
|
|
314
|
+
user: {
|
|
315
|
+
id: state.user.id,
|
|
316
|
+
email: email?.address ?? null,
|
|
317
|
+
emailVerified: email?.verified ?? false,
|
|
318
|
+
name: displayName(state.user),
|
|
319
|
+
image: state.user.image_url,
|
|
320
|
+
},
|
|
321
|
+
session: {
|
|
322
|
+
id: state.claims?.sid ?? '',
|
|
323
|
+
userId: state.user.id,
|
|
324
|
+
expiresAt: new Date(expiresIso(state.claims)),
|
|
325
|
+
activeOrganizationId: state.claims?.org_id ?? null,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* `createAuthClient()` from `better-auth/react`, on Atlas. The returned object has
|
|
331
|
+
* the same `useSession`, `getSession`, `signIn.social`, `signIn.email`, `signUp.email`
|
|
332
|
+
* and `signOut` members. The sign-in/up members open your Atlas pages (Atlas
|
|
333
|
+
* collects credentials on its own forms, never in app code).
|
|
334
|
+
*/
|
|
335
|
+
function createBetterAuthCompatClient(options = {}) {
|
|
336
|
+
const goSignIn = (callbackURL) => (0, components_shared_1.navigateTo)((0, components_shared_1.withRedirect)(options.signInUrl ?? '/sign-in', callbackURL));
|
|
337
|
+
const goSignUp = (callbackURL) => (0, components_shared_1.navigateTo)((0, components_shared_1.withRedirect)(options.signUpUrl ?? '/sign-up', callbackURL));
|
|
338
|
+
const ok = (data) => ({ data, error: null });
|
|
339
|
+
return {
|
|
340
|
+
/** Type-only, like Better Auth's `authClient.$Infer.Session`. */
|
|
341
|
+
$Infer: {},
|
|
342
|
+
useSession() {
|
|
343
|
+
const atlas = (0, AtlasProvider_1.useAtlas)();
|
|
344
|
+
return {
|
|
345
|
+
data: betterAuthSessionFrom(atlas),
|
|
346
|
+
isPending: atlas.status === 'loading',
|
|
347
|
+
error: null,
|
|
348
|
+
refetch: async () => {
|
|
349
|
+
await atlas.reload();
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
},
|
|
353
|
+
async getSession() {
|
|
354
|
+
return ok(betterAuthSessionFrom((0, active_atlas_1.requireActive)('authClient.getSession')));
|
|
355
|
+
},
|
|
356
|
+
signIn: {
|
|
357
|
+
async social(input = {}) {
|
|
358
|
+
goSignIn(input.callbackURL);
|
|
359
|
+
return ok({ redirect: true });
|
|
360
|
+
},
|
|
361
|
+
async email(input = {}) {
|
|
362
|
+
goSignIn(input.callbackURL);
|
|
363
|
+
return ok({ redirect: true });
|
|
364
|
+
},
|
|
365
|
+
async magicLink(input = {}) {
|
|
366
|
+
goSignIn(input.callbackURL);
|
|
367
|
+
return ok({ redirect: true });
|
|
368
|
+
},
|
|
369
|
+
async passkey() {
|
|
370
|
+
goSignIn();
|
|
371
|
+
return ok({ redirect: true });
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
signUp: {
|
|
375
|
+
async email(input = {}) {
|
|
376
|
+
goSignUp(input.callbackURL);
|
|
377
|
+
return ok({ redirect: true });
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
async signOut(input = {}) {
|
|
381
|
+
await (0, active_atlas_1.requireActive)('authClient.signOut').signOut();
|
|
382
|
+
input.fetchOptions?.onSuccess?.();
|
|
383
|
+
return ok({ success: true });
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=compat.js.map
|