@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.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
- if (token) {
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(token, user);
296
- window.history.replaceState({}, document.title, window.location.pathname);
297
- return { success: true, token, user };
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
- const token = localStorage.getItem("auth_token");
339
- if (!token) return null;
340
- let user = null;
341
- const userJson = localStorage.getItem("auth_user");
342
- if (userJson) {
343
- try {
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
- return { token, user };
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, user) {
608
+ saveAuthData(token) {
359
609
  try {
360
- localStorage.setItem("auth_token", token);
361
- localStorage.setItem("auth_user", JSON.stringify(user || {}));
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 (opts?.authRequired) {
772
- if (typeof window !== "undefined") {
773
- const loc = redirect || window.location.href;
774
- window.location.href = `/login?redirect=${encodeURIComponent(loc)}`;
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] = useState("");
797
- const [code, setCode] = useState("");
798
- const [validationErrors, setValidationErrors] = useState({});
799
- const [isAnyLoading, setIsAnyLoading] = useState(false);
800
- const [codeSent, setCodeSent] = useState(false);
801
- const [loginError, setLoginError] = useState(null);
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
- useEffect(() => {
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 = false;
1014
- const user = null;
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 jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
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__ */ jsx4("div", { className: `${containerClasses} ${className}`, children: /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1074
- /* @__PURE__ */ jsx4(
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__ */ jsx4("p", { className: "mt-2 text-sm text-gray-600", children: text })
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__ */ jsx4(
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 jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
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__ */ jsx5(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
1639
+ return /* @__PURE__ */ jsx7(FallbackComponent, { error: this.state.error, retry: this.handleRetry });
1126
1640
  }
1127
- return /* @__PURE__ */ jsx5("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs5("div", { className: "text-center max-w-md", children: [
1128
- /* @__PURE__ */ jsx5("div", { className: "text-red-500 text-6xl mb-4", children: "\u26A0\uFE0F" }),
1129
- /* @__PURE__ */ jsx5("h2", { className: "text-xl font-semibold text-gray-900 mb-2", children: "Something went wrong" }),
1130
- /* @__PURE__ */ jsx5("p", { className: "text-gray-600 mb-4", children: "An unexpected error occurred. Please try refreshing the page." }),
1131
- /* @__PURE__ */ jsx5(
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__ */ jsx5("div", { className: "min-h-[200px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
1146
- /* @__PURE__ */ jsx5("div", { className: "text-red-500 text-4xl mb-2", children: "\u26A0\uFE0F" }),
1147
- /* @__PURE__ */ jsx5("p", { className: "text-gray-600 mb-2", children: "Something went wrong" }),
1148
- retry && /* @__PURE__ */ jsx5(
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 React3 from "react";
1673
+ import * as React5 from "react";
1160
1674
  var MOBILE_BREAKPOINT = 768;
1161
1675
  function useIsMobile() {
1162
- const [isMobile, setIsMobile] = React3.useState(void 0);
1163
- React3.useEffect(() => {
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 useState3 } from "react";
1690
+ import { useState as useState5 } from "react";
1177
1691
  function useLocalStorage(key, initialValue) {
1178
- const [storedValue, setStoredValue] = useState3(() => {
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 useState4, useEffect as useEffect3 } from "react";
1722
+ import { useState as useState6, useEffect as useEffect6 } from "react";
1209
1723
  function useDebounce(value, delay) {
1210
- const [debouncedValue, setDebouncedValue] = useState4(value);
1211
- useEffect3(() => {
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
- script.text = code;
1405
- const parent = document.head || document.documentElement;
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,