authtara-sdk 1.0.0 → 1.1.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/react.d.mts +52 -0
- package/dist/react.d.ts +52 -0
- package/dist/react.js +458 -0
- package/dist/react.mjs +419 -0
- package/package.json +90 -71
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
interface User {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
name?: string | null;
|
|
8
|
+
avatar?: string | null;
|
|
9
|
+
}
|
|
10
|
+
interface AuthTaraConfig {
|
|
11
|
+
appId: string;
|
|
12
|
+
apiUrl: string;
|
|
13
|
+
}
|
|
14
|
+
interface AuthTaraContextValue {
|
|
15
|
+
isAuthenticated: boolean;
|
|
16
|
+
user: User | null;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
signIn: (provider: 'google' | 'github' | 'credentials', options?: SignInOptions) => Promise<void>;
|
|
19
|
+
signOut: () => Promise<void>;
|
|
20
|
+
refreshSession: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
interface SignInOptions {
|
|
23
|
+
email?: string;
|
|
24
|
+
password?: string;
|
|
25
|
+
redirectPath?: string;
|
|
26
|
+
}
|
|
27
|
+
declare function AuthTaraProvider({ children, appId, apiUrl, }: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
} & AuthTaraConfig): react_jsx_runtime.JSX.Element;
|
|
30
|
+
declare function useAuth(): AuthTaraContextValue;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* AuthTaraAuth Component
|
|
34
|
+
*
|
|
35
|
+
* Embeddable login/register component
|
|
36
|
+
* Renders social login buttons and handles OAuth popup flow
|
|
37
|
+
*/
|
|
38
|
+
interface AuthTaraAuthProps {
|
|
39
|
+
mode?: 'modal' | 'redirect';
|
|
40
|
+
appearance?: {
|
|
41
|
+
theme?: 'light' | 'dark';
|
|
42
|
+
variables?: Record<string, string>;
|
|
43
|
+
};
|
|
44
|
+
redirectUrl?: string;
|
|
45
|
+
onSuccess?: (session: {
|
|
46
|
+
user: any;
|
|
47
|
+
}) => void;
|
|
48
|
+
onError?: (error: Error) => void;
|
|
49
|
+
}
|
|
50
|
+
declare function AuthTaraAuth({ appearance, redirectUrl, onSuccess, onError, }: AuthTaraAuthProps): react_jsx_runtime.JSX.Element;
|
|
51
|
+
|
|
52
|
+
export { AuthTaraAuth, type AuthTaraAuthProps, type AuthTaraConfig, type AuthTaraContextValue, AuthTaraProvider, type SignInOptions, type User, useAuth };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
interface User {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
name?: string | null;
|
|
8
|
+
avatar?: string | null;
|
|
9
|
+
}
|
|
10
|
+
interface AuthTaraConfig {
|
|
11
|
+
appId: string;
|
|
12
|
+
apiUrl: string;
|
|
13
|
+
}
|
|
14
|
+
interface AuthTaraContextValue {
|
|
15
|
+
isAuthenticated: boolean;
|
|
16
|
+
user: User | null;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
signIn: (provider: 'google' | 'github' | 'credentials', options?: SignInOptions) => Promise<void>;
|
|
19
|
+
signOut: () => Promise<void>;
|
|
20
|
+
refreshSession: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
interface SignInOptions {
|
|
23
|
+
email?: string;
|
|
24
|
+
password?: string;
|
|
25
|
+
redirectPath?: string;
|
|
26
|
+
}
|
|
27
|
+
declare function AuthTaraProvider({ children, appId, apiUrl, }: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
} & AuthTaraConfig): react_jsx_runtime.JSX.Element;
|
|
30
|
+
declare function useAuth(): AuthTaraContextValue;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* AuthTaraAuth Component
|
|
34
|
+
*
|
|
35
|
+
* Embeddable login/register component
|
|
36
|
+
* Renders social login buttons and handles OAuth popup flow
|
|
37
|
+
*/
|
|
38
|
+
interface AuthTaraAuthProps {
|
|
39
|
+
mode?: 'modal' | 'redirect';
|
|
40
|
+
appearance?: {
|
|
41
|
+
theme?: 'light' | 'dark';
|
|
42
|
+
variables?: Record<string, string>;
|
|
43
|
+
};
|
|
44
|
+
redirectUrl?: string;
|
|
45
|
+
onSuccess?: (session: {
|
|
46
|
+
user: any;
|
|
47
|
+
}) => void;
|
|
48
|
+
onError?: (error: Error) => void;
|
|
49
|
+
}
|
|
50
|
+
declare function AuthTaraAuth({ appearance, redirectUrl, onSuccess, onError, }: AuthTaraAuthProps): react_jsx_runtime.JSX.Element;
|
|
51
|
+
|
|
52
|
+
export { AuthTaraAuth, type AuthTaraAuthProps, type AuthTaraConfig, type AuthTaraContextValue, AuthTaraProvider, type SignInOptions, type User, useAuth };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/react.ts
|
|
31
|
+
var react_exports = {};
|
|
32
|
+
__export(react_exports, {
|
|
33
|
+
AuthTaraAuth: () => AuthTaraAuth,
|
|
34
|
+
AuthTaraProvider: () => AuthTaraProvider,
|
|
35
|
+
useAuth: () => useAuth
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(react_exports);
|
|
38
|
+
|
|
39
|
+
// src/components/providers/AuthTaraProvider.tsx
|
|
40
|
+
var React = __toESM(require("react"));
|
|
41
|
+
|
|
42
|
+
// src/oauth/popup.ts
|
|
43
|
+
var OAuthPopup = class {
|
|
44
|
+
constructor(apiUrl) {
|
|
45
|
+
this.popup = null;
|
|
46
|
+
try {
|
|
47
|
+
const url = new URL(apiUrl);
|
|
48
|
+
this.expectedOrigin = url.origin;
|
|
49
|
+
} catch {
|
|
50
|
+
this.expectedOrigin = apiUrl;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Open popup window for OAuth flow
|
|
55
|
+
*/
|
|
56
|
+
async open(url) {
|
|
57
|
+
const width = 500;
|
|
58
|
+
const height = 700;
|
|
59
|
+
const left = window.screen.width / 2 - width / 2;
|
|
60
|
+
const top = window.screen.height / 2 - height / 2;
|
|
61
|
+
this.popup = window.open(
|
|
62
|
+
url,
|
|
63
|
+
"authtara-oauth",
|
|
64
|
+
`width=${width},height=${height},left=${left},top=${top},popup=1,scrollbars=1`
|
|
65
|
+
);
|
|
66
|
+
if (!this.popup) {
|
|
67
|
+
throw new Error("Popup blocked. Please allow popups for this site.");
|
|
68
|
+
}
|
|
69
|
+
this.popup.focus();
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
this.messageListener = (event) => {
|
|
72
|
+
if (event.origin !== this.expectedOrigin) {
|
|
73
|
+
console.warn("Received message from unexpected origin:", event.origin);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const { type, payload, error } = event.data;
|
|
77
|
+
if (type === "OAUTH_SUCCESS" && payload) {
|
|
78
|
+
this.cleanup();
|
|
79
|
+
resolve(payload);
|
|
80
|
+
} else if (type === "OAUTH_ERROR") {
|
|
81
|
+
this.cleanup();
|
|
82
|
+
reject(new Error(error || "OAuth authentication failed"));
|
|
83
|
+
} else if (type === "OAUTH_CANCEL") {
|
|
84
|
+
this.cleanup();
|
|
85
|
+
reject(new Error("Authentication cancelled by user"));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
window.addEventListener("message", this.messageListener);
|
|
89
|
+
this.pollTimer = setInterval(() => {
|
|
90
|
+
if (this.popup?.closed) {
|
|
91
|
+
this.cleanup();
|
|
92
|
+
reject(new Error("Authentication window was closed"));
|
|
93
|
+
}
|
|
94
|
+
}, 500);
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
if (this.popup && !this.popup.closed) {
|
|
97
|
+
this.cleanup();
|
|
98
|
+
reject(new Error("Authentication timed out"));
|
|
99
|
+
}
|
|
100
|
+
}, 5 * 60 * 1e3);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Cleanup resources
|
|
105
|
+
*/
|
|
106
|
+
cleanup() {
|
|
107
|
+
if (this.messageListener) {
|
|
108
|
+
window.removeEventListener("message", this.messageListener);
|
|
109
|
+
this.messageListener = void 0;
|
|
110
|
+
}
|
|
111
|
+
if (this.pollTimer) {
|
|
112
|
+
clearInterval(this.pollTimer);
|
|
113
|
+
this.pollTimer = void 0;
|
|
114
|
+
}
|
|
115
|
+
if (this.popup && !this.popup.closed) {
|
|
116
|
+
this.popup.close();
|
|
117
|
+
}
|
|
118
|
+
this.popup = null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Manually close popup
|
|
122
|
+
*/
|
|
123
|
+
close() {
|
|
124
|
+
this.cleanup();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/components/providers/AuthTaraProvider.tsx
|
|
129
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
130
|
+
var AuthTaraContext = React.createContext(null);
|
|
131
|
+
function AuthTaraProvider({
|
|
132
|
+
children,
|
|
133
|
+
appId,
|
|
134
|
+
apiUrl
|
|
135
|
+
}) {
|
|
136
|
+
const [user, setUser] = React.useState(null);
|
|
137
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
138
|
+
React.useEffect(() => {
|
|
139
|
+
loadSession();
|
|
140
|
+
}, []);
|
|
141
|
+
const loadSession = React.useCallback(async () => {
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch("/api/auth/me", {
|
|
144
|
+
credentials: "include"
|
|
145
|
+
});
|
|
146
|
+
if (response.ok) {
|
|
147
|
+
const data = await response.json();
|
|
148
|
+
setUser(data.user);
|
|
149
|
+
} else {
|
|
150
|
+
setUser(null);
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error("[AuthTara] Failed to load session:", error);
|
|
154
|
+
setUser(null);
|
|
155
|
+
} finally {
|
|
156
|
+
setIsLoading(false);
|
|
157
|
+
}
|
|
158
|
+
}, []);
|
|
159
|
+
const signIn = React.useCallback(
|
|
160
|
+
async (provider, options) => {
|
|
161
|
+
try {
|
|
162
|
+
setIsLoading(true);
|
|
163
|
+
if (provider === "credentials") {
|
|
164
|
+
throw new Error("Credentials flow not yet implemented in popup mode");
|
|
165
|
+
}
|
|
166
|
+
const callbackUrl = `${window.location.origin}/api/sso/callback`;
|
|
167
|
+
const state = btoa(JSON.stringify({
|
|
168
|
+
redirectPath: options?.redirectPath || "/dashboard",
|
|
169
|
+
timestamp: Date.now()
|
|
170
|
+
}));
|
|
171
|
+
const params = new URLSearchParams({
|
|
172
|
+
response_type: "code",
|
|
173
|
+
client_id: appId,
|
|
174
|
+
redirect_uri: callbackUrl,
|
|
175
|
+
state,
|
|
176
|
+
scope: "read write"
|
|
177
|
+
});
|
|
178
|
+
const authorizeUrl = `${apiUrl}/api/oauth/authorize?${params.toString()}`;
|
|
179
|
+
const popup = new OAuthPopup(apiUrl);
|
|
180
|
+
const { code: authCode, state: returnedState } = await popup.open(authorizeUrl);
|
|
181
|
+
const exchangeResponse = await fetch("/api/sso/callback", {
|
|
182
|
+
method: "POST",
|
|
183
|
+
headers: { "Content-Type": "application/json" },
|
|
184
|
+
credentials: "include",
|
|
185
|
+
body: JSON.stringify({
|
|
186
|
+
code: authCode,
|
|
187
|
+
state: returnedState
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
if (!exchangeResponse.ok) {
|
|
191
|
+
const error = await exchangeResponse.json();
|
|
192
|
+
throw new Error(error.message || "Token exchange failed");
|
|
193
|
+
}
|
|
194
|
+
await loadSession();
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error("[AuthTara] Sign in failed:", error);
|
|
197
|
+
throw error;
|
|
198
|
+
} finally {
|
|
199
|
+
setIsLoading(false);
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
[appId, apiUrl, loadSession]
|
|
203
|
+
);
|
|
204
|
+
const signOut = React.useCallback(async () => {
|
|
205
|
+
try {
|
|
206
|
+
await fetch("/api/auth/logout", {
|
|
207
|
+
method: "POST",
|
|
208
|
+
credentials: "include"
|
|
209
|
+
});
|
|
210
|
+
setUser(null);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error("[AuthTara] Sign out failed:", error);
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
}, []);
|
|
216
|
+
const refreshSession = React.useCallback(async () => {
|
|
217
|
+
await loadSession();
|
|
218
|
+
}, [loadSession]);
|
|
219
|
+
const value = {
|
|
220
|
+
isAuthenticated: !!user,
|
|
221
|
+
user,
|
|
222
|
+
isLoading,
|
|
223
|
+
signIn,
|
|
224
|
+
signOut,
|
|
225
|
+
refreshSession
|
|
226
|
+
};
|
|
227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthTaraContext.Provider, { value, children });
|
|
228
|
+
}
|
|
229
|
+
function useAuth() {
|
|
230
|
+
const context = React.useContext(AuthTaraContext);
|
|
231
|
+
if (!context) {
|
|
232
|
+
throw new Error("useAuth must be used within AuthTaraProvider");
|
|
233
|
+
}
|
|
234
|
+
return context;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/components/AuthTaraAuth.tsx
|
|
238
|
+
var React2 = __toESM(require("react"));
|
|
239
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
240
|
+
function AuthTaraAuth({
|
|
241
|
+
// mode = 'modal', // Reserved for future use
|
|
242
|
+
appearance,
|
|
243
|
+
redirectUrl = "/dashboard",
|
|
244
|
+
onSuccess,
|
|
245
|
+
onError
|
|
246
|
+
}) {
|
|
247
|
+
const { signIn, isLoading, user } = useAuth();
|
|
248
|
+
const [error, setError] = React2.useState(null);
|
|
249
|
+
const [provider, setProvider] = React2.useState(null);
|
|
250
|
+
async function handleSignIn(selectedProvider) {
|
|
251
|
+
setError(null);
|
|
252
|
+
setProvider(selectedProvider);
|
|
253
|
+
try {
|
|
254
|
+
await signIn(selectedProvider, { redirectPath: redirectUrl });
|
|
255
|
+
onSuccess?.({ user });
|
|
256
|
+
if (redirectUrl) {
|
|
257
|
+
window.location.href = redirectUrl;
|
|
258
|
+
}
|
|
259
|
+
} catch (err) {
|
|
260
|
+
const message = err instanceof Error ? err.message : "Authentication failed";
|
|
261
|
+
setError(message);
|
|
262
|
+
onError?.(err);
|
|
263
|
+
} finally {
|
|
264
|
+
setProvider(null);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const isProviderLoading = (p) => isLoading && provider === p;
|
|
268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "authtara-auth-container", style: { maxWidth: "400px", margin: "0 auto" }, children: [
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
270
|
+
"div",
|
|
271
|
+
{
|
|
272
|
+
className: "authtara-auth-card",
|
|
273
|
+
style: {
|
|
274
|
+
padding: "2rem",
|
|
275
|
+
border: "1px solid #e5e7eb",
|
|
276
|
+
borderRadius: "0.5rem",
|
|
277
|
+
backgroundColor: appearance?.theme === "dark" ? "#1f2937" : "#ffffff"
|
|
278
|
+
},
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
281
|
+
"h2",
|
|
282
|
+
{
|
|
283
|
+
style: {
|
|
284
|
+
fontSize: "1.5rem",
|
|
285
|
+
fontWeight: "bold",
|
|
286
|
+
marginBottom: "1.5rem",
|
|
287
|
+
color: appearance?.theme === "dark" ? "#ffffff" : "#111827"
|
|
288
|
+
},
|
|
289
|
+
children: "Sign in to continue"
|
|
290
|
+
}
|
|
291
|
+
),
|
|
292
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
293
|
+
"div",
|
|
294
|
+
{
|
|
295
|
+
style: {
|
|
296
|
+
padding: "0.75rem",
|
|
297
|
+
marginBottom: "1rem",
|
|
298
|
+
backgroundColor: "#fee2e2",
|
|
299
|
+
color: "#991b1b",
|
|
300
|
+
borderRadius: "0.375rem",
|
|
301
|
+
fontSize: "0.875rem"
|
|
302
|
+
},
|
|
303
|
+
children: error
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
307
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
308
|
+
"button",
|
|
309
|
+
{
|
|
310
|
+
onClick: () => handleSignIn("google"),
|
|
311
|
+
disabled: isLoading,
|
|
312
|
+
style: {
|
|
313
|
+
display: "flex",
|
|
314
|
+
alignItems: "center",
|
|
315
|
+
justifyContent: "center",
|
|
316
|
+
gap: "0.5rem",
|
|
317
|
+
padding: "0.75rem 1rem",
|
|
318
|
+
border: "1px solid #d1d5db",
|
|
319
|
+
borderRadius: "0.375rem",
|
|
320
|
+
backgroundColor: "#ffffff",
|
|
321
|
+
color: "#374151",
|
|
322
|
+
fontSize: "0.875rem",
|
|
323
|
+
fontWeight: "500",
|
|
324
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
325
|
+
opacity: isLoading ? 0.6 : 1,
|
|
326
|
+
transition: "all 0.2s"
|
|
327
|
+
},
|
|
328
|
+
onMouseOver: (e) => {
|
|
329
|
+
if (!isLoading) {
|
|
330
|
+
e.currentTarget.style.backgroundColor = "#f9fafb";
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
onMouseOut: (e) => {
|
|
334
|
+
e.currentTarget.style.backgroundColor = "#ffffff";
|
|
335
|
+
},
|
|
336
|
+
children: [
|
|
337
|
+
isProviderLoading("google") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
338
|
+
"div",
|
|
339
|
+
{
|
|
340
|
+
style: {
|
|
341
|
+
width: "1rem",
|
|
342
|
+
height: "1rem",
|
|
343
|
+
border: "2px solid #d1d5db",
|
|
344
|
+
borderTopColor: "#3b82f6",
|
|
345
|
+
borderRadius: "50%",
|
|
346
|
+
animation: "spin 1s linear infinite"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
350
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
351
|
+
"path",
|
|
352
|
+
{
|
|
353
|
+
fill: "#4285F4",
|
|
354
|
+
d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"
|
|
355
|
+
}
|
|
356
|
+
),
|
|
357
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
358
|
+
"path",
|
|
359
|
+
{
|
|
360
|
+
fill: "#34A853",
|
|
361
|
+
d: "M9.003 18c2.43 0 4.467-.806 5.956-2.18L12.05 13.56c-.806.54-1.837.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332C2.44 15.983 5.485 18 9.003 18z"
|
|
362
|
+
}
|
|
363
|
+
),
|
|
364
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
365
|
+
"path",
|
|
366
|
+
{
|
|
367
|
+
fill: "#FBBC05",
|
|
368
|
+
d: "M3.964 10.712c-.18-.54-.282-1.117-.282-1.71 0-.593.102-1.17.282-1.71V4.96H.957C.347 6.175 0 7.55 0 9.002c0 1.452.348 2.827.957 4.042l3.007-2.332z"
|
|
369
|
+
}
|
|
370
|
+
),
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
372
|
+
"path",
|
|
373
|
+
{
|
|
374
|
+
fill: "#EA4335",
|
|
375
|
+
d: "M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.003 0 5.485 0 2.44 2.017.96 4.958L3.967 7.29c.708-2.127 2.692-3.71 5.036-3.71z"
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
] }),
|
|
379
|
+
"Continue with Google"
|
|
380
|
+
]
|
|
381
|
+
}
|
|
382
|
+
),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
384
|
+
"button",
|
|
385
|
+
{
|
|
386
|
+
onClick: () => handleSignIn("github"),
|
|
387
|
+
disabled: isLoading,
|
|
388
|
+
style: {
|
|
389
|
+
display: "flex",
|
|
390
|
+
alignItems: "center",
|
|
391
|
+
justifyContent: "center",
|
|
392
|
+
gap: "0.5rem",
|
|
393
|
+
padding: "0.75rem 1rem",
|
|
394
|
+
border: "1px solid #d1d5db",
|
|
395
|
+
borderRadius: "0.375rem",
|
|
396
|
+
backgroundColor: "#24292e",
|
|
397
|
+
color: "#ffffff",
|
|
398
|
+
fontSize: "0.875rem",
|
|
399
|
+
fontWeight: "500",
|
|
400
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
401
|
+
opacity: isLoading ? 0.6 : 1,
|
|
402
|
+
transition: "all 0.2s"
|
|
403
|
+
},
|
|
404
|
+
onMouseOver: (e) => {
|
|
405
|
+
if (!isLoading) {
|
|
406
|
+
e.currentTarget.style.backgroundColor = "#1b1f23";
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
onMouseOut: (e) => {
|
|
410
|
+
e.currentTarget.style.backgroundColor = "#24292e";
|
|
411
|
+
},
|
|
412
|
+
children: [
|
|
413
|
+
isProviderLoading("github") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
414
|
+
"div",
|
|
415
|
+
{
|
|
416
|
+
style: {
|
|
417
|
+
width: "1rem",
|
|
418
|
+
height: "1rem",
|
|
419
|
+
border: "2px solid #ffffff40",
|
|
420
|
+
borderTopColor: "#ffffff",
|
|
421
|
+
borderRadius: "50%",
|
|
422
|
+
animation: "spin 1s linear infinite"
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" }) }),
|
|
426
|
+
"Continue with GitHub"
|
|
427
|
+
]
|
|
428
|
+
}
|
|
429
|
+
)
|
|
430
|
+
] }),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
432
|
+
"p",
|
|
433
|
+
{
|
|
434
|
+
style: {
|
|
435
|
+
marginTop: "1.5rem",
|
|
436
|
+
fontSize: "0.75rem",
|
|
437
|
+
color: appearance?.theme === "dark" ? "#9ca3af" : "#6b7280",
|
|
438
|
+
textAlign: "center"
|
|
439
|
+
},
|
|
440
|
+
children: "By continuing, you agree to our Terms of Service and Privacy Policy"
|
|
441
|
+
}
|
|
442
|
+
)
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
),
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
|
|
447
|
+
@keyframes spin {
|
|
448
|
+
to { transform: rotate(360deg); }
|
|
449
|
+
}
|
|
450
|
+
` })
|
|
451
|
+
] });
|
|
452
|
+
}
|
|
453
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
454
|
+
0 && (module.exports = {
|
|
455
|
+
AuthTaraAuth,
|
|
456
|
+
AuthTaraProvider,
|
|
457
|
+
useAuth
|
|
458
|
+
});
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
// src/components/providers/AuthTaraProvider.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
// src/oauth/popup.ts
|
|
5
|
+
var OAuthPopup = class {
|
|
6
|
+
constructor(apiUrl) {
|
|
7
|
+
this.popup = null;
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(apiUrl);
|
|
10
|
+
this.expectedOrigin = url.origin;
|
|
11
|
+
} catch {
|
|
12
|
+
this.expectedOrigin = apiUrl;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Open popup window for OAuth flow
|
|
17
|
+
*/
|
|
18
|
+
async open(url) {
|
|
19
|
+
const width = 500;
|
|
20
|
+
const height = 700;
|
|
21
|
+
const left = window.screen.width / 2 - width / 2;
|
|
22
|
+
const top = window.screen.height / 2 - height / 2;
|
|
23
|
+
this.popup = window.open(
|
|
24
|
+
url,
|
|
25
|
+
"authtara-oauth",
|
|
26
|
+
`width=${width},height=${height},left=${left},top=${top},popup=1,scrollbars=1`
|
|
27
|
+
);
|
|
28
|
+
if (!this.popup) {
|
|
29
|
+
throw new Error("Popup blocked. Please allow popups for this site.");
|
|
30
|
+
}
|
|
31
|
+
this.popup.focus();
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
this.messageListener = (event) => {
|
|
34
|
+
if (event.origin !== this.expectedOrigin) {
|
|
35
|
+
console.warn("Received message from unexpected origin:", event.origin);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const { type, payload, error } = event.data;
|
|
39
|
+
if (type === "OAUTH_SUCCESS" && payload) {
|
|
40
|
+
this.cleanup();
|
|
41
|
+
resolve(payload);
|
|
42
|
+
} else if (type === "OAUTH_ERROR") {
|
|
43
|
+
this.cleanup();
|
|
44
|
+
reject(new Error(error || "OAuth authentication failed"));
|
|
45
|
+
} else if (type === "OAUTH_CANCEL") {
|
|
46
|
+
this.cleanup();
|
|
47
|
+
reject(new Error("Authentication cancelled by user"));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
window.addEventListener("message", this.messageListener);
|
|
51
|
+
this.pollTimer = setInterval(() => {
|
|
52
|
+
if (this.popup?.closed) {
|
|
53
|
+
this.cleanup();
|
|
54
|
+
reject(new Error("Authentication window was closed"));
|
|
55
|
+
}
|
|
56
|
+
}, 500);
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
if (this.popup && !this.popup.closed) {
|
|
59
|
+
this.cleanup();
|
|
60
|
+
reject(new Error("Authentication timed out"));
|
|
61
|
+
}
|
|
62
|
+
}, 5 * 60 * 1e3);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Cleanup resources
|
|
67
|
+
*/
|
|
68
|
+
cleanup() {
|
|
69
|
+
if (this.messageListener) {
|
|
70
|
+
window.removeEventListener("message", this.messageListener);
|
|
71
|
+
this.messageListener = void 0;
|
|
72
|
+
}
|
|
73
|
+
if (this.pollTimer) {
|
|
74
|
+
clearInterval(this.pollTimer);
|
|
75
|
+
this.pollTimer = void 0;
|
|
76
|
+
}
|
|
77
|
+
if (this.popup && !this.popup.closed) {
|
|
78
|
+
this.popup.close();
|
|
79
|
+
}
|
|
80
|
+
this.popup = null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Manually close popup
|
|
84
|
+
*/
|
|
85
|
+
close() {
|
|
86
|
+
this.cleanup();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/components/providers/AuthTaraProvider.tsx
|
|
91
|
+
import { jsx } from "react/jsx-runtime";
|
|
92
|
+
var AuthTaraContext = React.createContext(null);
|
|
93
|
+
function AuthTaraProvider({
|
|
94
|
+
children,
|
|
95
|
+
appId,
|
|
96
|
+
apiUrl
|
|
97
|
+
}) {
|
|
98
|
+
const [user, setUser] = React.useState(null);
|
|
99
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
100
|
+
React.useEffect(() => {
|
|
101
|
+
loadSession();
|
|
102
|
+
}, []);
|
|
103
|
+
const loadSession = React.useCallback(async () => {
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch("/api/auth/me", {
|
|
106
|
+
credentials: "include"
|
|
107
|
+
});
|
|
108
|
+
if (response.ok) {
|
|
109
|
+
const data = await response.json();
|
|
110
|
+
setUser(data.user);
|
|
111
|
+
} else {
|
|
112
|
+
setUser(null);
|
|
113
|
+
}
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error("[AuthTara] Failed to load session:", error);
|
|
116
|
+
setUser(null);
|
|
117
|
+
} finally {
|
|
118
|
+
setIsLoading(false);
|
|
119
|
+
}
|
|
120
|
+
}, []);
|
|
121
|
+
const signIn = React.useCallback(
|
|
122
|
+
async (provider, options) => {
|
|
123
|
+
try {
|
|
124
|
+
setIsLoading(true);
|
|
125
|
+
if (provider === "credentials") {
|
|
126
|
+
throw new Error("Credentials flow not yet implemented in popup mode");
|
|
127
|
+
}
|
|
128
|
+
const callbackUrl = `${window.location.origin}/api/sso/callback`;
|
|
129
|
+
const state = btoa(JSON.stringify({
|
|
130
|
+
redirectPath: options?.redirectPath || "/dashboard",
|
|
131
|
+
timestamp: Date.now()
|
|
132
|
+
}));
|
|
133
|
+
const params = new URLSearchParams({
|
|
134
|
+
response_type: "code",
|
|
135
|
+
client_id: appId,
|
|
136
|
+
redirect_uri: callbackUrl,
|
|
137
|
+
state,
|
|
138
|
+
scope: "read write"
|
|
139
|
+
});
|
|
140
|
+
const authorizeUrl = `${apiUrl}/api/oauth/authorize?${params.toString()}`;
|
|
141
|
+
const popup = new OAuthPopup(apiUrl);
|
|
142
|
+
const { code: authCode, state: returnedState } = await popup.open(authorizeUrl);
|
|
143
|
+
const exchangeResponse = await fetch("/api/sso/callback", {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: { "Content-Type": "application/json" },
|
|
146
|
+
credentials: "include",
|
|
147
|
+
body: JSON.stringify({
|
|
148
|
+
code: authCode,
|
|
149
|
+
state: returnedState
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
if (!exchangeResponse.ok) {
|
|
153
|
+
const error = await exchangeResponse.json();
|
|
154
|
+
throw new Error(error.message || "Token exchange failed");
|
|
155
|
+
}
|
|
156
|
+
await loadSession();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error("[AuthTara] Sign in failed:", error);
|
|
159
|
+
throw error;
|
|
160
|
+
} finally {
|
|
161
|
+
setIsLoading(false);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
[appId, apiUrl, loadSession]
|
|
165
|
+
);
|
|
166
|
+
const signOut = React.useCallback(async () => {
|
|
167
|
+
try {
|
|
168
|
+
await fetch("/api/auth/logout", {
|
|
169
|
+
method: "POST",
|
|
170
|
+
credentials: "include"
|
|
171
|
+
});
|
|
172
|
+
setUser(null);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error("[AuthTara] Sign out failed:", error);
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
const refreshSession = React.useCallback(async () => {
|
|
179
|
+
await loadSession();
|
|
180
|
+
}, [loadSession]);
|
|
181
|
+
const value = {
|
|
182
|
+
isAuthenticated: !!user,
|
|
183
|
+
user,
|
|
184
|
+
isLoading,
|
|
185
|
+
signIn,
|
|
186
|
+
signOut,
|
|
187
|
+
refreshSession
|
|
188
|
+
};
|
|
189
|
+
return /* @__PURE__ */ jsx(AuthTaraContext.Provider, { value, children });
|
|
190
|
+
}
|
|
191
|
+
function useAuth() {
|
|
192
|
+
const context = React.useContext(AuthTaraContext);
|
|
193
|
+
if (!context) {
|
|
194
|
+
throw new Error("useAuth must be used within AuthTaraProvider");
|
|
195
|
+
}
|
|
196
|
+
return context;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/components/AuthTaraAuth.tsx
|
|
200
|
+
import * as React2 from "react";
|
|
201
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
202
|
+
function AuthTaraAuth({
|
|
203
|
+
// mode = 'modal', // Reserved for future use
|
|
204
|
+
appearance,
|
|
205
|
+
redirectUrl = "/dashboard",
|
|
206
|
+
onSuccess,
|
|
207
|
+
onError
|
|
208
|
+
}) {
|
|
209
|
+
const { signIn, isLoading, user } = useAuth();
|
|
210
|
+
const [error, setError] = React2.useState(null);
|
|
211
|
+
const [provider, setProvider] = React2.useState(null);
|
|
212
|
+
async function handleSignIn(selectedProvider) {
|
|
213
|
+
setError(null);
|
|
214
|
+
setProvider(selectedProvider);
|
|
215
|
+
try {
|
|
216
|
+
await signIn(selectedProvider, { redirectPath: redirectUrl });
|
|
217
|
+
onSuccess?.({ user });
|
|
218
|
+
if (redirectUrl) {
|
|
219
|
+
window.location.href = redirectUrl;
|
|
220
|
+
}
|
|
221
|
+
} catch (err) {
|
|
222
|
+
const message = err instanceof Error ? err.message : "Authentication failed";
|
|
223
|
+
setError(message);
|
|
224
|
+
onError?.(err);
|
|
225
|
+
} finally {
|
|
226
|
+
setProvider(null);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const isProviderLoading = (p) => isLoading && provider === p;
|
|
230
|
+
return /* @__PURE__ */ jsxs("div", { className: "authtara-auth-container", style: { maxWidth: "400px", margin: "0 auto" }, children: [
|
|
231
|
+
/* @__PURE__ */ jsxs(
|
|
232
|
+
"div",
|
|
233
|
+
{
|
|
234
|
+
className: "authtara-auth-card",
|
|
235
|
+
style: {
|
|
236
|
+
padding: "2rem",
|
|
237
|
+
border: "1px solid #e5e7eb",
|
|
238
|
+
borderRadius: "0.5rem",
|
|
239
|
+
backgroundColor: appearance?.theme === "dark" ? "#1f2937" : "#ffffff"
|
|
240
|
+
},
|
|
241
|
+
children: [
|
|
242
|
+
/* @__PURE__ */ jsx2(
|
|
243
|
+
"h2",
|
|
244
|
+
{
|
|
245
|
+
style: {
|
|
246
|
+
fontSize: "1.5rem",
|
|
247
|
+
fontWeight: "bold",
|
|
248
|
+
marginBottom: "1.5rem",
|
|
249
|
+
color: appearance?.theme === "dark" ? "#ffffff" : "#111827"
|
|
250
|
+
},
|
|
251
|
+
children: "Sign in to continue"
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
error && /* @__PURE__ */ jsx2(
|
|
255
|
+
"div",
|
|
256
|
+
{
|
|
257
|
+
style: {
|
|
258
|
+
padding: "0.75rem",
|
|
259
|
+
marginBottom: "1rem",
|
|
260
|
+
backgroundColor: "#fee2e2",
|
|
261
|
+
color: "#991b1b",
|
|
262
|
+
borderRadius: "0.375rem",
|
|
263
|
+
fontSize: "0.875rem"
|
|
264
|
+
},
|
|
265
|
+
children: error
|
|
266
|
+
}
|
|
267
|
+
),
|
|
268
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
269
|
+
/* @__PURE__ */ jsxs(
|
|
270
|
+
"button",
|
|
271
|
+
{
|
|
272
|
+
onClick: () => handleSignIn("google"),
|
|
273
|
+
disabled: isLoading,
|
|
274
|
+
style: {
|
|
275
|
+
display: "flex",
|
|
276
|
+
alignItems: "center",
|
|
277
|
+
justifyContent: "center",
|
|
278
|
+
gap: "0.5rem",
|
|
279
|
+
padding: "0.75rem 1rem",
|
|
280
|
+
border: "1px solid #d1d5db",
|
|
281
|
+
borderRadius: "0.375rem",
|
|
282
|
+
backgroundColor: "#ffffff",
|
|
283
|
+
color: "#374151",
|
|
284
|
+
fontSize: "0.875rem",
|
|
285
|
+
fontWeight: "500",
|
|
286
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
287
|
+
opacity: isLoading ? 0.6 : 1,
|
|
288
|
+
transition: "all 0.2s"
|
|
289
|
+
},
|
|
290
|
+
onMouseOver: (e) => {
|
|
291
|
+
if (!isLoading) {
|
|
292
|
+
e.currentTarget.style.backgroundColor = "#f9fafb";
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
onMouseOut: (e) => {
|
|
296
|
+
e.currentTarget.style.backgroundColor = "#ffffff";
|
|
297
|
+
},
|
|
298
|
+
children: [
|
|
299
|
+
isProviderLoading("google") ? /* @__PURE__ */ jsx2(
|
|
300
|
+
"div",
|
|
301
|
+
{
|
|
302
|
+
style: {
|
|
303
|
+
width: "1rem",
|
|
304
|
+
height: "1rem",
|
|
305
|
+
border: "2px solid #d1d5db",
|
|
306
|
+
borderTopColor: "#3b82f6",
|
|
307
|
+
borderRadius: "50%",
|
|
308
|
+
animation: "spin 1s linear infinite"
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
) : /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
|
|
312
|
+
/* @__PURE__ */ jsx2(
|
|
313
|
+
"path",
|
|
314
|
+
{
|
|
315
|
+
fill: "#4285F4",
|
|
316
|
+
d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"
|
|
317
|
+
}
|
|
318
|
+
),
|
|
319
|
+
/* @__PURE__ */ jsx2(
|
|
320
|
+
"path",
|
|
321
|
+
{
|
|
322
|
+
fill: "#34A853",
|
|
323
|
+
d: "M9.003 18c2.43 0 4.467-.806 5.956-2.18L12.05 13.56c-.806.54-1.837.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332C2.44 15.983 5.485 18 9.003 18z"
|
|
324
|
+
}
|
|
325
|
+
),
|
|
326
|
+
/* @__PURE__ */ jsx2(
|
|
327
|
+
"path",
|
|
328
|
+
{
|
|
329
|
+
fill: "#FBBC05",
|
|
330
|
+
d: "M3.964 10.712c-.18-.54-.282-1.117-.282-1.71 0-.593.102-1.17.282-1.71V4.96H.957C.347 6.175 0 7.55 0 9.002c0 1.452.348 2.827.957 4.042l3.007-2.332z"
|
|
331
|
+
}
|
|
332
|
+
),
|
|
333
|
+
/* @__PURE__ */ jsx2(
|
|
334
|
+
"path",
|
|
335
|
+
{
|
|
336
|
+
fill: "#EA4335",
|
|
337
|
+
d: "M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.003 0 5.485 0 2.44 2.017.96 4.958L3.967 7.29c.708-2.127 2.692-3.71 5.036-3.71z"
|
|
338
|
+
}
|
|
339
|
+
)
|
|
340
|
+
] }),
|
|
341
|
+
"Continue with Google"
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
/* @__PURE__ */ jsxs(
|
|
346
|
+
"button",
|
|
347
|
+
{
|
|
348
|
+
onClick: () => handleSignIn("github"),
|
|
349
|
+
disabled: isLoading,
|
|
350
|
+
style: {
|
|
351
|
+
display: "flex",
|
|
352
|
+
alignItems: "center",
|
|
353
|
+
justifyContent: "center",
|
|
354
|
+
gap: "0.5rem",
|
|
355
|
+
padding: "0.75rem 1rem",
|
|
356
|
+
border: "1px solid #d1d5db",
|
|
357
|
+
borderRadius: "0.375rem",
|
|
358
|
+
backgroundColor: "#24292e",
|
|
359
|
+
color: "#ffffff",
|
|
360
|
+
fontSize: "0.875rem",
|
|
361
|
+
fontWeight: "500",
|
|
362
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
363
|
+
opacity: isLoading ? 0.6 : 1,
|
|
364
|
+
transition: "all 0.2s"
|
|
365
|
+
},
|
|
366
|
+
onMouseOver: (e) => {
|
|
367
|
+
if (!isLoading) {
|
|
368
|
+
e.currentTarget.style.backgroundColor = "#1b1f23";
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
onMouseOut: (e) => {
|
|
372
|
+
e.currentTarget.style.backgroundColor = "#24292e";
|
|
373
|
+
},
|
|
374
|
+
children: [
|
|
375
|
+
isProviderLoading("github") ? /* @__PURE__ */ jsx2(
|
|
376
|
+
"div",
|
|
377
|
+
{
|
|
378
|
+
style: {
|
|
379
|
+
width: "1rem",
|
|
380
|
+
height: "1rem",
|
|
381
|
+
border: "2px solid #ffffff40",
|
|
382
|
+
borderTopColor: "#ffffff",
|
|
383
|
+
borderRadius: "50%",
|
|
384
|
+
animation: "spin 1s linear infinite"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
) : /* @__PURE__ */ jsx2("svg", { width: "18", height: "18", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" }) }),
|
|
388
|
+
"Continue with GitHub"
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
)
|
|
392
|
+
] }),
|
|
393
|
+
/* @__PURE__ */ jsx2(
|
|
394
|
+
"p",
|
|
395
|
+
{
|
|
396
|
+
style: {
|
|
397
|
+
marginTop: "1.5rem",
|
|
398
|
+
fontSize: "0.75rem",
|
|
399
|
+
color: appearance?.theme === "dark" ? "#9ca3af" : "#6b7280",
|
|
400
|
+
textAlign: "center"
|
|
401
|
+
},
|
|
402
|
+
children: "By continuing, you agree to our Terms of Service and Privacy Policy"
|
|
403
|
+
}
|
|
404
|
+
)
|
|
405
|
+
]
|
|
406
|
+
}
|
|
407
|
+
),
|
|
408
|
+
/* @__PURE__ */ jsx2("style", { children: `
|
|
409
|
+
@keyframes spin {
|
|
410
|
+
to { transform: rotate(360deg); }
|
|
411
|
+
}
|
|
412
|
+
` })
|
|
413
|
+
] });
|
|
414
|
+
}
|
|
415
|
+
export {
|
|
416
|
+
AuthTaraAuth,
|
|
417
|
+
AuthTaraProvider,
|
|
418
|
+
useAuth
|
|
419
|
+
};
|
package/package.json
CHANGED
|
@@ -1,72 +1,91 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "authtara-sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "SDK Client untuk integrasi dengan DigitalSolution Platform - SSO, Billing, dan Metering",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.mjs",
|
|
12
|
-
"require": "./dist/index.js"
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "authtara-sdk",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "SDK Client untuk integrasi dengan DigitalSolution Platform - SSO, Billing, dan Metering",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react.d.ts",
|
|
16
|
+
"import": "./dist/react.mjs",
|
|
17
|
+
"require": "./dist/react.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup src/index.ts src/react.ts --format cjs,esm --dts --clean",
|
|
27
|
+
"dev": "tsup src/index.ts src/react.ts --format cjs,esm --dts --watch",
|
|
28
|
+
"test": "vitest",
|
|
29
|
+
"test:run": "vitest run",
|
|
30
|
+
"test:coverage": "vitest run --coverage",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"prepublishOnly": "bun run build && bun test:run",
|
|
33
|
+
"release": "bun run build && bun test:run && npm version patch",
|
|
34
|
+
"release:minor": "bun run build && bun test:run && npm version minor",
|
|
35
|
+
"release:major": "bun run build && bun test:run && npm version major"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"digitalsolution",
|
|
39
|
+
"authtara",
|
|
40
|
+
"sdk",
|
|
41
|
+
"sso",
|
|
42
|
+
"authentication",
|
|
43
|
+
"billing",
|
|
44
|
+
"metering",
|
|
45
|
+
"oauth",
|
|
46
|
+
"jwt",
|
|
47
|
+
"saas"
|
|
48
|
+
],
|
|
49
|
+
"author": "DigitalSolution Team",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/digitalsolution/authtara-sdk.git"
|
|
54
|
+
},
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/digitalsolution/authtara-sdk/issues",
|
|
57
|
+
"email": "support@digitalsolution.com"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://docs.digitalsolution.com/sdk",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"jose": "^6.0.11"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
65
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependenciesMeta": {
|
|
68
|
+
"react": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"react-dom": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/node": "^24.0.0",
|
|
77
|
+
"@types/react": "^19.2.8",
|
|
78
|
+
"@types/react-dom": "^19.2.3",
|
|
79
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
80
|
+
"tsup": "^8.5.0",
|
|
81
|
+
"typescript": "^5.9.3",
|
|
82
|
+
"vitest": "^4.0.15"
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=18.0.0"
|
|
86
|
+
},
|
|
87
|
+
"publishConfig": {
|
|
88
|
+
"access": "public",
|
|
89
|
+
"registry": "https://registry.npmjs.org/"
|
|
90
|
+
}
|
|
72
91
|
}
|