@sanvika/auth 1.0.4 → 1.0.5

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.
@@ -1,171 +0,0 @@
1
- "use client";
2
- // ============================================================
3
- // SanvikaAuthProvider — Context + global auth state manager
4
- // Wrap your root layout with this provider.
5
- //
6
- // Usage:
7
- // <SanvikaAuthProvider
8
- // clientId="sanvika_XXXXXXXXXX"
9
- // redirectUri="https://yourapp.com/auth/callback"
10
- // iamUrl="https://accounts.sanvikaproduction.com" // optional
11
- // dashboardPath="/dashboard" // optional
12
- // >
13
- // {children}
14
- // </SanvikaAuthProvider>
15
- // ============================================================
16
-
17
- import {
18
- createContext,
19
- useContext,
20
- useEffect,
21
- useState,
22
- useCallback,
23
- } from "react";
24
- import { STORAGE_KEYS, DEFAULT_IAM_URL } from "./constants.js";
25
-
26
- // ─── Context ──────────────────────────────────────────────────────────────
27
- export const SanvikaAuthContext = createContext(null);
28
-
29
- // ─── Provider ─────────────────────────────────────────────────────────────
30
- export function SanvikaAuthProvider({
31
- children,
32
- clientId,
33
- redirectUri,
34
- iamUrl = DEFAULT_IAM_URL,
35
- dashboardPath = "/dashboard",
36
- }) {
37
- const [user, setUser] = useState(null);
38
- const [accessToken, setToken] = useState(null);
39
- const [loading, setLoading] = useState(true); // true during initial localStorage read
40
-
41
- // ── Hydrate from localStorage on mount ────────────────────────────────
42
- useEffect(() => {
43
- try {
44
- const storedToken = localStorage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
45
- const storedUser = localStorage.getItem(STORAGE_KEYS.USER);
46
- if (storedToken && storedUser) {
47
- setToken(storedToken);
48
- setUser(JSON.parse(storedUser));
49
- }
50
- } catch {
51
- // corrupted storage — clear it
52
- localStorage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);
53
- localStorage.removeItem(STORAGE_KEYS.USER);
54
- } finally {
55
- setLoading(false);
56
- }
57
- }, []);
58
-
59
- // ── Cross-tab sync: ek tab logout kare → sab tabs logout ──────────────
60
- useEffect(() => {
61
- function onStorage(e) {
62
- if (e.key === STORAGE_KEYS.ACCESS_TOKEN && !e.newValue) {
63
- setUser(null);
64
- setToken(null);
65
- }
66
- // New login in another tab
67
- if (e.key === STORAGE_KEYS.ACCESS_TOKEN && e.newValue) {
68
- try {
69
- const u = localStorage.getItem(STORAGE_KEYS.USER);
70
- if (u) setUser(JSON.parse(u));
71
- setToken(e.newValue);
72
- } catch {
73
- /* ignore */
74
- }
75
- }
76
- }
77
- window.addEventListener("storage", onStorage);
78
- return () => window.removeEventListener("storage", onStorage);
79
- }, []);
80
-
81
- // ── login: called after callback route gets tokens ────────────────────
82
- const login = useCallback((token, userData) => {
83
- localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);
84
- localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(userData));
85
- setToken(token);
86
- setUser(userData);
87
- }, []);
88
-
89
- // ── logout: clear state + localStorage ────────────────────────────────
90
- const logout = useCallback(async () => {
91
- const token = localStorage.getItem(STORAGE_KEYS.ACCESS_TOKEN);
92
- // Optionally revoke on server (fire-and-forget)
93
- if (token) {
94
- fetch(`${iamUrl}/api/auth/logout`, {
95
- method: "POST",
96
- headers: { "Content-Type": "application/json" },
97
- body: JSON.stringify({ logout_all: false }),
98
- credentials: "include",
99
- }).catch(() => {});
100
- }
101
- localStorage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);
102
- localStorage.removeItem(STORAGE_KEYS.USER);
103
- setUser(null);
104
- setToken(null);
105
- }, [iamUrl]);
106
-
107
- // ── updateUser: partial state update (e.g. image changed) ─────────────
108
- const updateUser = useCallback((partial) => {
109
- setUser((prev) => {
110
- if (!prev) return prev;
111
- const merged = { ...prev, ...partial };
112
- localStorage.setItem(STORAGE_KEYS.USER, JSON.stringify(merged));
113
- return merged;
114
- });
115
- }, []);
116
-
117
- // ── Redirect to Sanvika SSO ────────────────────────────────────────────
118
- const redirectToLogin = useCallback(
119
- (returnPath) => {
120
- // Save current path so we can return after login
121
- if (returnPath) {
122
- localStorage.setItem(STORAGE_KEYS.RETURN_PATH, returnPath);
123
- }
124
- // CSRF state
125
- const state = Math.random().toString(36).slice(2);
126
- localStorage.setItem(STORAGE_KEYS.STATE, state);
127
-
128
- const url = new URL(`${iamUrl}/authorize`);
129
- url.searchParams.set("client_id", clientId);
130
- url.searchParams.set("redirect_uri", redirectUri);
131
- url.searchParams.set("response_type", "code");
132
- url.searchParams.set("state", state);
133
- // Pass app's current theme so SA authorize page can match it
134
- const appTheme = localStorage.getItem("theme");
135
- if (appTheme === "light" || appTheme === "dark") {
136
- url.searchParams.set("theme", appTheme);
137
- }
138
- window.location.href = url.toString();
139
- },
140
- [iamUrl, clientId, redirectUri],
141
- );
142
-
143
- return (
144
- <SanvikaAuthContext.Provider
145
- value={{
146
- user,
147
- accessToken,
148
- loading,
149
- isLoggedIn: !!user,
150
- login,
151
- logout,
152
- updateUser,
153
- redirectToLogin,
154
- clientId,
155
- redirectUri,
156
- iamUrl,
157
- dashboardPath,
158
- }}
159
- >
160
- {children}
161
- </SanvikaAuthContext.Provider>
162
- );
163
- }
164
-
165
- // ─── Hook ─────────────────────────────────────────────────────────────────
166
- export function useSanvikaAuth() {
167
- const ctx = useContext(SanvikaAuthContext);
168
- if (!ctx)
169
- throw new Error("useSanvikaAuth must be used inside <SanvikaAuthProvider>");
170
- return ctx;
171
- }
package/constants.js DELETED
@@ -1,32 +0,0 @@
1
- // ============================================================
2
- // Sanvika Auth SDK — Storage Keys & Constants
3
- // ============================================================
4
-
5
- // localStorage keys — use these everywhere (never hardcode strings)
6
- export const STORAGE_KEYS = {
7
- ACCESS_TOKEN: "sanvika_access_token",
8
- USER: "sanvika_user",
9
- STATE: "sanvika_oauth_state", // CSRF state for OAuth flow
10
- RETURN_PATH: "sanvika_return_path", // Page to redirect back after login
11
- };
12
-
13
- // Default Sanvika Accounts base URL
14
- export const DEFAULT_IAM_URL = "https://accounts.sanvikaproduction.com";
15
-
16
- // Token key in response body from /api/auth/token
17
- export const TOKEN_RESPONSE_KEYS = {
18
- ACCESS_TOKEN: "access_token",
19
- REFRESH_TOKEN: "refresh_token",
20
- USER: "user",
21
- };
22
-
23
- // User statuses (matches Sanvika Accounts User schema)
24
- export const USER_STATUS = {
25
- ONBOARDING: "onboarding",
26
- ACTIVE: "active",
27
- SUSPENDED: "suspended",
28
- DELETED: "deleted",
29
- };
30
-
31
- // Default avatar shown when user has no image
32
- export const DEFAULT_AVATAR_SVG = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='20' fill='%23e5e7eb'/%3E%3Ccircle cx='20' cy='15' r='7' fill='%23adb5bd'/%3E%3Cellipse cx='20' cy='35' rx='12' ry='8' fill='%23adb5bd'/%3E%3C/svg%3E`;
package/index.js DELETED
@@ -1,16 +0,0 @@
1
- // ============================================================
2
- // Sanvika Auth SDK — Main Barrel Export
3
- // Export all public SDK components and utilities
4
- // ============================================================
5
-
6
- export {
7
- SanvikaAuthProvider,
8
- SanvikaAuthContext,
9
- useSanvikaAuth,
10
- } from "./SanvikaAuthProvider.jsx";
11
- export { default as SanvikaAccountButton } from "./SanvikaAccountButton.jsx";
12
- export {
13
- STORAGE_KEYS,
14
- DEFAULT_IAM_URL,
15
- DEFAULT_AVATAR_SVG,
16
- } from "./constants.js";