@instroc/auth 1.0.0 → 1.0.1
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 +125 -73
- package/dist/index.js +35 -21
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,107 +1,159 @@
|
|
|
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
|
+
/**
|
|
49
|
+
* Result of signup() — indicates what post-signup flow the caller should show.
|
|
50
|
+
*
|
|
51
|
+
* - `status: "authenticated"` — user is logged in, session is active. Redirect to app.
|
|
52
|
+
* - `status: "needs_verification"` — email verification OTP was sent. Show OTP screen.
|
|
53
|
+
* - `status: "needs_approval"` — account pending admin approval. Show waiting screen.
|
|
54
|
+
*/
|
|
55
|
+
type SignupResult =
|
|
56
|
+
| {
|
|
57
|
+
status: "authenticated";
|
|
58
|
+
user: AuthUser;
|
|
59
|
+
}
|
|
60
|
+
| {
|
|
61
|
+
status: "needs_verification";
|
|
62
|
+
email: string;
|
|
63
|
+
}
|
|
64
|
+
| {
|
|
65
|
+
status: "needs_approval";
|
|
66
|
+
user: AuthUser;
|
|
67
|
+
};
|
|
48
68
|
interface AuthContextValue extends AuthState {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
login: (credentials: LoginCredentials) => Promise<void>;
|
|
70
|
+
signup: (credentials: SignupCredentials) => Promise<SignupResult>;
|
|
71
|
+
logout: () => Promise<void>;
|
|
72
|
+
signInWithOAuth: (provider: OAuthProvider) => void;
|
|
73
|
+
verifyOTP: (email: string, code: string) => Promise<void>;
|
|
74
|
+
resendOTP: (email: string) => Promise<void>;
|
|
75
|
+
updateProfile: (data: UpdateProfileData) => Promise<void>;
|
|
76
|
+
refreshSession: () => Promise<void>;
|
|
77
|
+
forgotPassword: (email: string) => Promise<void>;
|
|
78
|
+
resetPassword: (token: string, newPassword: string) => Promise<void>;
|
|
79
|
+
setProjectId: (projectId: string) => void;
|
|
80
|
+
projectId: string | null;
|
|
81
|
+
authConfig: AuthConfig | null;
|
|
82
|
+
visibilityConfig: VisibilityConfig | null;
|
|
63
83
|
}
|
|
64
84
|
interface UpdateProfileData {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
displayName?: string;
|
|
86
|
+
avatarUrl?: string;
|
|
87
|
+
metadata?: Record<string, unknown>;
|
|
68
88
|
}
|
|
69
89
|
interface AuthProviderProps {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
90
|
+
children: React.ReactNode;
|
|
91
|
+
projectId?: string;
|
|
92
|
+
baseUrl?: string;
|
|
93
|
+
persistSession?: boolean;
|
|
94
|
+
onAuthStateChange?: (user: AuthUser | null) => void;
|
|
75
95
|
}
|
|
76
96
|
interface AuthResponse {
|
|
77
|
-
|
|
78
|
-
|
|
97
|
+
user: AuthUser;
|
|
98
|
+
session: AuthSession;
|
|
99
|
+
/** Set when signup requires email verification — session is a placeholder with empty tokens. */
|
|
100
|
+
needsVerification?: boolean;
|
|
101
|
+
/** Set when signup succeeded but account is pending admin approval (private apps). */
|
|
102
|
+
needsApproval?: boolean;
|
|
79
103
|
}
|
|
80
104
|
interface RefreshResponse {
|
|
81
|
-
|
|
82
|
-
|
|
105
|
+
access_token: string;
|
|
106
|
+
expires_at: string;
|
|
83
107
|
}
|
|
84
108
|
|
|
85
|
-
declare function AuthProvider({
|
|
109
|
+
declare function AuthProvider({
|
|
110
|
+
children,
|
|
111
|
+
projectId: initialProjectId,
|
|
112
|
+
baseUrl,
|
|
113
|
+
persistSession,
|
|
114
|
+
onAuthStateChange,
|
|
115
|
+
}: AuthProviderProps): JSX.Element;
|
|
86
116
|
declare function useAuthContext(): AuthContextValue;
|
|
87
117
|
|
|
88
118
|
declare function useAuth(): AuthContextValue;
|
|
89
119
|
declare function useUser(): {
|
|
90
|
-
|
|
91
|
-
|
|
120
|
+
user: AuthUser | null;
|
|
121
|
+
loading: boolean;
|
|
92
122
|
};
|
|
93
123
|
declare function useSession(): {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
};
|
|
97
|
-
declare function useAuthRequired(): {
|
|
98
|
-
user: null;
|
|
99
|
-
session: null;
|
|
100
|
-
loading: boolean;
|
|
101
|
-
} | {
|
|
102
|
-
user: AuthUser;
|
|
103
|
-
session: AuthSession | null;
|
|
104
|
-
loading: boolean;
|
|
124
|
+
session: AuthSession | null;
|
|
125
|
+
loading: boolean;
|
|
105
126
|
};
|
|
127
|
+
declare function useAuthRequired():
|
|
128
|
+
| {
|
|
129
|
+
user: null;
|
|
130
|
+
session: null;
|
|
131
|
+
loading: boolean;
|
|
132
|
+
}
|
|
133
|
+
| {
|
|
134
|
+
user: AuthUser;
|
|
135
|
+
session: AuthSession | null;
|
|
136
|
+
loading: boolean;
|
|
137
|
+
};
|
|
106
138
|
|
|
107
|
-
export {
|
|
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,
|
|
159
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,10 @@ function AuthProvider({
|
|
|
36
36
|
},
|
|
37
37
|
[projectId, baseUrl]
|
|
38
38
|
);
|
|
39
|
+
const authFetch = useCallback(
|
|
40
|
+
(url, init) => fetch(url, { ...init, credentials: "include" }),
|
|
41
|
+
[]
|
|
42
|
+
);
|
|
39
43
|
const saveSession = useCallback(
|
|
40
44
|
(sessionData) => {
|
|
41
45
|
if (persistSession && typeof window !== "undefined") {
|
|
@@ -74,7 +78,7 @@ function AuthProvider({
|
|
|
74
78
|
try {
|
|
75
79
|
await refreshSession();
|
|
76
80
|
} catch (err) {
|
|
77
|
-
console.
|
|
81
|
+
console.warn("Token refresh failed:", err);
|
|
78
82
|
setUser(null);
|
|
79
83
|
setSession(null);
|
|
80
84
|
saveSession(null);
|
|
@@ -105,7 +109,7 @@ function AuthProvider({
|
|
|
105
109
|
return;
|
|
106
110
|
}
|
|
107
111
|
try {
|
|
108
|
-
const response = await
|
|
112
|
+
const response = await authFetch(buildUrl("me"), {
|
|
109
113
|
headers: {
|
|
110
114
|
Authorization: `Bearer ${storedSession.access_token}`
|
|
111
115
|
}
|
|
@@ -115,7 +119,7 @@ function AuthProvider({
|
|
|
115
119
|
updateAuthState(data.user, storedSession);
|
|
116
120
|
} else if (response.status === 401) {
|
|
117
121
|
try {
|
|
118
|
-
const refreshResponse = await
|
|
122
|
+
const refreshResponse = await authFetch(buildUrl("refresh"), {
|
|
119
123
|
method: "POST",
|
|
120
124
|
headers: { "Content-Type": "application/json" },
|
|
121
125
|
body: JSON.stringify({ refreshToken: storedSession.refresh_token })
|
|
@@ -127,7 +131,7 @@ function AuthProvider({
|
|
|
127
131
|
access_token: refreshData.access_token,
|
|
128
132
|
expires_at: refreshData.expires_at
|
|
129
133
|
};
|
|
130
|
-
const userResponse = await
|
|
134
|
+
const userResponse = await authFetch(buildUrl("me"), {
|
|
131
135
|
headers: {
|
|
132
136
|
Authorization: `Bearer ${newSession.access_token}`
|
|
133
137
|
}
|
|
@@ -171,7 +175,7 @@ function AuthProvider({
|
|
|
171
175
|
setError(null);
|
|
172
176
|
setLoading(true);
|
|
173
177
|
try {
|
|
174
|
-
const response = await
|
|
178
|
+
const response = await authFetch(buildUrl("login"), {
|
|
175
179
|
method: "POST",
|
|
176
180
|
headers: { "Content-Type": "application/json" },
|
|
177
181
|
body: JSON.stringify(credentials)
|
|
@@ -197,7 +201,7 @@ function AuthProvider({
|
|
|
197
201
|
setError(null);
|
|
198
202
|
setLoading(true);
|
|
199
203
|
try {
|
|
200
|
-
const response = await
|
|
204
|
+
const response = await authFetch(buildUrl("signup"), {
|
|
201
205
|
method: "POST",
|
|
202
206
|
headers: { "Content-Type": "application/json" },
|
|
203
207
|
body: JSON.stringify(credentials)
|
|
@@ -207,11 +211,24 @@ function AuthProvider({
|
|
|
207
211
|
throw new Error(data.error || "Signup failed");
|
|
208
212
|
}
|
|
209
213
|
const authResponse = data;
|
|
214
|
+
if (authResponse.needsVerification) {
|
|
215
|
+
return {
|
|
216
|
+
status: "needs_verification",
|
|
217
|
+
email: credentials.email
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
if (authResponse.needsApproval) {
|
|
221
|
+
updateAuthState(authResponse.user, authResponse.session);
|
|
222
|
+
return { status: "needs_approval", user: authResponse.user };
|
|
223
|
+
}
|
|
210
224
|
if (authResponse.session.access_token) {
|
|
211
225
|
updateAuthState(authResponse.user, authResponse.session);
|
|
212
|
-
|
|
213
|
-
setUser(authResponse.user);
|
|
226
|
+
return { status: "authenticated", user: authResponse.user };
|
|
214
227
|
}
|
|
228
|
+
return {
|
|
229
|
+
status: "needs_verification",
|
|
230
|
+
email: credentials.email
|
|
231
|
+
};
|
|
215
232
|
} catch (err) {
|
|
216
233
|
const message = err instanceof Error ? err.message : "Signup failed";
|
|
217
234
|
setError(message);
|
|
@@ -225,7 +242,7 @@ function AuthProvider({
|
|
|
225
242
|
const logout = useCallback(async () => {
|
|
226
243
|
try {
|
|
227
244
|
if (session) {
|
|
228
|
-
await
|
|
245
|
+
await authFetch(buildUrl("logout"), {
|
|
229
246
|
method: "POST",
|
|
230
247
|
headers: {
|
|
231
248
|
Authorization: `Bearer ${session.access_token}`
|
|
@@ -248,7 +265,7 @@ function AuthProvider({
|
|
|
248
265
|
}
|
|
249
266
|
setError(null);
|
|
250
267
|
try {
|
|
251
|
-
const response = await
|
|
268
|
+
const response = await authFetch(buildUrl("me"), {
|
|
252
269
|
method: "PATCH",
|
|
253
270
|
headers: {
|
|
254
271
|
"Content-Type": "application/json",
|
|
@@ -270,10 +287,9 @@ function AuthProvider({
|
|
|
270
287
|
[session, buildUrl]
|
|
271
288
|
);
|
|
272
289
|
const refreshSession = useCallback(async () => {
|
|
273
|
-
if (!session)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const response = await fetch(buildUrl("refresh"), {
|
|
290
|
+
if (!session)
|
|
291
|
+
return;
|
|
292
|
+
const response = await authFetch(buildUrl("refresh"), {
|
|
277
293
|
method: "POST",
|
|
278
294
|
headers: { "Content-Type": "application/json" },
|
|
279
295
|
body: JSON.stringify({ refreshToken: session.refresh_token })
|
|
@@ -294,7 +310,7 @@ function AuthProvider({
|
|
|
294
310
|
async (email) => {
|
|
295
311
|
setError(null);
|
|
296
312
|
try {
|
|
297
|
-
const response = await
|
|
313
|
+
const response = await authFetch(buildUrl("forgot-password"), {
|
|
298
314
|
method: "POST",
|
|
299
315
|
headers: { "Content-Type": "application/json" },
|
|
300
316
|
body: JSON.stringify({ email })
|
|
@@ -315,7 +331,7 @@ function AuthProvider({
|
|
|
315
331
|
async (token, newPassword) => {
|
|
316
332
|
setError(null);
|
|
317
333
|
try {
|
|
318
|
-
const response = await
|
|
334
|
+
const response = await authFetch(buildUrl("reset-password"), {
|
|
319
335
|
method: "POST",
|
|
320
336
|
headers: { "Content-Type": "application/json" },
|
|
321
337
|
body: JSON.stringify({ token, password: newPassword })
|
|
@@ -349,7 +365,7 @@ function AuthProvider({
|
|
|
349
365
|
setError(null);
|
|
350
366
|
setLoading(true);
|
|
351
367
|
try {
|
|
352
|
-
const response = await
|
|
368
|
+
const response = await authFetch(buildUrl("verify-email"), {
|
|
353
369
|
method: "POST",
|
|
354
370
|
headers: { "Content-Type": "application/json" },
|
|
355
371
|
body: JSON.stringify({ email, otp: code })
|
|
@@ -375,7 +391,7 @@ function AuthProvider({
|
|
|
375
391
|
async (email) => {
|
|
376
392
|
setError(null);
|
|
377
393
|
try {
|
|
378
|
-
const response = await
|
|
394
|
+
const response = await authFetch(buildUrl("resend-verification"), {
|
|
379
395
|
method: "POST",
|
|
380
396
|
headers: { "Content-Type": "application/json" },
|
|
381
397
|
body: JSON.stringify({ email })
|
|
@@ -396,9 +412,7 @@ function AuthProvider({
|
|
|
396
412
|
if (!projectId)
|
|
397
413
|
return;
|
|
398
414
|
try {
|
|
399
|
-
const response = await fetch(
|
|
400
|
-
`${baseUrl}/${projectId}/auth/config`
|
|
401
|
-
);
|
|
415
|
+
const response = await fetch(`${baseUrl}/${projectId}/auth/config`);
|
|
402
416
|
if (response.ok) {
|
|
403
417
|
const data = await response.json();
|
|
404
418
|
setAuthConfig(data.config || null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@instroc/auth",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Authentication hooks for Instroc Cloud — useAuth, useUser, AuthProvider",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
15
17
|
"scripts": {
|
|
16
18
|
"build": "tsup",
|
|
17
19
|
"dev": "tsup --watch"
|