@instroc/auth 1.0.1 → 1.0.2
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/index.d.ts +118 -118
- package/dist/index.js +28 -9
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
interface AuthUser {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
email_verified: boolean;
|
|
5
|
+
display_name: string | null;
|
|
6
|
+
avatar_url: string | null;
|
|
7
|
+
metadata: Record<string, unknown>;
|
|
8
|
+
created_at: string;
|
|
9
9
|
}
|
|
10
10
|
interface AuthSession {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
access_token: string;
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
expires_at: string;
|
|
14
14
|
}
|
|
15
15
|
interface AuthState {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
user: AuthUser | null;
|
|
17
|
+
session: AuthSession | null;
|
|
18
|
+
loading: boolean;
|
|
19
|
+
error: string | null;
|
|
20
20
|
}
|
|
21
21
|
interface LoginCredentials {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
email: string;
|
|
23
|
+
password: string;
|
|
24
24
|
}
|
|
25
25
|
interface SignupCredentials {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
email: string;
|
|
27
|
+
password: string;
|
|
28
|
+
displayName?: string;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
30
|
}
|
|
31
31
|
type OAuthProvider = "google" | "github" | "microsoft" | "facebook";
|
|
32
32
|
interface AuthConfig {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
emailAuthEnabled: boolean;
|
|
34
|
+
googleAuthEnabled: boolean;
|
|
35
|
+
githubAuthEnabled: boolean;
|
|
36
|
+
microsoftAuthEnabled: boolean;
|
|
37
|
+
facebookAuthEnabled: boolean;
|
|
38
|
+
allowSignup: boolean;
|
|
39
|
+
requireEmailVerification: boolean;
|
|
40
40
|
}
|
|
41
41
|
interface VisibilityConfig {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
projectName: string;
|
|
43
|
+
visibility: "public" | "private";
|
|
44
|
+
requireLogin: boolean;
|
|
45
|
+
logoUrl: string | null;
|
|
46
|
+
welcomeMessage: string | null;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Result of signup() — indicates what post-signup flow the caller should show.
|
|
@@ -52,108 +52,108 @@ interface VisibilityConfig {
|
|
|
52
52
|
* - `status: "needs_verification"` — email verification OTP was sent. Show OTP screen.
|
|
53
53
|
* - `status: "needs_approval"` — account pending admin approval. Show waiting screen.
|
|
54
54
|
*/
|
|
55
|
-
type SignupResult =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
status: "needs_approval";
|
|
66
|
-
user: AuthUser;
|
|
67
|
-
};
|
|
55
|
+
type SignupResult = {
|
|
56
|
+
status: "authenticated";
|
|
57
|
+
user: AuthUser;
|
|
58
|
+
} | {
|
|
59
|
+
status: "needs_verification";
|
|
60
|
+
email: string;
|
|
61
|
+
} | {
|
|
62
|
+
status: "needs_approval";
|
|
63
|
+
user: AuthUser;
|
|
64
|
+
};
|
|
68
65
|
interface AuthContextValue extends AuthState {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
66
|
+
login: (credentials: LoginCredentials) => Promise<void>;
|
|
67
|
+
signup: (credentials: SignupCredentials) => Promise<SignupResult>;
|
|
68
|
+
logout: () => Promise<void>;
|
|
69
|
+
signInWithOAuth: (provider: OAuthProvider) => void;
|
|
70
|
+
verifyOTP: (email: string, code: string) => Promise<void>;
|
|
71
|
+
resendOTP: (email: string) => Promise<void>;
|
|
72
|
+
updateProfile: (data: UpdateProfileData) => Promise<void>;
|
|
73
|
+
refreshSession: () => Promise<void>;
|
|
74
|
+
forgotPassword: (email: string) => Promise<void>;
|
|
75
|
+
resetPassword: (token: string, newPassword: string) => Promise<void>;
|
|
76
|
+
setProjectId: (projectId: string) => void;
|
|
77
|
+
projectId: string | null;
|
|
78
|
+
authConfig: AuthConfig | null;
|
|
79
|
+
visibilityConfig: VisibilityConfig | null;
|
|
83
80
|
}
|
|
84
81
|
interface UpdateProfileData {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
displayName?: string;
|
|
83
|
+
avatarUrl?: string;
|
|
84
|
+
metadata?: Record<string, unknown>;
|
|
88
85
|
}
|
|
89
86
|
interface AuthProviderProps {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
children: React.ReactNode;
|
|
88
|
+
projectId?: string;
|
|
89
|
+
baseUrl?: string;
|
|
90
|
+
persistSession?: boolean;
|
|
91
|
+
onAuthStateChange?: (user: AuthUser | null) => void;
|
|
95
92
|
}
|
|
96
93
|
interface AuthResponse {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
user: AuthUser;
|
|
95
|
+
session: AuthSession;
|
|
96
|
+
/** Set when signup requires email verification — session is a placeholder with empty tokens. */
|
|
97
|
+
needsVerification?: boolean;
|
|
98
|
+
/** Set when signup succeeded but account is pending admin approval (private apps). */
|
|
99
|
+
needsApproval?: boolean;
|
|
103
100
|
}
|
|
104
101
|
interface RefreshResponse {
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
access_token: string;
|
|
103
|
+
expires_at: string;
|
|
107
104
|
}
|
|
108
105
|
|
|
109
|
-
declare function AuthProvider({
|
|
110
|
-
children,
|
|
111
|
-
projectId: initialProjectId,
|
|
112
|
-
baseUrl,
|
|
113
|
-
persistSession,
|
|
114
|
-
onAuthStateChange,
|
|
115
|
-
}: AuthProviderProps): JSX.Element;
|
|
106
|
+
declare function AuthProvider({ children, projectId: initialProjectId, baseUrl, persistSession, onAuthStateChange, }: AuthProviderProps): JSX.Element;
|
|
116
107
|
declare function useAuthContext(): AuthContextValue;
|
|
117
108
|
|
|
118
109
|
declare function useAuth(): AuthContextValue;
|
|
119
110
|
declare function useUser(): {
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
user: AuthUser | null;
|
|
112
|
+
loading: boolean;
|
|
122
113
|
};
|
|
123
114
|
declare function useSession(): {
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
session: AuthSession | null;
|
|
116
|
+
loading: boolean;
|
|
126
117
|
};
|
|
127
|
-
declare function useAuthRequired():
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
session: AuthSession | null;
|
|
136
|
-
loading: boolean;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export {
|
|
140
|
-
type AuthConfig,
|
|
141
|
-
type AuthContextValue,
|
|
142
|
-
AuthProvider,
|
|
143
|
-
type AuthProviderProps,
|
|
144
|
-
type AuthResponse,
|
|
145
|
-
type AuthSession,
|
|
146
|
-
type AuthState,
|
|
147
|
-
type AuthUser,
|
|
148
|
-
type LoginCredentials,
|
|
149
|
-
type OAuthProvider,
|
|
150
|
-
type RefreshResponse,
|
|
151
|
-
type SignupCredentials,
|
|
152
|
-
type UpdateProfileData,
|
|
153
|
-
type VisibilityConfig,
|
|
154
|
-
useAuth,
|
|
155
|
-
useAuthContext,
|
|
156
|
-
useAuthRequired,
|
|
157
|
-
useSession,
|
|
158
|
-
useUser,
|
|
118
|
+
declare function useAuthRequired(): {
|
|
119
|
+
user: null;
|
|
120
|
+
session: null;
|
|
121
|
+
loading: boolean;
|
|
122
|
+
} | {
|
|
123
|
+
user: AuthUser;
|
|
124
|
+
session: AuthSession | null;
|
|
125
|
+
loading: boolean;
|
|
159
126
|
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Typed error thrown by every `@instroc/auth` method when the server responds
|
|
130
|
+
* with a non-2xx status. Carries the HTTP status so consumers can branch on
|
|
131
|
+
* behavioural outcomes (429 = cooldown UI, 403 = redirect to OTP page, etc.)
|
|
132
|
+
* without string-matching the message.
|
|
133
|
+
*
|
|
134
|
+
* Usage:
|
|
135
|
+
* try {
|
|
136
|
+
* await login({ email, password });
|
|
137
|
+
* } catch (err) {
|
|
138
|
+
* if (err instanceof AuthError) {
|
|
139
|
+
* if (err.status === 429) { setCooldown(60); return; }
|
|
140
|
+
* if (err.status === 403) { onNeedsVerification?.(email); return; }
|
|
141
|
+
* setLocalError(err.message);
|
|
142
|
+
* } else {
|
|
143
|
+
* setLocalError("An unexpected error occurred.");
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
*/
|
|
147
|
+
declare class AuthError extends Error {
|
|
148
|
+
/** HTTP status code from the server (400, 401, 403, 404, 409, 429, 500…). */
|
|
149
|
+
readonly status: number;
|
|
150
|
+
/**
|
|
151
|
+
* Optional machine-readable error code from the server (e.g. `"invalid_credentials"`,
|
|
152
|
+
* `"email_not_verified"`). Present when the server includes a `code` field in the
|
|
153
|
+
* error body; otherwise `undefined`.
|
|
154
|
+
*/
|
|
155
|
+
readonly code?: string;
|
|
156
|
+
constructor(message: string, status: number, code?: string);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { type AuthConfig, type AuthContextValue, AuthError, AuthProvider, type AuthProviderProps, type AuthResponse, type AuthSession, type AuthState, type AuthUser, type LoginCredentials, type OAuthProvider, type RefreshResponse, type SignupCredentials, type SignupResult, type UpdateProfileData, type VisibilityConfig, useAuth, useAuthContext, useAuthRequired, useSession, useUser };
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,24 @@ import {
|
|
|
7
7
|
useEffect,
|
|
8
8
|
useRef
|
|
9
9
|
} from "react";
|
|
10
|
+
|
|
11
|
+
// src/errors.ts
|
|
12
|
+
var AuthError = class _AuthError extends Error {
|
|
13
|
+
constructor(message, status, code) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "AuthError";
|
|
16
|
+
this.status = status;
|
|
17
|
+
this.code = code;
|
|
18
|
+
Object.setPrototypeOf(this, _AuthError.prototype);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
function authErrorFromResponse(response, data, fallbackMessage) {
|
|
22
|
+
const body = data ?? {};
|
|
23
|
+
const message = body.error || fallbackMessage;
|
|
24
|
+
return new AuthError(message, response.status, body.code);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/provider.tsx
|
|
10
28
|
import { jsx } from "react/jsx-runtime";
|
|
11
29
|
var AuthContext = createContext(null);
|
|
12
30
|
var STORAGE_KEY = "instroc_auth_session";
|
|
@@ -182,7 +200,7 @@ function AuthProvider({
|
|
|
182
200
|
});
|
|
183
201
|
const data = await response.json();
|
|
184
202
|
if (!response.ok) {
|
|
185
|
-
throw
|
|
203
|
+
throw authErrorFromResponse(response, data, "Login failed");
|
|
186
204
|
}
|
|
187
205
|
const authResponse = data;
|
|
188
206
|
updateAuthState(authResponse.user, authResponse.session);
|
|
@@ -208,7 +226,7 @@ function AuthProvider({
|
|
|
208
226
|
});
|
|
209
227
|
const data = await response.json();
|
|
210
228
|
if (!response.ok) {
|
|
211
|
-
throw
|
|
229
|
+
throw authErrorFromResponse(response, data, "Signup failed");
|
|
212
230
|
}
|
|
213
231
|
const authResponse = data;
|
|
214
232
|
if (authResponse.needsVerification) {
|
|
@@ -261,7 +279,7 @@ function AuthProvider({
|
|
|
261
279
|
const updateProfile = useCallback(
|
|
262
280
|
async (data) => {
|
|
263
281
|
if (!session) {
|
|
264
|
-
throw new
|
|
282
|
+
throw new AuthError("Not authenticated", 401);
|
|
265
283
|
}
|
|
266
284
|
setError(null);
|
|
267
285
|
try {
|
|
@@ -275,7 +293,7 @@ function AuthProvider({
|
|
|
275
293
|
});
|
|
276
294
|
const result = await response.json();
|
|
277
295
|
if (!response.ok) {
|
|
278
|
-
throw
|
|
296
|
+
throw authErrorFromResponse(response, result, "Update failed");
|
|
279
297
|
}
|
|
280
298
|
setUser(result.user);
|
|
281
299
|
} catch (err) {
|
|
@@ -296,7 +314,7 @@ function AuthProvider({
|
|
|
296
314
|
});
|
|
297
315
|
const data = await response.json();
|
|
298
316
|
if (!response.ok) {
|
|
299
|
-
throw
|
|
317
|
+
throw authErrorFromResponse(response, data, "Refresh failed");
|
|
300
318
|
}
|
|
301
319
|
const refreshData = data;
|
|
302
320
|
const newSession = {
|
|
@@ -317,7 +335,7 @@ function AuthProvider({
|
|
|
317
335
|
});
|
|
318
336
|
const data = await response.json();
|
|
319
337
|
if (!response.ok) {
|
|
320
|
-
throw
|
|
338
|
+
throw authErrorFromResponse(response, data, "Request failed");
|
|
321
339
|
}
|
|
322
340
|
} catch (err) {
|
|
323
341
|
const message = err instanceof Error ? err.message : "Request failed";
|
|
@@ -338,7 +356,7 @@ function AuthProvider({
|
|
|
338
356
|
});
|
|
339
357
|
const data = await response.json();
|
|
340
358
|
if (!response.ok) {
|
|
341
|
-
throw
|
|
359
|
+
throw authErrorFromResponse(response, data, "Reset failed");
|
|
342
360
|
}
|
|
343
361
|
} catch (err) {
|
|
344
362
|
const message = err instanceof Error ? err.message : "Reset failed";
|
|
@@ -372,7 +390,7 @@ function AuthProvider({
|
|
|
372
390
|
});
|
|
373
391
|
const data = await response.json();
|
|
374
392
|
if (!response.ok) {
|
|
375
|
-
throw
|
|
393
|
+
throw authErrorFromResponse(response, data, "Verification failed");
|
|
376
394
|
}
|
|
377
395
|
if (data.session) {
|
|
378
396
|
updateAuthState(data.user, data.session);
|
|
@@ -398,7 +416,7 @@ function AuthProvider({
|
|
|
398
416
|
});
|
|
399
417
|
const data = await response.json();
|
|
400
418
|
if (!response.ok) {
|
|
401
|
-
throw
|
|
419
|
+
throw authErrorFromResponse(response, data, "Failed to resend code");
|
|
402
420
|
}
|
|
403
421
|
} catch (err) {
|
|
404
422
|
const message = err instanceof Error ? err.message : "Failed to resend code";
|
|
@@ -541,6 +559,7 @@ function useAuthRequired() {
|
|
|
541
559
|
return { user, session, loading: false };
|
|
542
560
|
}
|
|
543
561
|
export {
|
|
562
|
+
AuthError,
|
|
544
563
|
AuthProvider,
|
|
545
564
|
useAuth,
|
|
546
565
|
useAuthContext,
|