@howone/sdk 0.1.0 → 0.1.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.mts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +620 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +615 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -3
- package/README.md +0 -129
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,233 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __esm = (fn, res) => function __init() {
|
|
6
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
|
+
};
|
|
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/auth/index.ts
|
|
23
|
+
var auth_exports = {};
|
|
24
|
+
__export(auth_exports, {
|
|
25
|
+
AUTH_TOKEN_KEY: () => AUTH_TOKEN_KEY,
|
|
26
|
+
getToken: () => getToken,
|
|
27
|
+
isTokenValid: () => isTokenValid,
|
|
28
|
+
onAuthStateChanged: () => onAuthStateChanged,
|
|
29
|
+
parseUserFromToken: () => parseUserFromToken,
|
|
30
|
+
setToken: () => setToken,
|
|
31
|
+
useAuth: () => useAuth
|
|
32
|
+
});
|
|
33
|
+
import { useEffect, useState } from "react";
|
|
34
|
+
function setCookie(name, value, days = 30) {
|
|
35
|
+
try {
|
|
36
|
+
if (typeof document === "undefined") return;
|
|
37
|
+
if (!value) {
|
|
38
|
+
document.cookie = `${name}=; Max-Age=0; path=/; SameSite=Lax`;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const expires = new Date(Date.now() + days * 24 * 60 * 60 * 1e3).toUTCString();
|
|
42
|
+
document.cookie = `${name}=${encodeURIComponent(value)}; Expires=${expires}; Path=/; SameSite=Lax`;
|
|
43
|
+
} catch (e) {
|
|
44
|
+
void e;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function getCookie(name) {
|
|
48
|
+
try {
|
|
49
|
+
if (typeof document === "undefined") return null;
|
|
50
|
+
const match = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([.$?*|{}()\[\]\\/+^])/g, "\\$1") + "=([^;]*)"));
|
|
51
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function setToken(token) {
|
|
57
|
+
try {
|
|
58
|
+
setCookie(AUTH_TOKEN_KEY, token, 30);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
void e;
|
|
61
|
+
}
|
|
62
|
+
if (!token) {
|
|
63
|
+
try {
|
|
64
|
+
notifyAuthStateChanged();
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
notifyAuthStateChanged();
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function getToken() {
|
|
75
|
+
try {
|
|
76
|
+
const cookie = getCookie(AUTH_TOKEN_KEY);
|
|
77
|
+
if (cookie) return cookie;
|
|
78
|
+
} catch (e) {
|
|
79
|
+
void e;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
function decodeJwtPayload(token) {
|
|
84
|
+
try {
|
|
85
|
+
const payload = token.split(".")[1];
|
|
86
|
+
if (!payload) return null;
|
|
87
|
+
let base64 = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
88
|
+
const pad = base64.length % 4;
|
|
89
|
+
if (pad === 2) base64 += "==";
|
|
90
|
+
else if (pad === 3) base64 += "=";
|
|
91
|
+
else if (pad !== 0) return null;
|
|
92
|
+
const json = atob(base64);
|
|
93
|
+
return JSON.parse(json);
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function parseUserFromToken(token) {
|
|
99
|
+
if (!token) return null;
|
|
100
|
+
const payload = decodeJwtPayload(token);
|
|
101
|
+
if (!payload) return null;
|
|
102
|
+
return {
|
|
103
|
+
id: payload.userId || payload.sub || "",
|
|
104
|
+
email: payload.email || "",
|
|
105
|
+
name: payload.name || "",
|
|
106
|
+
avatar: payload.avatar || payload.picture || ""
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function isTokenValid(token) {
|
|
110
|
+
if (!token) return false;
|
|
111
|
+
const payload = decodeJwtPayload(token);
|
|
112
|
+
if (!payload) return false;
|
|
113
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
114
|
+
const expCandidate = payload.exp ?? payload.expires_at;
|
|
115
|
+
const exp = Number(expCandidate);
|
|
116
|
+
if (!exp || !Number.isFinite(exp)) return true;
|
|
117
|
+
return exp > now;
|
|
118
|
+
}
|
|
119
|
+
function useAuth() {
|
|
120
|
+
const [token, setTokenState] = useState(() => getToken());
|
|
121
|
+
const [user, setUser] = useState(() => parseUserFromToken(getToken()));
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
const onStorage = () => {
|
|
124
|
+
const t = getToken();
|
|
125
|
+
setTokenState(t);
|
|
126
|
+
setUser(parseUserFromToken(t));
|
|
127
|
+
};
|
|
128
|
+
window.addEventListener("storage", onStorage);
|
|
129
|
+
const unsubscribe = onAuthStateChanged(() => {
|
|
130
|
+
setTokenState(getToken());
|
|
131
|
+
setUser(parseUserFromToken(getToken()));
|
|
132
|
+
});
|
|
133
|
+
return () => {
|
|
134
|
+
window.removeEventListener("storage", onStorage);
|
|
135
|
+
unsubscribe();
|
|
136
|
+
};
|
|
137
|
+
}, []);
|
|
138
|
+
const logout = () => {
|
|
139
|
+
setToken(null);
|
|
140
|
+
setTokenState(null);
|
|
141
|
+
setUser(null);
|
|
142
|
+
notifyAuthStateChanged();
|
|
143
|
+
};
|
|
144
|
+
return {
|
|
145
|
+
token,
|
|
146
|
+
user,
|
|
147
|
+
isAuthenticated: !!token && isTokenValid(token),
|
|
148
|
+
logout
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function onAuthStateChanged(cb) {
|
|
152
|
+
try {
|
|
153
|
+
const current = { user: parseUserFromToken(getToken()), isLoading: false };
|
|
154
|
+
cb(current);
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
authSubscribers.add(cb);
|
|
158
|
+
return () => {
|
|
159
|
+
authSubscribers.delete(cb);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function notifyAuthStateChanged() {
|
|
163
|
+
const state = { user: parseUserFromToken(getToken()), isLoading: false };
|
|
164
|
+
for (const cb of Array.from(authSubscribers)) {
|
|
165
|
+
try {
|
|
166
|
+
cb(state);
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
var AUTH_TOKEN_KEY, authSubscribers;
|
|
172
|
+
var init_auth = __esm({
|
|
173
|
+
"src/auth/index.ts"() {
|
|
174
|
+
"use strict";
|
|
175
|
+
AUTH_TOKEN_KEY = "auth_token";
|
|
176
|
+
authSubscribers = /* @__PURE__ */ new Set();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// src/config.ts
|
|
181
|
+
var config_exports = {};
|
|
182
|
+
__export(config_exports, {
|
|
183
|
+
AUTH_ROOT: () => AUTH_ROOT,
|
|
184
|
+
default: () => config_default,
|
|
185
|
+
getAuthRoot: () => getAuthRoot,
|
|
186
|
+
getDefaultProjectId: () => getDefaultProjectId,
|
|
187
|
+
setAuthRoot: () => setAuthRoot,
|
|
188
|
+
setDefaultProjectId: () => setDefaultProjectId
|
|
189
|
+
});
|
|
190
|
+
function setAuthRoot(url) {
|
|
191
|
+
AUTH_ROOT_VALUE = url.replace(/\/+$/g, "");
|
|
192
|
+
}
|
|
193
|
+
function getAuthRoot() {
|
|
194
|
+
return AUTH_ROOT_VALUE;
|
|
195
|
+
}
|
|
196
|
+
function setDefaultProjectId(id) {
|
|
197
|
+
DEFAULT_PROJECT_ID = id;
|
|
198
|
+
}
|
|
199
|
+
function getDefaultProjectId() {
|
|
200
|
+
try {
|
|
201
|
+
if (DEFAULT_PROJECT_ID) return DEFAULT_PROJECT_ID;
|
|
202
|
+
const g = globalThis.__HOWONE_PROJECT_ID__;
|
|
203
|
+
if (typeof g === "string" && g.length > 0) return String(g);
|
|
204
|
+
return null;
|
|
205
|
+
} catch {
|
|
206
|
+
return DEFAULT_PROJECT_ID;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
var AUTH_ROOT_VALUE, DEFAULT_PROJECT_ID, AUTH_ROOT, config_default;
|
|
210
|
+
var init_config = __esm({
|
|
211
|
+
"src/config.ts"() {
|
|
212
|
+
"use strict";
|
|
213
|
+
AUTH_ROOT_VALUE = "http://localhost:3000";
|
|
214
|
+
DEFAULT_PROJECT_ID = null;
|
|
215
|
+
AUTH_ROOT = getAuthRoot();
|
|
216
|
+
try {
|
|
217
|
+
const g = globalThis.__HOWONE_AUTH_ROOT__;
|
|
218
|
+
if (typeof g === "string" && g.length > 0) {
|
|
219
|
+
setAuthRoot(g);
|
|
220
|
+
}
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
config_default = {
|
|
224
|
+
getAuthRoot,
|
|
225
|
+
setAuthRoot,
|
|
226
|
+
AUTH_ROOT: () => AUTH_ROOT_VALUE
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
1
231
|
// src/components/FloatingButton.tsx
|
|
2
232
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
233
|
var FloatingButton = ({
|
|
@@ -282,9 +512,21 @@ var UnifiedAuthService = class {
|
|
|
282
512
|
checkOAuthCallback() {
|
|
283
513
|
const urlParams = new URLSearchParams(window.location.search);
|
|
284
514
|
const token = urlParams.get("token");
|
|
515
|
+
const accessTokenQuery = urlParams.get("access_token");
|
|
285
516
|
const error = urlParams.get("error");
|
|
286
517
|
const userParam = urlParams.get("user");
|
|
287
|
-
|
|
518
|
+
let hashToken = null;
|
|
519
|
+
try {
|
|
520
|
+
if (window.location.hash && window.location.hash.length > 1) {
|
|
521
|
+
const hash = window.location.hash.slice(1);
|
|
522
|
+
const hashParams = new URLSearchParams(hash);
|
|
523
|
+
hashToken = hashParams.get("access_token") || hashParams.get("token") || null;
|
|
524
|
+
}
|
|
525
|
+
} catch {
|
|
526
|
+
hashToken = null;
|
|
527
|
+
}
|
|
528
|
+
const finalToken = accessTokenQuery || token || hashToken;
|
|
529
|
+
if (finalToken) {
|
|
288
530
|
let user = null;
|
|
289
531
|
if (userParam) {
|
|
290
532
|
try {
|
|
@@ -292,9 +534,20 @@ var UnifiedAuthService = class {
|
|
|
292
534
|
} catch (e) {
|
|
293
535
|
}
|
|
294
536
|
}
|
|
295
|
-
this.saveAuthData(
|
|
296
|
-
|
|
297
|
-
|
|
537
|
+
this.saveAuthData(finalToken);
|
|
538
|
+
try {
|
|
539
|
+
const u = new URL(window.location.href);
|
|
540
|
+
u.searchParams.delete("token");
|
|
541
|
+
u.searchParams.delete("access_token");
|
|
542
|
+
u.hash = "";
|
|
543
|
+
window.history.replaceState({}, document.title, u.toString());
|
|
544
|
+
} catch (e) {
|
|
545
|
+
try {
|
|
546
|
+
window.history.replaceState({}, document.title, window.location.pathname);
|
|
547
|
+
} catch {
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return { success: true, token: finalToken, user };
|
|
298
551
|
}
|
|
299
552
|
if (error) {
|
|
300
553
|
window.history.replaceState({}, document.title, window.location.pathname);
|
|
@@ -335,18 +588,15 @@ var UnifiedAuthService = class {
|
|
|
335
588
|
*/
|
|
336
589
|
getSavedAuthData() {
|
|
337
590
|
try {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
user = JSON.parse(userJson);
|
|
345
|
-
} catch (e) {
|
|
346
|
-
console.error("Failed to parse saved user data:", e);
|
|
347
|
-
}
|
|
591
|
+
let token = null;
|
|
592
|
+
try {
|
|
593
|
+
const { getToken: getToken2 } = (init_auth(), __toCommonJS(auth_exports));
|
|
594
|
+
if (getToken2) token = getToken2();
|
|
595
|
+
} catch {
|
|
596
|
+
token = null;
|
|
348
597
|
}
|
|
349
|
-
|
|
598
|
+
if (!token) return null;
|
|
599
|
+
return { token };
|
|
350
600
|
} catch (e) {
|
|
351
601
|
console.error("Failed to get auth data from localStorage:", e);
|
|
352
602
|
return null;
|
|
@@ -355,10 +605,13 @@ var UnifiedAuthService = class {
|
|
|
355
605
|
/**
|
|
356
606
|
* 保存认证数据到本地存储
|
|
357
607
|
*/
|
|
358
|
-
saveAuthData(token
|
|
608
|
+
saveAuthData(token) {
|
|
359
609
|
try {
|
|
360
|
-
|
|
361
|
-
|
|
610
|
+
try {
|
|
611
|
+
const { setToken: setToken2 } = (init_auth(), __toCommonJS(auth_exports));
|
|
612
|
+
if (setToken2) setToken2(token);
|
|
613
|
+
} catch {
|
|
614
|
+
}
|
|
362
615
|
} catch (e) {
|
|
363
616
|
console.error("Failed to save auth data to localStorage:", e);
|
|
364
617
|
}
|
|
@@ -631,6 +884,9 @@ function createArtifactsClient(req) {
|
|
|
631
884
|
}
|
|
632
885
|
|
|
633
886
|
// src/services/index.ts
|
|
887
|
+
init_auth();
|
|
888
|
+
init_config();
|
|
889
|
+
init_config();
|
|
634
890
|
var request = new request_default({
|
|
635
891
|
baseURL: "https://create-x-backend.fly.dev/api",
|
|
636
892
|
timeout: 6e4,
|
|
@@ -674,6 +930,12 @@ function createClient(opts) {
|
|
|
674
930
|
const biz = opts?.requestInstance || request;
|
|
675
931
|
const ai = opts?.aiRequestInstance || aiRequest;
|
|
676
932
|
let token = null;
|
|
933
|
+
try {
|
|
934
|
+
if (opts?.projectId) {
|
|
935
|
+
setDefaultProjectId(String(opts.projectId));
|
|
936
|
+
}
|
|
937
|
+
} catch {
|
|
938
|
+
}
|
|
677
939
|
function applyToken(t) {
|
|
678
940
|
try {
|
|
679
941
|
try {
|
|
@@ -753,6 +1015,8 @@ function createClient(opts) {
|
|
|
753
1015
|
} catch (_e) {
|
|
754
1016
|
}
|
|
755
1017
|
return {
|
|
1018
|
+
// expose projectId so consumers can read it from the client instance
|
|
1019
|
+
projectId: opts?.projectId ?? null,
|
|
756
1020
|
request: biz,
|
|
757
1021
|
aiRequest: ai,
|
|
758
1022
|
workflowRequest: ai,
|
|
@@ -768,11 +1032,19 @@ function createClient(opts) {
|
|
|
768
1032
|
isAuthenticated: () => Boolean(token),
|
|
769
1033
|
// minimal login/logout stubs - consumers can override behavior
|
|
770
1034
|
login: (redirect) => {
|
|
771
|
-
if (
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1035
|
+
if (typeof window === "undefined") return;
|
|
1036
|
+
const loc = redirect || window.location.href;
|
|
1037
|
+
try {
|
|
1038
|
+
const root = getAuthRoot() || "http://localhost:3000";
|
|
1039
|
+
const authUrl = new URL("/auth", String(root));
|
|
1040
|
+
authUrl.searchParams.set("redirect_uri", String(loc));
|
|
1041
|
+
if (opts?.projectId) authUrl.searchParams.set("project_id", String(opts.projectId));
|
|
1042
|
+
window.location.href = authUrl.toString();
|
|
1043
|
+
} catch {
|
|
1044
|
+
const encoded = encodeURIComponent(String(loc));
|
|
1045
|
+
const pid = opts?.projectId ? `&project_id=${encodeURIComponent(String(opts.projectId))}` : "";
|
|
1046
|
+
const root = "http://localhost:3000";
|
|
1047
|
+
window.location.href = `${root}/auth?redirect_uri=${encoded}${pid}`;
|
|
776
1048
|
}
|
|
777
1049
|
},
|
|
778
1050
|
logout: () => {
|
|
@@ -784,7 +1056,7 @@ function createClient(opts) {
|
|
|
784
1056
|
}
|
|
785
1057
|
|
|
786
1058
|
// src/components/auth/LoginForm.tsx
|
|
787
|
-
import { useState, useEffect } from "react";
|
|
1059
|
+
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
788
1060
|
import { Icon } from "@iconify/react";
|
|
789
1061
|
import { Loader2 } from "lucide-react";
|
|
790
1062
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -793,12 +1065,12 @@ var LoginForm = ({
|
|
|
793
1065
|
appName = "AI Application Platform",
|
|
794
1066
|
className = ""
|
|
795
1067
|
}) => {
|
|
796
|
-
const [email, setEmail] =
|
|
797
|
-
const [code, setCode] =
|
|
798
|
-
const [validationErrors, setValidationErrors] =
|
|
799
|
-
const [isAnyLoading, setIsAnyLoading] =
|
|
800
|
-
const [codeSent, setCodeSent] =
|
|
801
|
-
const [loginError, setLoginError] =
|
|
1068
|
+
const [email, setEmail] = useState2("");
|
|
1069
|
+
const [code, setCode] = useState2("");
|
|
1070
|
+
const [validationErrors, setValidationErrors] = useState2({});
|
|
1071
|
+
const [isAnyLoading, setIsAnyLoading] = useState2(false);
|
|
1072
|
+
const [codeSent, setCodeSent] = useState2(false);
|
|
1073
|
+
const [loginError, setLoginError] = useState2(null);
|
|
802
1074
|
const googleLogin = async () => {
|
|
803
1075
|
console.log("Google login clicked");
|
|
804
1076
|
};
|
|
@@ -817,7 +1089,7 @@ var LoginForm = ({
|
|
|
817
1089
|
setLoginError(null);
|
|
818
1090
|
setValidationErrors({});
|
|
819
1091
|
};
|
|
820
|
-
|
|
1092
|
+
useEffect2(() => {
|
|
821
1093
|
if (loginError) {
|
|
822
1094
|
try {
|
|
823
1095
|
const errorObj = JSON.parse(loginError);
|
|
@@ -1000,7 +1272,9 @@ var LoginForm = ({
|
|
|
1000
1272
|
};
|
|
1001
1273
|
|
|
1002
1274
|
// src/components/auth/AuthGuard.tsx
|
|
1275
|
+
init_auth();
|
|
1003
1276
|
import { Navigate, useLocation } from "react-router-dom";
|
|
1277
|
+
init_config();
|
|
1004
1278
|
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1005
1279
|
var AuthGuard = ({
|
|
1006
1280
|
children,
|
|
@@ -1010,8 +1284,8 @@ var AuthGuard = ({
|
|
|
1010
1284
|
roles = [],
|
|
1011
1285
|
permissions = []
|
|
1012
1286
|
}) => {
|
|
1013
|
-
const isAuthenticated =
|
|
1014
|
-
const user =
|
|
1287
|
+
const { user: parsedUser, isAuthenticated } = useAuth();
|
|
1288
|
+
const user = parsedUser;
|
|
1015
1289
|
const isLoading = false;
|
|
1016
1290
|
const location = useLocation();
|
|
1017
1291
|
if (isLoading) {
|
|
@@ -1021,6 +1295,47 @@ var AuthGuard = ({
|
|
|
1021
1295
|
return /* @__PURE__ */ jsx3("div", { className: "min-h-screen flex items-center justify-center", children: /* @__PURE__ */ jsx3("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600" }) });
|
|
1022
1296
|
}
|
|
1023
1297
|
if (requireAuth && !isAuthenticated) {
|
|
1298
|
+
try {
|
|
1299
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
1300
|
+
const tokenInUrl = urlParams.get("token") || urlParams.get("access_token");
|
|
1301
|
+
let tokenInHash = null;
|
|
1302
|
+
try {
|
|
1303
|
+
if (window.location.hash && window.location.hash.length > 1) {
|
|
1304
|
+
const hashParams = new URLSearchParams(window.location.hash.slice(1));
|
|
1305
|
+
tokenInHash = hashParams.get("access_token") || hashParams.get("token");
|
|
1306
|
+
}
|
|
1307
|
+
} catch {
|
|
1308
|
+
tokenInHash = null;
|
|
1309
|
+
}
|
|
1310
|
+
const localToken = getToken();
|
|
1311
|
+
if (tokenInUrl || tokenInHash) {
|
|
1312
|
+
try {
|
|
1313
|
+
const res = unifiedAuth.checkOAuthCallback();
|
|
1314
|
+
if (res && res.success) {
|
|
1315
|
+
return null;
|
|
1316
|
+
}
|
|
1317
|
+
} catch {
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (localToken) {
|
|
1321
|
+
return null;
|
|
1322
|
+
}
|
|
1323
|
+
} catch (e) {
|
|
1324
|
+
void e;
|
|
1325
|
+
}
|
|
1326
|
+
if (redirectTo === "/login") {
|
|
1327
|
+
const root = getAuthRoot() || "http://localhost:3000";
|
|
1328
|
+
try {
|
|
1329
|
+
const authUrl = new URL("/auth", String(root));
|
|
1330
|
+
authUrl.searchParams.set("redirect_uri", window.location.href);
|
|
1331
|
+
const pid = getDefaultProjectId();
|
|
1332
|
+
if (pid) authUrl.searchParams.set("project_id", pid);
|
|
1333
|
+
window.location.replace(authUrl.toString());
|
|
1334
|
+
} catch {
|
|
1335
|
+
window.location.replace(root);
|
|
1336
|
+
}
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1024
1339
|
return /* @__PURE__ */ jsx3(Navigate, { to: redirectTo, state: { from: location }, replace: true });
|
|
1025
1340
|
}
|
|
1026
1341
|
if (roles.length > 0 && user !== null) {
|
|
@@ -1056,8 +1371,207 @@ var AuthGuard = ({
|
|
|
1056
1371
|
return /* @__PURE__ */ jsx3(Fragment, { children });
|
|
1057
1372
|
};
|
|
1058
1373
|
|
|
1374
|
+
// src/components/auth/AuthRedirector.tsx
|
|
1375
|
+
import { useEffect as useEffect3 } from "react";
|
|
1376
|
+
init_auth();
|
|
1377
|
+
init_config();
|
|
1378
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1379
|
+
var AuthRedirector = ({ fallback }) => {
|
|
1380
|
+
useEffect3(() => {
|
|
1381
|
+
try {
|
|
1382
|
+
const cb = unifiedAuth.checkOAuthCallback();
|
|
1383
|
+
if (cb && cb.success) return;
|
|
1384
|
+
const unsubscribe = onAuthStateChanged((state) => {
|
|
1385
|
+
if (!state.user) {
|
|
1386
|
+
try {
|
|
1387
|
+
const root = getAuthRoot() || "http://localhost:3000";
|
|
1388
|
+
const authUrl = new URL("/auth", String(root));
|
|
1389
|
+
authUrl.searchParams.set("redirect_uri", window.location.href);
|
|
1390
|
+
const pid = getDefaultProjectId && getDefaultProjectId();
|
|
1391
|
+
if (pid) authUrl.searchParams.set("project_id", pid);
|
|
1392
|
+
window.location.replace(authUrl.toString());
|
|
1393
|
+
} catch {
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
return () => {
|
|
1398
|
+
try {
|
|
1399
|
+
unsubscribe();
|
|
1400
|
+
} catch {
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
} catch {
|
|
1404
|
+
}
|
|
1405
|
+
}, []);
|
|
1406
|
+
return /* @__PURE__ */ jsx4("div", { className: "min-h-screen flex items-center justify-center bg-white", children: fallback ?? /* @__PURE__ */ jsx4("div", { className: "text-center", children: /* @__PURE__ */ jsx4("h2", { className: "text-lg font-semibold", children: "Redirecting to authentication..." }) }) });
|
|
1407
|
+
};
|
|
1408
|
+
var AuthRedirector_default = AuthRedirector;
|
|
1409
|
+
|
|
1410
|
+
// src/components/auth/AuthProvider.tsx
|
|
1411
|
+
import { createContext, useContext, useEffect as useEffect4, useState as useState3 } from "react";
|
|
1412
|
+
init_auth();
|
|
1413
|
+
init_config();
|
|
1414
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1415
|
+
var AuthContext = createContext(null);
|
|
1416
|
+
var AuthProvider = ({ children, autoRedirect = true, showFloatingButton = true, projectId }) => {
|
|
1417
|
+
const [user, setUser] = useState3(() => parseUserFromToken(getToken()));
|
|
1418
|
+
const [token, setTokenState] = useState3(() => getToken());
|
|
1419
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
1420
|
+
useEffect4(() => {
|
|
1421
|
+
try {
|
|
1422
|
+
if (projectId) setDefaultProjectId(String(projectId));
|
|
1423
|
+
} catch {
|
|
1424
|
+
}
|
|
1425
|
+
setIsLoading(true);
|
|
1426
|
+
try {
|
|
1427
|
+
const cb = unifiedAuth.checkOAuthCallback();
|
|
1428
|
+
if (cb && cb.success) {
|
|
1429
|
+
setTokenState(cb.token ?? getToken());
|
|
1430
|
+
setUser(cb.user ?? parseUserFromToken(cb.token ?? getToken()));
|
|
1431
|
+
setIsLoading(false);
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
} catch {
|
|
1435
|
+
}
|
|
1436
|
+
const unsubscribe = onAuthStateChanged((state) => {
|
|
1437
|
+
try {
|
|
1438
|
+
setTokenState(getToken());
|
|
1439
|
+
setUser(state.user ?? parseUserFromToken(getToken()));
|
|
1440
|
+
} catch {
|
|
1441
|
+
}
|
|
1442
|
+
setIsLoading(false);
|
|
1443
|
+
if (autoRedirect && !state.user) {
|
|
1444
|
+
try {
|
|
1445
|
+
const root = getAuthRoot() || "http://localhost:3000";
|
|
1446
|
+
const authUrl = new URL("/auth", String(root));
|
|
1447
|
+
authUrl.searchParams.set("redirect_uri", window.location.href);
|
|
1448
|
+
const pid = getDefaultProjectId();
|
|
1449
|
+
if (pid) authUrl.searchParams.set("project_id", pid);
|
|
1450
|
+
window.location.replace(authUrl.toString());
|
|
1451
|
+
} catch {
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
return () => {
|
|
1456
|
+
try {
|
|
1457
|
+
unsubscribe();
|
|
1458
|
+
} catch {
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
}, [autoRedirect]);
|
|
1462
|
+
const logout = () => {
|
|
1463
|
+
try {
|
|
1464
|
+
setToken(null);
|
|
1465
|
+
} catch {
|
|
1466
|
+
}
|
|
1467
|
+
setTokenState(null);
|
|
1468
|
+
setUser(null);
|
|
1469
|
+
};
|
|
1470
|
+
const value = {
|
|
1471
|
+
user,
|
|
1472
|
+
token,
|
|
1473
|
+
isAuthenticated: !!token,
|
|
1474
|
+
isLoading,
|
|
1475
|
+
logout
|
|
1476
|
+
};
|
|
1477
|
+
return /* @__PURE__ */ jsxs4(AuthContext.Provider, { value, children: [
|
|
1478
|
+
children,
|
|
1479
|
+
showFloatingButton && /* @__PURE__ */ jsx5(FloatingButton, { onClick: () => window.open("https://howone.ai", "_blank") })
|
|
1480
|
+
] });
|
|
1481
|
+
};
|
|
1482
|
+
function useAuthContext() {
|
|
1483
|
+
const ctx = useContext(AuthContext);
|
|
1484
|
+
if (!ctx) {
|
|
1485
|
+
const t = getToken();
|
|
1486
|
+
return {
|
|
1487
|
+
user: parseUserFromToken(t),
|
|
1488
|
+
token: t,
|
|
1489
|
+
isAuthenticated: !!t,
|
|
1490
|
+
isLoading: false,
|
|
1491
|
+
logout: () => {
|
|
1492
|
+
try {
|
|
1493
|
+
setToken(null);
|
|
1494
|
+
} catch {
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
return ctx;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
// src/components/index.ts
|
|
1503
|
+
init_auth();
|
|
1504
|
+
|
|
1505
|
+
// src/howone/client.ts
|
|
1506
|
+
init_auth();
|
|
1507
|
+
init_config();
|
|
1508
|
+
var HowoneAuthClient = class {
|
|
1509
|
+
constructor() {
|
|
1510
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1511
|
+
this.loading = false;
|
|
1512
|
+
}
|
|
1513
|
+
emit() {
|
|
1514
|
+
const state = {
|
|
1515
|
+
user: parseUserFromToken(getToken()),
|
|
1516
|
+
isLoading: this.loading
|
|
1517
|
+
};
|
|
1518
|
+
for (const l of this.listeners) {
|
|
1519
|
+
try {
|
|
1520
|
+
l(state);
|
|
1521
|
+
} catch (e) {
|
|
1522
|
+
void e;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
onAuthStateChanged(listener) {
|
|
1527
|
+
this.listeners.add(listener);
|
|
1528
|
+
try {
|
|
1529
|
+
listener({ user: parseUserFromToken(getToken()), isLoading: this.loading });
|
|
1530
|
+
} catch (e) {
|
|
1531
|
+
void e;
|
|
1532
|
+
}
|
|
1533
|
+
return () => {
|
|
1534
|
+
this.listeners.delete(listener);
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
// Simple redirect-based login trigger (consumer can override)
|
|
1538
|
+
login() {
|
|
1539
|
+
const root = getAuthRoot() || "http://localhost:3000";
|
|
1540
|
+
try {
|
|
1541
|
+
const loc = window.location.href;
|
|
1542
|
+
const authUrl = new URL("/auth", String(root));
|
|
1543
|
+
authUrl.searchParams.set("redirect_uri", String(loc));
|
|
1544
|
+
try {
|
|
1545
|
+
const cfg = (init_config(), __toCommonJS(config_exports));
|
|
1546
|
+
const pid = cfg.getDefaultProjectId && cfg.getDefaultProjectId();
|
|
1547
|
+
if (pid) authUrl.searchParams.set("project_id", String(pid));
|
|
1548
|
+
} catch {
|
|
1549
|
+
}
|
|
1550
|
+
window.location.replace(authUrl.toString());
|
|
1551
|
+
} catch {
|
|
1552
|
+
window.location.replace(String(root));
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
logout() {
|
|
1556
|
+
setToken(null);
|
|
1557
|
+
this.emit();
|
|
1558
|
+
}
|
|
1559
|
+
getUser() {
|
|
1560
|
+
return parseUserFromToken(getToken());
|
|
1561
|
+
}
|
|
1562
|
+
// helper to programmatically set token (e.g., after callback handling)
|
|
1563
|
+
setToken(token) {
|
|
1564
|
+
setToken(token);
|
|
1565
|
+
this.emit();
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
var howone = {
|
|
1569
|
+
auth: new HowoneAuthClient()
|
|
1570
|
+
};
|
|
1571
|
+
var client_default = howone;
|
|
1572
|
+
|
|
1059
1573
|
// src/components/ui/Loading.tsx
|
|
1060
|
-
import { jsx as
|
|
1574
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1061
1575
|
var Loading = ({
|
|
1062
1576
|
size = "md",
|
|
1063
1577
|
text = "Loading...",
|
|
@@ -1070,14 +1584,14 @@ var Loading = ({
|
|
|
1070
1584
|
lg: "h-12 w-12"
|
|
1071
1585
|
};
|
|
1072
1586
|
const containerClasses = fullScreen ? "fixed inset-0 flex items-center justify-center bg-white/80 backdrop-blur-sm z-50" : "flex items-center justify-center p-4";
|
|
1073
|
-
return /* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1587
|
+
return /* @__PURE__ */ jsx6("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
|
|
1588
|
+
/* @__PURE__ */ jsx6(
|
|
1075
1589
|
"div",
|
|
1076
1590
|
{
|
|
1077
1591
|
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 mx-auto ${sizeClasses[size]}`
|
|
1078
1592
|
}
|
|
1079
1593
|
),
|
|
1080
|
-
text && /* @__PURE__ */
|
|
1594
|
+
text && /* @__PURE__ */ jsx6("p", { className: "mt-2 text-sm text-gray-600", children: text })
|
|
1081
1595
|
] }) });
|
|
1082
1596
|
};
|
|
1083
1597
|
var LoadingSpinner = ({
|
|
@@ -1089,7 +1603,7 @@ var LoadingSpinner = ({
|
|
|
1089
1603
|
md: "h-8 w-8",
|
|
1090
1604
|
lg: "h-12 w-12"
|
|
1091
1605
|
};
|
|
1092
|
-
return /* @__PURE__ */
|
|
1606
|
+
return /* @__PURE__ */ jsx6(
|
|
1093
1607
|
"div",
|
|
1094
1608
|
{
|
|
1095
1609
|
className: `animate-spin rounded-full border-2 border-gray-300 border-t-blue-600 ${sizeClasses[size]} ${className}`
|
|
@@ -1099,7 +1613,7 @@ var LoadingSpinner = ({
|
|
|
1099
1613
|
|
|
1100
1614
|
// src/components/ui/ErrorBoundary.tsx
|
|
1101
1615
|
import { Component } from "react";
|
|
1102
|
-
import { jsx as
|
|
1616
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1103
1617
|
var ErrorBoundary = class extends Component {
|
|
1104
1618
|
constructor(props) {
|
|
1105
1619
|
super(props);
|
|
@@ -1122,13 +1636,13 @@ var ErrorBoundary = class extends Component {
|
|
|
1122
1636
|
if (this.state.hasError) {
|
|
1123
1637
|
if (this.props.fallback) {
|
|
1124
1638
|
const FallbackComponent = this.props.fallback;
|
|
1125
|
-
return /* @__PURE__ */
|
|
1639
|
+
return /* @__PURE__ */ jsx7(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
|
|
1126
1640
|
}
|
|
1127
|
-
return /* @__PURE__ */
|
|
1128
|
-
/* @__PURE__ */
|
|
1129
|
-
/* @__PURE__ */
|
|
1130
|
-
/* @__PURE__ */
|
|
1131
|
-
/* @__PURE__ */
|
|
1641
|
+
return /* @__PURE__ */ jsx7("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs6("div", { className: "text-center max-w-md", children: [
|
|
1642
|
+
/* @__PURE__ */ jsx7("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
|
|
1643
|
+
/* @__PURE__ */ jsx7("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
|
|
1644
|
+
/* @__PURE__ */ jsx7("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
|
|
1645
|
+
/* @__PURE__ */ jsx7(
|
|
1132
1646
|
"button",
|
|
1133
1647
|
{
|
|
1134
1648
|
onClick: this.handleRetry,
|
|
@@ -1142,10 +1656,10 @@ var ErrorBoundary = class extends Component {
|
|
|
1142
1656
|
return this.props.children;
|
|
1143
1657
|
}
|
|
1144
1658
|
};
|
|
1145
|
-
var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */
|
|
1146
|
-
/* @__PURE__ */
|
|
1147
|
-
/* @__PURE__ */
|
|
1148
|
-
retry && /* @__PURE__ */
|
|
1659
|
+
var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ jsx7("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
|
|
1660
|
+
/* @__PURE__ */ jsx7("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
|
|
1661
|
+
/* @__PURE__ */ jsx7("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
|
|
1662
|
+
retry && /* @__PURE__ */ jsx7(
|
|
1149
1663
|
"button",
|
|
1150
1664
|
{
|
|
1151
1665
|
onClick: retry,
|
|
@@ -1156,11 +1670,11 @@ var DefaultErrorFallback = ({ retry }) => /* @__PURE__ */ jsx5("div", { classNam
|
|
|
1156
1670
|
] }) });
|
|
1157
1671
|
|
|
1158
1672
|
// src/hooks/use-mobile.ts
|
|
1159
|
-
import * as
|
|
1673
|
+
import * as React5 from "react";
|
|
1160
1674
|
var MOBILE_BREAKPOINT = 768;
|
|
1161
1675
|
function useIsMobile() {
|
|
1162
|
-
const [isMobile, setIsMobile] =
|
|
1163
|
-
|
|
1676
|
+
const [isMobile, setIsMobile] = React5.useState(void 0);
|
|
1677
|
+
React5.useEffect(() => {
|
|
1164
1678
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
1165
1679
|
const onChange = () => {
|
|
1166
1680
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
@@ -1173,9 +1687,9 @@ function useIsMobile() {
|
|
|
1173
1687
|
}
|
|
1174
1688
|
|
|
1175
1689
|
// src/hooks/use-local-storage.ts
|
|
1176
|
-
import { useState as
|
|
1690
|
+
import { useState as useState5 } from "react";
|
|
1177
1691
|
function useLocalStorage(key, initialValue) {
|
|
1178
|
-
const [storedValue, setStoredValue] =
|
|
1692
|
+
const [storedValue, setStoredValue] = useState5(() => {
|
|
1179
1693
|
try {
|
|
1180
1694
|
const item = window.localStorage.getItem(key);
|
|
1181
1695
|
return item ? JSON.parse(item) : initialValue;
|
|
@@ -1205,10 +1719,10 @@ function useLocalStorage(key, initialValue) {
|
|
|
1205
1719
|
}
|
|
1206
1720
|
|
|
1207
1721
|
// src/hooks/use-debounce.ts
|
|
1208
|
-
import { useState as
|
|
1722
|
+
import { useState as useState6, useEffect as useEffect6 } from "react";
|
|
1209
1723
|
function useDebounce(value, delay) {
|
|
1210
|
-
const [debouncedValue, setDebouncedValue] =
|
|
1211
|
-
|
|
1724
|
+
const [debouncedValue, setDebouncedValue] = useState6(value);
|
|
1725
|
+
useEffect6(() => {
|
|
1212
1726
|
const handler = setTimeout(() => {
|
|
1213
1727
|
setDebouncedValue(value);
|
|
1214
1728
|
}, delay);
|
|
@@ -1399,17 +1913,47 @@ function injectEarlyErrorHandler() {
|
|
|
1399
1913
|
})();
|
|
1400
1914
|
`;
|
|
1401
1915
|
try {
|
|
1916
|
+
const parent = document.head || document.documentElement;
|
|
1917
|
+
try {
|
|
1918
|
+
const external = document.createElement("script");
|
|
1919
|
+
external.type = "text/javascript";
|
|
1920
|
+
external.src = "/error-handler.js";
|
|
1921
|
+
external.async = false;
|
|
1922
|
+
parent.prepend(external);
|
|
1923
|
+
return;
|
|
1924
|
+
} catch (e) {
|
|
1925
|
+
void e;
|
|
1926
|
+
}
|
|
1402
1927
|
const script = document.createElement("script");
|
|
1403
1928
|
script.type = "text/javascript";
|
|
1404
|
-
|
|
1405
|
-
|
|
1929
|
+
try {
|
|
1930
|
+
if ("textContent" in script) {
|
|
1931
|
+
script.textContent = code;
|
|
1932
|
+
} else {
|
|
1933
|
+
script.appendChild(document.createTextNode(code));
|
|
1934
|
+
}
|
|
1935
|
+
} catch (e) {
|
|
1936
|
+
try {
|
|
1937
|
+
script.appendChild(document.createTextNode(code));
|
|
1938
|
+
} catch {
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1406
1941
|
parent.prepend(script);
|
|
1407
1942
|
} catch (e) {
|
|
1408
1943
|
void e;
|
|
1409
1944
|
}
|
|
1410
1945
|
}
|
|
1946
|
+
|
|
1947
|
+
// src/index.ts
|
|
1948
|
+
init_config();
|
|
1949
|
+
init_config();
|
|
1411
1950
|
export {
|
|
1951
|
+
AUTH_ROOT,
|
|
1952
|
+
AUTH_TOKEN_KEY,
|
|
1412
1953
|
AuthGuard,
|
|
1954
|
+
AuthProvider,
|
|
1955
|
+
AuthRedirector,
|
|
1956
|
+
AuthRedirector_default as AuthRedirectorDefault,
|
|
1413
1957
|
DefaultErrorFallback,
|
|
1414
1958
|
ErrorBoundary,
|
|
1415
1959
|
FloatingButton,
|
|
@@ -1423,13 +1967,25 @@ export {
|
|
|
1423
1967
|
createAIWorkflowClientAxios,
|
|
1424
1968
|
createArtifactsClient,
|
|
1425
1969
|
createClient,
|
|
1970
|
+
getAuthRoot,
|
|
1426
1971
|
getCodeStatus,
|
|
1972
|
+
getDefaultProjectId,
|
|
1973
|
+
getToken,
|
|
1974
|
+
client_default as howone,
|
|
1427
1975
|
injectEarlyErrorHandler,
|
|
1976
|
+
isTokenValid,
|
|
1428
1977
|
loginWithEmailCode,
|
|
1978
|
+
onAuthStateChanged,
|
|
1979
|
+
parseUserFromToken,
|
|
1429
1980
|
request,
|
|
1430
1981
|
sendEmailVerificationCode,
|
|
1982
|
+
setAuthRoot,
|
|
1983
|
+
setDefaultProjectId,
|
|
1984
|
+
setToken,
|
|
1431
1985
|
unifiedAuth,
|
|
1432
1986
|
unifiedOAuth,
|
|
1987
|
+
useAuth,
|
|
1988
|
+
useAuthContext,
|
|
1433
1989
|
useDebounce,
|
|
1434
1990
|
useIsMobile,
|
|
1435
1991
|
useLocalStorage,
|