@fluid-app/rep-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.cjs +123 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +122 -46
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/index.d.cts +0 -2164
- package/dist/index.d.ts +0 -2164
package/dist/index.js
CHANGED
|
@@ -23,6 +23,45 @@ var HTTP_METHODS = {
|
|
|
23
23
|
DELETE: "DELETE"
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
// src/auth/auth-redirect.ts
|
|
27
|
+
var DEFAULT_AUTH_URL = "https://auth.fluid.app";
|
|
28
|
+
var AUTH_REDIRECT_TOKEN_KEY = "jwt";
|
|
29
|
+
var REDIRECT_TIMESTAMP_KEY = "__fluid_auth_redirect_ts";
|
|
30
|
+
var REDIRECT_COOLDOWN_S = 10;
|
|
31
|
+
function isRedirectLoop() {
|
|
32
|
+
try {
|
|
33
|
+
const ts = sessionStorage.getItem(REDIRECT_TIMESTAMP_KEY);
|
|
34
|
+
if (!ts) return false;
|
|
35
|
+
const elapsed = (Date.now() - Number(ts)) / 1e3;
|
|
36
|
+
return elapsed < REDIRECT_COOLDOWN_S;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function markRedirect() {
|
|
42
|
+
try {
|
|
43
|
+
sessionStorage.setItem(REDIRECT_TIMESTAMP_KEY, String(Date.now()));
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function createDefaultAuthRedirect(authUrl) {
|
|
48
|
+
return () => {
|
|
49
|
+
if (isRedirectLoop()) {
|
|
50
|
+
console.warn(
|
|
51
|
+
"[FluidAuth] Auth redirect suppressed \u2014 possible redirect loop. Check that your auth server returns a token accepted by the API."
|
|
52
|
+
);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
markRedirect();
|
|
56
|
+
const base = authUrl ?? DEFAULT_AUTH_URL;
|
|
57
|
+
const currentUrl = encodeURIComponent(window.location.href);
|
|
58
|
+
window.location.href = `${base}/?redirect_url=${currentUrl}`;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function resolveAuthFailureHandler(onAuthFailure, authUrl) {
|
|
62
|
+
return onAuthFailure ?? createDefaultAuthRedirect(authUrl);
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
// src/client/fluid-client.ts
|
|
27
66
|
var ApiError = class _ApiError extends Error {
|
|
28
67
|
status;
|
|
@@ -66,6 +105,7 @@ function extractErrorMessage(data, fallback) {
|
|
|
66
105
|
}
|
|
67
106
|
function createFluidClient(config) {
|
|
68
107
|
const { baseUrl, getAuthToken, onAuthError, defaultHeaders = {} } = config;
|
|
108
|
+
const effectiveOnAuthError = onAuthError ?? createDefaultAuthRedirect();
|
|
69
109
|
async function buildHeaders(customHeaders) {
|
|
70
110
|
const headers = {
|
|
71
111
|
"Content-Type": "application/json",
|
|
@@ -151,8 +191,9 @@ function createFluidClient(config) {
|
|
|
151
191
|
null
|
|
152
192
|
);
|
|
153
193
|
}
|
|
154
|
-
if (response.status === 401
|
|
155
|
-
|
|
194
|
+
if (response.status === 401) {
|
|
195
|
+
effectiveOnAuthError();
|
|
196
|
+
return null;
|
|
156
197
|
}
|
|
157
198
|
if (!response.ok) {
|
|
158
199
|
try {
|
|
@@ -313,6 +354,16 @@ function createFluidClient(config) {
|
|
|
313
354
|
var ThemeContext = createContext(null);
|
|
314
355
|
function applyThemeVariables(theme, container) {
|
|
315
356
|
const target = container ?? document.documentElement;
|
|
357
|
+
const toRemove = [];
|
|
358
|
+
for (let i = 0; i < target.style.length; i++) {
|
|
359
|
+
const prop = target.style[i];
|
|
360
|
+
if (prop.startsWith("--fluid-")) {
|
|
361
|
+
toRemove.push(prop);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
for (const prop of toRemove) {
|
|
365
|
+
target.style.removeProperty(prop);
|
|
366
|
+
}
|
|
316
367
|
for (const [key, value] of Object.entries(theme.config)) {
|
|
317
368
|
target.style.setProperty(`--fluid-${key}`, value);
|
|
318
369
|
}
|
|
@@ -379,7 +430,11 @@ function FluidProvider({
|
|
|
379
430
|
const configRef = useRef(config);
|
|
380
431
|
configRef.current = config;
|
|
381
432
|
const client = useMemo(
|
|
382
|
-
() => createFluidClient(
|
|
433
|
+
() => createFluidClient({
|
|
434
|
+
...configRef.current,
|
|
435
|
+
getAuthToken: () => configRef.current.getAuthToken?.() ?? null,
|
|
436
|
+
onAuthError: () => configRef.current.onAuthError?.()
|
|
437
|
+
}),
|
|
383
438
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
384
439
|
[config.baseUrl]
|
|
385
440
|
);
|
|
@@ -432,10 +487,12 @@ var URL_PARAMS = {
|
|
|
432
487
|
COMPANY_TOKEN: "fluidCompanyToken"
|
|
433
488
|
};
|
|
434
489
|
|
|
435
|
-
// src/auth/
|
|
490
|
+
// src/auth/browser-utils.ts
|
|
436
491
|
function isBrowser() {
|
|
437
|
-
return typeof window !== "undefined";
|
|
492
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
438
493
|
}
|
|
494
|
+
|
|
495
|
+
// src/auth/url-token.ts
|
|
439
496
|
function extractTokenFromUrl(tokenKey = URL_PARAMS.USER_TOKEN) {
|
|
440
497
|
if (!isBrowser()) {
|
|
441
498
|
return null;
|
|
@@ -506,11 +563,8 @@ function extractAllTokensFromUrl(userTokenKey = URL_PARAMS.USER_TOKEN, companyTo
|
|
|
506
563
|
}
|
|
507
564
|
|
|
508
565
|
// src/auth/token-storage.ts
|
|
509
|
-
function isBrowser2() {
|
|
510
|
-
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
511
|
-
}
|
|
512
566
|
function parseCookies() {
|
|
513
|
-
if (!
|
|
567
|
+
if (!isBrowser()) {
|
|
514
568
|
return {};
|
|
515
569
|
}
|
|
516
570
|
const cookies = {};
|
|
@@ -527,7 +581,7 @@ function parseCookies() {
|
|
|
527
581
|
return cookies;
|
|
528
582
|
}
|
|
529
583
|
function setCookie(name, value, options = {}) {
|
|
530
|
-
if (!
|
|
584
|
+
if (!isBrowser()) {
|
|
531
585
|
return;
|
|
532
586
|
}
|
|
533
587
|
const {
|
|
@@ -546,13 +600,13 @@ function setCookie(name, value, options = {}) {
|
|
|
546
600
|
document.cookie = cookieString;
|
|
547
601
|
}
|
|
548
602
|
function deleteCookie(name, path = "/") {
|
|
549
|
-
if (!
|
|
603
|
+
if (!isBrowser()) {
|
|
550
604
|
return;
|
|
551
605
|
}
|
|
552
606
|
document.cookie = `${name}=; path=${path}; max-age=0`;
|
|
553
607
|
}
|
|
554
608
|
function getStoredToken(config) {
|
|
555
|
-
if (!
|
|
609
|
+
if (!isBrowser()) {
|
|
556
610
|
return null;
|
|
557
611
|
}
|
|
558
612
|
const cookieKey = config?.cookieKey ?? STORAGE_KEYS.AUTH_COOKIE;
|
|
@@ -569,7 +623,7 @@ function getStoredToken(config) {
|
|
|
569
623
|
}
|
|
570
624
|
}
|
|
571
625
|
function storeToken(token, config) {
|
|
572
|
-
if (!
|
|
626
|
+
if (!isBrowser()) {
|
|
573
627
|
return;
|
|
574
628
|
}
|
|
575
629
|
const cookieKey = config?.cookieKey ?? STORAGE_KEYS.AUTH_COOKIE;
|
|
@@ -592,7 +646,7 @@ function storeToken(token, config) {
|
|
|
592
646
|
}
|
|
593
647
|
}
|
|
594
648
|
function clearTokens(config) {
|
|
595
|
-
if (!
|
|
649
|
+
if (!isBrowser()) {
|
|
596
650
|
return;
|
|
597
651
|
}
|
|
598
652
|
const cookieKey = config?.cookieKey ?? STORAGE_KEYS.AUTH_COOKIE;
|
|
@@ -609,16 +663,31 @@ function clearTokens(config) {
|
|
|
609
663
|
function hasStoredToken(config) {
|
|
610
664
|
return getStoredToken(config) !== null;
|
|
611
665
|
}
|
|
666
|
+
|
|
667
|
+
// src/auth/types.ts
|
|
668
|
+
var USER_TYPES = {
|
|
669
|
+
admin: "admin",
|
|
670
|
+
rep: "rep",
|
|
671
|
+
root_admin: "root_admin",
|
|
672
|
+
customer: "customer"
|
|
673
|
+
};
|
|
674
|
+
function isUserType(value) {
|
|
675
|
+
return Object.values(USER_TYPES).includes(value);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// src/auth/token-utils.ts
|
|
612
679
|
function extractPayloadFromJose(decoded) {
|
|
680
|
+
const rawUserType = decoded.user_type;
|
|
681
|
+
const rawOgUserType = decoded.og_user_type;
|
|
613
682
|
return {
|
|
614
|
-
id: decoded.id,
|
|
615
|
-
email: decoded.email,
|
|
616
|
-
full_name: decoded.full_name,
|
|
617
|
-
user_type:
|
|
618
|
-
og_user_type:
|
|
619
|
-
company_id: decoded.company_id,
|
|
683
|
+
id: typeof decoded.id === "number" ? decoded.id : void 0,
|
|
684
|
+
email: typeof decoded.email === "string" ? decoded.email : void 0,
|
|
685
|
+
full_name: typeof decoded.full_name === "string" ? decoded.full_name : void 0,
|
|
686
|
+
user_type: typeof rawUserType === "string" && isUserType(rawUserType) ? rawUserType : "rep",
|
|
687
|
+
og_user_type: typeof rawOgUserType === "string" && isUserType(rawOgUserType) ? rawOgUserType : void 0,
|
|
688
|
+
company_id: typeof decoded.company_id === "number" ? decoded.company_id : void 0,
|
|
620
689
|
exp: decoded.exp,
|
|
621
|
-
auth_type: decoded.auth_type
|
|
690
|
+
auth_type: typeof decoded.auth_type === "string" ? decoded.auth_type : void 0
|
|
622
691
|
};
|
|
623
692
|
}
|
|
624
693
|
function decodeToken(token) {
|
|
@@ -708,17 +777,6 @@ async function verifyToken(token, jwksUrl) {
|
|
|
708
777
|
}
|
|
709
778
|
}
|
|
710
779
|
|
|
711
|
-
// src/auth/types.ts
|
|
712
|
-
var USER_TYPES = {
|
|
713
|
-
admin: "admin",
|
|
714
|
-
rep: "rep",
|
|
715
|
-
root_admin: "root_admin",
|
|
716
|
-
customer: "customer"
|
|
717
|
-
};
|
|
718
|
-
function isUserType(value) {
|
|
719
|
-
return Object.values(USER_TYPES).includes(value);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
780
|
// src/auth/dev-utils.ts
|
|
723
781
|
function isDevBypassActive(devBypass) {
|
|
724
782
|
if (!devBypass) return false;
|
|
@@ -730,12 +788,14 @@ function isDevBypassActive(devBypass) {
|
|
|
730
788
|
}
|
|
731
789
|
function createDevUser() {
|
|
732
790
|
return {
|
|
733
|
-
id:
|
|
791
|
+
id: 99999,
|
|
792
|
+
// Dev placeholder — avoids falsy 0
|
|
734
793
|
email: "dev@localhost",
|
|
735
794
|
full_name: "Dev User",
|
|
736
795
|
user_type: USER_TYPES.rep,
|
|
737
796
|
og_user_type: void 0,
|
|
738
|
-
company_id:
|
|
797
|
+
company_id: 99999,
|
|
798
|
+
// Dev placeholder — avoids falsy 0
|
|
739
799
|
exp: void 0,
|
|
740
800
|
// Never expires
|
|
741
801
|
auth_type: "dev_bypass"
|
|
@@ -754,6 +814,11 @@ function FluidAuthProvider({
|
|
|
754
814
|
const [error, setError] = useState(null);
|
|
755
815
|
useEffect(() => {
|
|
756
816
|
const initializeAuth = async () => {
|
|
817
|
+
const handleAuthFailure = () => {
|
|
818
|
+
const current = configRef.current;
|
|
819
|
+
const handler = resolveAuthFailureHandler(current?.onAuthFailure, current?.authUrl);
|
|
820
|
+
handler();
|
|
821
|
+
};
|
|
757
822
|
try {
|
|
758
823
|
if (isDevBypassActive(config?.devBypass)) {
|
|
759
824
|
const envToken = import.meta.env.VITE_DEV_TOKEN;
|
|
@@ -781,7 +846,11 @@ function FluidAuthProvider({
|
|
|
781
846
|
}
|
|
782
847
|
const tokenKey = config?.tokenKey ?? "fluidUserToken";
|
|
783
848
|
let candidateToken = extractTokenFromUrl(tokenKey);
|
|
849
|
+
if (!candidateToken && tokenKey !== AUTH_REDIRECT_TOKEN_KEY) {
|
|
850
|
+
candidateToken = extractTokenFromUrl(AUTH_REDIRECT_TOKEN_KEY);
|
|
851
|
+
}
|
|
784
852
|
cleanTokenFromUrl(tokenKey);
|
|
853
|
+
cleanTokenFromUrl(AUTH_REDIRECT_TOKEN_KEY);
|
|
785
854
|
if (!candidateToken) {
|
|
786
855
|
candidateToken = getStoredToken(config);
|
|
787
856
|
}
|
|
@@ -794,7 +863,7 @@ function FluidAuthProvider({
|
|
|
794
863
|
setToken(null);
|
|
795
864
|
setUser(null);
|
|
796
865
|
setError(new Error("JWT signature verification failed"));
|
|
797
|
-
|
|
866
|
+
handleAuthFailure();
|
|
798
867
|
return;
|
|
799
868
|
}
|
|
800
869
|
if (isTokenExpired(candidateToken, config?.gracePeriodMs)) {
|
|
@@ -802,7 +871,7 @@ function FluidAuthProvider({
|
|
|
802
871
|
setToken(null);
|
|
803
872
|
setUser(null);
|
|
804
873
|
setError(new Error("Token has expired"));
|
|
805
|
-
|
|
874
|
+
handleAuthFailure();
|
|
806
875
|
return;
|
|
807
876
|
}
|
|
808
877
|
} else {
|
|
@@ -817,7 +886,7 @@ function FluidAuthProvider({
|
|
|
817
886
|
setToken(null);
|
|
818
887
|
setUser(null);
|
|
819
888
|
setError(new Error(validation.error ?? "Invalid token"));
|
|
820
|
-
|
|
889
|
+
handleAuthFailure();
|
|
821
890
|
return;
|
|
822
891
|
}
|
|
823
892
|
}
|
|
@@ -829,14 +898,14 @@ function FluidAuthProvider({
|
|
|
829
898
|
setToken(null);
|
|
830
899
|
setUser(null);
|
|
831
900
|
setError(new Error("No authentication token found"));
|
|
832
|
-
|
|
901
|
+
handleAuthFailure();
|
|
833
902
|
}
|
|
834
903
|
} catch (err) {
|
|
835
904
|
const error2 = err instanceof Error ? err : new Error("Authentication error");
|
|
836
905
|
setError(error2);
|
|
837
906
|
setToken(null);
|
|
838
907
|
setUser(null);
|
|
839
|
-
|
|
908
|
+
handleAuthFailure();
|
|
840
909
|
} finally {
|
|
841
910
|
setIsLoading(false);
|
|
842
911
|
}
|
|
@@ -1872,7 +1941,19 @@ function AuthError({
|
|
|
1872
1941
|
}
|
|
1873
1942
|
);
|
|
1874
1943
|
}
|
|
1944
|
+
var SPIN_STYLE_ID = "fluid-auth-loading-spin";
|
|
1945
|
+
function ensureSpinStyle() {
|
|
1946
|
+
if (typeof document === "undefined") return;
|
|
1947
|
+
if (document.getElementById(SPIN_STYLE_ID)) return;
|
|
1948
|
+
const style = document.createElement("style");
|
|
1949
|
+
style.id = SPIN_STYLE_ID;
|
|
1950
|
+
style.textContent = `@keyframes spin { to { transform: rotate(360deg); } }`;
|
|
1951
|
+
document.head.appendChild(style);
|
|
1952
|
+
}
|
|
1875
1953
|
function AuthLoading() {
|
|
1954
|
+
useEffect(() => {
|
|
1955
|
+
ensureSpinStyle();
|
|
1956
|
+
}, []);
|
|
1876
1957
|
return /* @__PURE__ */ jsxs(
|
|
1877
1958
|
"div",
|
|
1878
1959
|
{
|
|
@@ -1909,12 +1990,7 @@ function AuthLoading() {
|
|
|
1909
1990
|
},
|
|
1910
1991
|
children: "Authenticating..."
|
|
1911
1992
|
}
|
|
1912
|
-
)
|
|
1913
|
-
/* @__PURE__ */ jsx("style", { children: `
|
|
1914
|
-
@keyframes spin {
|
|
1915
|
-
to { transform: rotate(360deg); }
|
|
1916
|
-
}
|
|
1917
|
-
` })
|
|
1993
|
+
)
|
|
1918
1994
|
]
|
|
1919
1995
|
}
|
|
1920
1996
|
);
|
|
@@ -2074,6 +2150,6 @@ var export_toDarkMode = themes_exports.toDarkMode;
|
|
|
2074
2150
|
var export_toLightMode = themes_exports.toLightMode;
|
|
2075
2151
|
var export_tokyoNight = themes_exports.tokyoNight;
|
|
2076
2152
|
|
|
2077
|
-
export { ACTIVITY_SLUGS, AUTH_CONSTANTS, ApiError, AuthError, AuthLoading, export_BUILT_IN_THEMES as BUILT_IN_THEMES, export_CORE_COLOR_KEYS as CORE_COLOR_KEYS, CORE_PAGE_IDS, CURRENT_REP_QUERY_KEY, export_DEFAULT_CORE_COLORS as DEFAULT_CORE_COLORS, FluidAuthProvider, FluidProvider, FluidThemeProvider, PAGE_CATEGORIES, PERMISSIONS_QUERY_KEY, PROFILE_QUERY_KEY, PageTemplateProvider, PageTemplateRegistry, RequireAuth, STORAGE_KEYS, URL_PARAMS, USER_TYPES, export_catppuccinMocha as catppuccinMocha, export_clampChroma as clampChroma, cleanTokenFromUrl, clearTokens, createFluidClient, decodeToken, export_defaultTheme as defaultTheme, export_detectThemeMode as detectThemeMode, export_dracula as dracula, export_everforest as everforest, extractAllTokensFromUrl, extractCompanyTokenFromUrl, extractTokenFromUrl, export_generateColorSwatches as generateColorSwatches, export_generateDualTheme as generateDualTheme, export_generateSmartDualTheme as generateSmartDualTheme, export_generateTheme as generateTheme, export_generateThemeCssVars as generateThemeCssVars, getAvailablePageTemplates, getCorePageTemplates, getOptionalPageTemplates, getProperty, getStoredToken, getTokenExpiration, getTokenTimeRemaining, export_gruvbox as gruvbox, hasData, hasStoredToken, hasTokenInUrl, isActivitySlug, isApiError, isContactStatus, isErrorResult, isIdle, isLoading, isTokenExpired, isUserType, isValidToken, export_mod as mod, export_monokai as monokai, export_nord as nord, export_oklchString as oklchString, export_parseOklch as parseOklch, resolveNavigationPages, export_rosePine as rosePine, export_rotateHue as rotateHue, export_rotateSoft as rotateSoft, screenPropertySchemas, selectProperty, export_solarized as solarized, storeToken, export_toDarkMode as toDarkMode, export_toLightMode as toLightMode, export_tokyoNight as tokyoNight, useActivities, useCalendarEvents, useCatchUps, useContact, useContacts, useConversationMessages, useConversations, useCurrentRep, useFluidApi, useFluidAuth, useFluidAuthContext, useFluidContext, useFluidPermissions, useFluidProfile, useFluidTheme, useMySite, usePageTemplates, useResolvedPages, useThemeContext, useTodos, validateNavigationPages, validateToken };
|
|
2153
|
+
export { ACTIVITY_SLUGS, AUTH_CONSTANTS, ApiError, AuthError, AuthLoading, export_BUILT_IN_THEMES as BUILT_IN_THEMES, export_CORE_COLOR_KEYS as CORE_COLOR_KEYS, CORE_PAGE_IDS, CURRENT_REP_QUERY_KEY, DEFAULT_AUTH_URL, export_DEFAULT_CORE_COLORS as DEFAULT_CORE_COLORS, FluidAuthProvider, FluidProvider, FluidThemeProvider, PAGE_CATEGORIES, PERMISSIONS_QUERY_KEY, PROFILE_QUERY_KEY, PageTemplateProvider, PageTemplateRegistry, RequireAuth, STORAGE_KEYS, URL_PARAMS, USER_TYPES, export_catppuccinMocha as catppuccinMocha, export_clampChroma as clampChroma, cleanTokenFromUrl, clearTokens, createDefaultAuthRedirect, createFluidClient, decodeToken, export_defaultTheme as defaultTheme, export_detectThemeMode as detectThemeMode, export_dracula as dracula, export_everforest as everforest, extractAllTokensFromUrl, extractCompanyTokenFromUrl, extractTokenFromUrl, export_generateColorSwatches as generateColorSwatches, export_generateDualTheme as generateDualTheme, export_generateSmartDualTheme as generateSmartDualTheme, export_generateTheme as generateTheme, export_generateThemeCssVars as generateThemeCssVars, getAvailablePageTemplates, getCorePageTemplates, getOptionalPageTemplates, getProperty, getStoredToken, getTokenExpiration, getTokenTimeRemaining, export_gruvbox as gruvbox, hasData, hasStoredToken, hasTokenInUrl, isActivitySlug, isApiError, isContactStatus, isErrorResult, isIdle, isLoading, isTokenExpired, isUserType, isValidToken, export_mod as mod, export_monokai as monokai, export_nord as nord, export_oklchString as oklchString, export_parseOklch as parseOklch, resolveNavigationPages, export_rosePine as rosePine, export_rotateHue as rotateHue, export_rotateSoft as rotateSoft, screenPropertySchemas, selectProperty, export_solarized as solarized, storeToken, export_toDarkMode as toDarkMode, export_toLightMode as toLightMode, export_tokyoNight as tokyoNight, useActivities, useCalendarEvents, useCatchUps, useContact, useContacts, useConversationMessages, useConversations, useCurrentRep, useFluidApi, useFluidAuth, useFluidAuthContext, useFluidContext, useFluidPermissions, useFluidProfile, useFluidTheme, useMySite, usePageTemplates, useResolvedPages, useThemeContext, useTodos, validateNavigationPages, validateToken };
|
|
2078
2154
|
//# sourceMappingURL=index.js.map
|
|
2079
2155
|
//# sourceMappingURL=index.js.map
|