@every-app/sdk 0.1.13 → 0.2.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/internal/identity.d.ts +73 -0
- package/dist/internal/identity.d.ts.map +1 -0
- package/dist/internal/identity.js +192 -0
- package/dist/internal/index.d.ts +3 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +2 -0
- package/dist/internal/protocol.d.ts +111 -0
- package/dist/internal/protocol.d.ts.map +1 -0
- package/dist/internal/protocol.js +139 -0
- package/dist/server/everyApp.d.ts +55 -0
- package/dist/server/everyApp.d.ts.map +1 -0
- package/dist/server/everyApp.js +121 -0
- package/dist/server/gatewayFetch.d.ts +21 -0
- package/dist/server/gatewayFetch.d.ts.map +1 -0
- package/dist/server/gatewayFetch.js +70 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +8 -0
- package/dist/server/mcp.d.ts +66 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +147 -0
- package/package.json +21 -44
- package/dist/cloudflare/getLocalD1Url.d.ts +0 -2
- package/dist/cloudflare/getLocalD1Url.d.ts.map +0 -1
- package/dist/cloudflare/getLocalD1Url.js +0 -40
- package/dist/cloudflare/index.d.ts +0 -2
- package/dist/cloudflare/index.d.ts.map +0 -1
- package/dist/cloudflare/index.js +0 -1
- package/dist/cloudflare/lazyInit.d.ts +0 -22
- package/dist/cloudflare/lazyInit.d.ts.map +0 -1
- package/dist/cloudflare/lazyInit.js +0 -65
- package/dist/cloudflare/server/gateway.d.ts +0 -29
- package/dist/cloudflare/server/gateway.d.ts.map +0 -1
- package/dist/cloudflare/server/gateway.js +0 -69
- package/dist/cloudflare/server/index.d.ts +0 -3
- package/dist/cloudflare/server/index.d.ts.map +0 -1
- package/dist/cloudflare/server/index.js +0 -2
- package/dist/core/authenticatedFetch.d.ts +0 -9
- package/dist/core/authenticatedFetch.d.ts.map +0 -1
- package/dist/core/authenticatedFetch.js +0 -31
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -2
- package/dist/core/sessionManager.d.ts +0 -58
- package/dist/core/sessionManager.d.ts.map +0 -1
- package/dist/core/sessionManager.js +0 -357
- package/dist/shared/bypassGatewayLocalOnly.d.ts +0 -14
- package/dist/shared/bypassGatewayLocalOnly.d.ts.map +0 -1
- package/dist/shared/bypassGatewayLocalOnly.js +0 -41
- package/dist/shared/parseMessagePayload.d.ts +0 -3
- package/dist/shared/parseMessagePayload.d.ts.map +0 -1
- package/dist/shared/parseMessagePayload.js +0 -18
- package/dist/tanstack/EmbeddedAppProvider.d.ts +0 -30
- package/dist/tanstack/EmbeddedAppProvider.d.ts.map +0 -1
- package/dist/tanstack/EmbeddedAppProvider.js +0 -57
- package/dist/tanstack/GatewayRequiredError.d.ts +0 -20
- package/dist/tanstack/GatewayRequiredError.d.ts.map +0 -1
- package/dist/tanstack/GatewayRequiredError.js +0 -91
- package/dist/tanstack/_internal/useEveryAppSession.d.ts +0 -18
- package/dist/tanstack/_internal/useEveryAppSession.d.ts.map +0 -1
- package/dist/tanstack/_internal/useEveryAppSession.js +0 -47
- package/dist/tanstack/index.d.ts +0 -4
- package/dist/tanstack/index.d.ts.map +0 -1
- package/dist/tanstack/index.js +0 -3
- package/dist/tanstack/server/authConfig.d.ts +0 -3
- package/dist/tanstack/server/authConfig.d.ts.map +0 -1
- package/dist/tanstack/server/authConfig.js +0 -13
- package/dist/tanstack/server/authenticateRequest.d.ts +0 -29
- package/dist/tanstack/server/authenticateRequest.d.ts.map +0 -1
- package/dist/tanstack/server/authenticateRequest.js +0 -82
- package/dist/tanstack/server/index.d.ts +0 -4
- package/dist/tanstack/server/index.d.ts.map +0 -1
- package/dist/tanstack/server/index.js +0 -2
- package/dist/tanstack/server/types.d.ts +0 -5
- package/dist/tanstack/server/types.d.ts.map +0 -1
- package/dist/tanstack/server/types.js +0 -1
- package/dist/tanstack/useEveryAppRouter.d.ts +0 -7
- package/dist/tanstack/useEveryAppRouter.d.ts.map +0 -1
- package/dist/tanstack/useEveryAppRouter.js +0 -66
- package/dist/tanstack/useSessionTokenClientMiddleware.d.ts +0 -2
- package/dist/tanstack/useSessionTokenClientMiddleware.d.ts.map +0 -1
- package/dist/tanstack/useSessionTokenClientMiddleware.js +0 -29
- package/src/cloudflare/getLocalD1Url.ts +0 -64
- package/src/cloudflare/index.ts +0 -1
- package/src/cloudflare/lazyInit.ts +0 -67
- package/src/cloudflare/server/gateway.test.ts +0 -262
- package/src/cloudflare/server/gateway.ts +0 -114
- package/src/cloudflare/server/index.ts +0 -2
- package/src/core/authenticatedFetch.ts +0 -54
- package/src/core/index.ts +0 -12
- package/src/core/sessionManager.test.ts +0 -939
- package/src/core/sessionManager.ts +0 -492
- package/src/env.d.ts +0 -13
- package/src/shared/bypassGatewayLocalOnly.ts +0 -55
- package/src/shared/parseMessagePayload.ts +0 -22
- package/src/tanstack/EmbeddedAppProvider.tsx +0 -96
- package/src/tanstack/GatewayRequiredError.tsx +0 -150
- package/src/tanstack/_internal/useEveryAppSession.test.ts +0 -40
- package/src/tanstack/_internal/useEveryAppSession.tsx +0 -74
- package/src/tanstack/index.ts +0 -3
- package/src/tanstack/server/authConfig.ts +0 -19
- package/src/tanstack/server/authenticateRequest.test.ts +0 -482
- package/src/tanstack/server/authenticateRequest.ts +0 -143
- package/src/tanstack/server/index.ts +0 -3
- package/src/tanstack/server/types.ts +0 -4
- package/src/tanstack/useEveryAppRouter.tsx +0 -83
- package/src/tanstack/useSessionTokenClientMiddleware.ts +0 -43
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export const BYPASS_GATEWAY_LOCAL_ONLY_TOKEN = "BYPASS_GATEWAY_LOCAL_ONLY";
|
|
2
|
-
export const BYPASS_GATEWAY_LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
-
export const BYPASS_GATEWAY_LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
-
export function isBypassGatewayLocalOnlyClient() {
|
|
5
|
-
if (import.meta.env.PROD) {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
const metaEnv = import.meta
|
|
9
|
-
.env;
|
|
10
|
-
return (metaEnv?.VITE_BYPASS_GATEWAY_LOCAL_ONLY === "true" ||
|
|
11
|
-
metaEnv?.BYPASS_GATEWAY_LOCAL_ONLY === "true");
|
|
12
|
-
}
|
|
13
|
-
export function isBypassGatewayLocalOnlyServer() {
|
|
14
|
-
if (import.meta.env.PROD) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
const metaEnv = import.meta
|
|
18
|
-
.env;
|
|
19
|
-
const metaValue = metaEnv?.BYPASS_GATEWAY_LOCAL_ONLY ??
|
|
20
|
-
metaEnv?.VITE_BYPASS_GATEWAY_LOCAL_ONLY;
|
|
21
|
-
if (metaValue === "true") {
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
if (typeof process !== "undefined" &&
|
|
25
|
-
process.env?.BYPASS_GATEWAY_LOCAL_ONLY === "true") {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
export function createBypassGatewayLocalOnlySessionPayload(audience) {
|
|
31
|
-
const issuedAt = Math.floor(Date.now() / 1000);
|
|
32
|
-
const expiresAt = issuedAt + 60 * 60;
|
|
33
|
-
return {
|
|
34
|
-
sub: BYPASS_GATEWAY_LOCAL_ONLY_USER_ID,
|
|
35
|
-
email: BYPASS_GATEWAY_LOCAL_ONLY_EMAIL,
|
|
36
|
-
iss: "local",
|
|
37
|
-
aud: audience,
|
|
38
|
-
iat: issuedAt,
|
|
39
|
-
exp: expiresAt,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parseMessagePayload.d.ts","sourceRoot":"","sources":["../../src/shared/parseMessagePayload.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAmBxE"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export function parseMessagePayload(data) {
|
|
2
|
-
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
3
|
-
return data;
|
|
4
|
-
}
|
|
5
|
-
if (typeof data !== "string") {
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
8
|
-
try {
|
|
9
|
-
const parsed = JSON.parse(data);
|
|
10
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
11
|
-
return parsed;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { SessionManagerConfig } from "../core/sessionManager.js";
|
|
3
|
-
interface EmbeddedProviderConfig extends SessionManagerConfig {
|
|
4
|
-
children: React.ReactNode;
|
|
5
|
-
}
|
|
6
|
-
export declare function EmbeddedAppProvider({ children, ...config }: EmbeddedProviderConfig): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
-
/**
|
|
8
|
-
* Hook to get the current authenticated user.
|
|
9
|
-
* Returns the user's ID and email extracted from the JWT token,
|
|
10
|
-
* or null if not authenticated.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```tsx
|
|
14
|
-
* function MyComponent() {
|
|
15
|
-
* const user = useCurrentUser();
|
|
16
|
-
*
|
|
17
|
-
* if (!user) {
|
|
18
|
-
* return <div>Not authenticated</div>;
|
|
19
|
-
* }
|
|
20
|
-
*
|
|
21
|
-
* return <div>Welcome, {user.email}</div>;
|
|
22
|
-
* }
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare function useCurrentUser(): {
|
|
26
|
-
userId: string;
|
|
27
|
-
email: string;
|
|
28
|
-
} | null;
|
|
29
|
-
export {};
|
|
30
|
-
//# sourceMappingURL=EmbeddedAppProvider.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedAppProvider.d.ts","sourceRoot":"","sources":["../../src/tanstack/EmbeddedAppProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,EAEL,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAKnC,UAAU,sBAAuB,SAAQ,oBAAoB;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAUD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,sBAAsB,kDAgCxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAmBzE"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useMemo } from "react";
|
|
3
|
-
import { useEveryAppSession } from "./_internal/useEveryAppSession.js";
|
|
4
|
-
import { useEveryAppRouter } from "./useEveryAppRouter.js";
|
|
5
|
-
import { GatewayRequiredError } from "./GatewayRequiredError.js";
|
|
6
|
-
const EmbeddedAppContext = createContext(null);
|
|
7
|
-
export function EmbeddedAppProvider({ children, ...config }) {
|
|
8
|
-
const { sessionManager, sessionTokenState } = useEveryAppSession({
|
|
9
|
-
sessionManagerConfig: config,
|
|
10
|
-
});
|
|
11
|
-
useEveryAppRouter({ sessionManager });
|
|
12
|
-
if (!sessionManager)
|
|
13
|
-
return null;
|
|
14
|
-
// Check if the app is running outside of the Gateway (iframe or React Native WebView)
|
|
15
|
-
if (!sessionManager.isEmbedded() &&
|
|
16
|
-
!sessionManager.isBypassGatewayLocalOnly) {
|
|
17
|
-
return (_jsx(GatewayRequiredError, { gatewayOrigin: sessionManager.parentOrigin, appId: config.appId }));
|
|
18
|
-
}
|
|
19
|
-
const value = {
|
|
20
|
-
sessionManager,
|
|
21
|
-
isAuthenticated: sessionTokenState.status === "VALID",
|
|
22
|
-
sessionTokenState,
|
|
23
|
-
};
|
|
24
|
-
return (_jsx(EmbeddedAppContext.Provider, { value: value, children: children }));
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Hook to get the current authenticated user.
|
|
28
|
-
* Returns the user's ID and email extracted from the JWT token,
|
|
29
|
-
* or null if not authenticated.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```tsx
|
|
33
|
-
* function MyComponent() {
|
|
34
|
-
* const user = useCurrentUser();
|
|
35
|
-
*
|
|
36
|
-
* if (!user) {
|
|
37
|
-
* return <div>Not authenticated</div>;
|
|
38
|
-
* }
|
|
39
|
-
*
|
|
40
|
-
* return <div>Welcome, {user.email}</div>;
|
|
41
|
-
* }
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export function useCurrentUser() {
|
|
45
|
-
const context = useContext(EmbeddedAppContext);
|
|
46
|
-
if (!context) {
|
|
47
|
-
throw new Error("useCurrentUser must be used within an EmbeddedAppProvider");
|
|
48
|
-
}
|
|
49
|
-
const { sessionManager, sessionTokenState } = context;
|
|
50
|
-
return useMemo(() => {
|
|
51
|
-
// Only return user if we have a valid token
|
|
52
|
-
if (sessionTokenState.status !== "VALID") {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
return sessionManager.getUser();
|
|
56
|
-
}, [sessionManager, sessionTokenState]);
|
|
57
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
interface GatewayRequiredErrorProps {
|
|
2
|
-
/**
|
|
3
|
-
* The origin of the Gateway (e.g., "https://gateway.example.com").
|
|
4
|
-
*/
|
|
5
|
-
gatewayOrigin: string;
|
|
6
|
-
/**
|
|
7
|
-
* The app ID used in the Gateway URL path.
|
|
8
|
-
*/
|
|
9
|
-
appId: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Error component displayed when an embedded app is accessed directly
|
|
13
|
-
* instead of through the Every App Gateway.
|
|
14
|
-
*
|
|
15
|
-
* This component informs users that authentication requires accessing
|
|
16
|
-
* the app through the Gateway and provides a link to do so.
|
|
17
|
-
*/
|
|
18
|
-
export declare function GatewayRequiredError({ gatewayOrigin, appId, }: GatewayRequiredErrorProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=GatewayRequiredError.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GatewayRequiredError.d.ts","sourceRoot":"","sources":["../../src/tanstack/GatewayRequiredError.tsx"],"names":[],"mappings":"AAEA,UAAU,yBAAyB;IACjC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAmFD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,aAAa,EACb,KAAK,GACN,EAAE,yBAAyB,2CA6C3B"}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// CSS custom properties for theming
|
|
3
|
-
const CSS_VARIABLES = `
|
|
4
|
-
@media (prefers-color-scheme: light) {
|
|
5
|
-
:root {
|
|
6
|
-
--gateway-bg: oklch(100% 0 0);
|
|
7
|
-
--gateway-text: oklch(0% 0 0);
|
|
8
|
-
--gateway-text-muted: oklch(40% 0 0);
|
|
9
|
-
--gateway-icon-bg: oklch(94% 0 0);
|
|
10
|
-
--gateway-icon-stroke: oklch(80% 0.18 90);
|
|
11
|
-
--gateway-border: oklch(94% 0 0);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
@media (prefers-color-scheme: dark) {
|
|
15
|
-
:root {
|
|
16
|
-
--gateway-bg: #0a0f0d;
|
|
17
|
-
--gateway-text: oklch(92% 0 0);
|
|
18
|
-
--gateway-text-muted: oklch(60% 0 0);
|
|
19
|
-
--gateway-icon-bg: oklch(22% 0 0);
|
|
20
|
-
--gateway-icon-stroke: oklch(85% 0.18 90);
|
|
21
|
-
--gateway-border: oklch(30% 0 0);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
const styles = {
|
|
26
|
-
container: {
|
|
27
|
-
display: "flex",
|
|
28
|
-
flexDirection: "column",
|
|
29
|
-
alignItems: "center",
|
|
30
|
-
justifyContent: "center",
|
|
31
|
-
minHeight: "100vh",
|
|
32
|
-
padding: "24px",
|
|
33
|
-
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',
|
|
34
|
-
backgroundColor: "var(--gateway-bg, oklch(100% 0 0))",
|
|
35
|
-
color: "var(--gateway-text, oklch(0% 0 0))",
|
|
36
|
-
colorScheme: "light dark",
|
|
37
|
-
},
|
|
38
|
-
content: {
|
|
39
|
-
maxWidth: "520px",
|
|
40
|
-
width: "100%",
|
|
41
|
-
textAlign: "left",
|
|
42
|
-
},
|
|
43
|
-
iconContainer: {
|
|
44
|
-
width: "44px",
|
|
45
|
-
height: "44px",
|
|
46
|
-
marginBottom: "16px",
|
|
47
|
-
borderRadius: "0.25rem",
|
|
48
|
-
backgroundColor: "var(--gateway-icon-bg, oklch(94% 0 0))",
|
|
49
|
-
display: "flex",
|
|
50
|
-
alignItems: "center",
|
|
51
|
-
justifyContent: "center",
|
|
52
|
-
border: "1px solid var(--gateway-border, oklch(94% 0 0))",
|
|
53
|
-
},
|
|
54
|
-
title: {
|
|
55
|
-
fontSize: "18px",
|
|
56
|
-
fontWeight: 600,
|
|
57
|
-
marginBottom: "8px",
|
|
58
|
-
color: "var(--gateway-text, oklch(0% 0 0))",
|
|
59
|
-
letterSpacing: "-0.01em",
|
|
60
|
-
},
|
|
61
|
-
description: {
|
|
62
|
-
fontSize: "14px",
|
|
63
|
-
lineHeight: 1.5,
|
|
64
|
-
color: "var(--gateway-text-muted, oklch(40% 0 0))",
|
|
65
|
-
marginBottom: "20px",
|
|
66
|
-
},
|
|
67
|
-
urlText: {
|
|
68
|
-
fontSize: "14px",
|
|
69
|
-
lineHeight: 1.5,
|
|
70
|
-
color: "var(--gateway-text-muted, oklch(40% 0 0))",
|
|
71
|
-
wordBreak: "break-all",
|
|
72
|
-
},
|
|
73
|
-
urlLink: {
|
|
74
|
-
color: "rgb(168, 162, 158)",
|
|
75
|
-
textDecoration: "underline",
|
|
76
|
-
textDecorationColor: "rgb(87, 83, 78)",
|
|
77
|
-
textUnderlineOffset: "2px",
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Error component displayed when an embedded app is accessed directly
|
|
82
|
-
* instead of through the Every App Gateway.
|
|
83
|
-
*
|
|
84
|
-
* This component informs users that authentication requires accessing
|
|
85
|
-
* the app through the Gateway and provides a link to do so.
|
|
86
|
-
*/
|
|
87
|
-
export function GatewayRequiredError({ gatewayOrigin, appId, }) {
|
|
88
|
-
const isLocalhost = window.location.hostname === "localhost";
|
|
89
|
-
const gatewayUrl = `${gatewayOrigin}/apps/${appId}${window.location.pathname}${isLocalhost ? "dev" : ""}`;
|
|
90
|
-
return (_jsxs("div", { style: styles.container, children: [_jsx("style", { children: CSS_VARIABLES }), _jsxs("div", { style: styles.content, children: [_jsx("div", { style: styles.iconContainer, children: _jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "var(--gateway-icon-stroke, oklch(55% 0.22 25))", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), _jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), _jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }) }), _jsx("h1", { style: styles.title, children: "Open in Gateway" }), _jsx("p", { style: styles.description, children: "The Gateway handles sign in and user auth. Access your app from there so this works properly." }), _jsxs("p", { style: styles.urlText, children: ["Go to", " ", _jsx("a", { href: gatewayUrl, style: styles.urlLink, children: gatewayUrl })] })] })] }));
|
|
91
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { SessionManager } from "../../core/sessionManager.js";
|
|
2
|
-
interface SessionManagerConfig {
|
|
3
|
-
appId: string;
|
|
4
|
-
}
|
|
5
|
-
interface UseEveryAppSessionParams {
|
|
6
|
-
sessionManagerConfig: SessionManagerConfig;
|
|
7
|
-
}
|
|
8
|
-
type SessionBootstrapGate = Pick<SessionManager, "isEmbedded" | "isBypassGatewayLocalOnly">;
|
|
9
|
-
export declare function shouldBootstrapSession(sessionManager: SessionBootstrapGate): boolean;
|
|
10
|
-
export declare function useEveryAppSession({ sessionManagerConfig, }: UseEveryAppSessionParams): {
|
|
11
|
-
sessionManager: SessionManager | null;
|
|
12
|
-
sessionTokenState: {
|
|
13
|
-
status: "NO_TOKEN" | "VALID" | "EXPIRED" | "REFRESHING";
|
|
14
|
-
token: string | null;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
export {};
|
|
18
|
-
//# sourceMappingURL=useEveryAppSession.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useEveryAppSession.d.ts","sourceRoot":"","sources":["../../../src/tanstack/_internal/useEveryAppSession.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,wBAAwB;IAChC,oBAAoB,EAAE,oBAAoB,CAAC;CAC5C;AAED,KAAK,oBAAoB,GAAG,IAAI,CAC9B,cAAc,EACd,YAAY,GAAG,0BAA0B,CAC1C,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,oBAAoB,GACnC,OAAO,CAKT;AAED,wBAAgB,kBAAkB,CAAC,EACjC,oBAAoB,GACrB,EAAE,wBAAwB;;;;;;EA8C1B"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
import { SessionManager } from "../../core/sessionManager.js";
|
|
3
|
-
export function shouldBootstrapSession(sessionManager) {
|
|
4
|
-
// Bootstrapping should happen whenever the app is hosted by a trusted container.
|
|
5
|
-
// This intentionally keys off embedded environment semantics (iframe OR RN WebView),
|
|
6
|
-
// not iframe-only detection, so RN can initialize auth from pushed tokens.
|
|
7
|
-
return sessionManager.isEmbedded() || sessionManager.isBypassGatewayLocalOnly;
|
|
8
|
-
}
|
|
9
|
-
export function useEveryAppSession({ sessionManagerConfig, }) {
|
|
10
|
-
const sessionManagerRef = useRef(null);
|
|
11
|
-
const [sessionTokenState, setSessionTokenState] = useState({
|
|
12
|
-
status: "NO_TOKEN",
|
|
13
|
-
token: null,
|
|
14
|
-
});
|
|
15
|
-
if (!sessionManagerRef.current && typeof document !== "undefined") {
|
|
16
|
-
sessionManagerRef.current = new SessionManager(sessionManagerConfig);
|
|
17
|
-
}
|
|
18
|
-
const sessionManager = sessionManagerRef.current;
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (!sessionManager)
|
|
21
|
-
return;
|
|
22
|
-
// Skip token bootstrap when not embedded (unless in demo mode) - the app will show GatewayRequiredError instead
|
|
23
|
-
if (!shouldBootstrapSession(sessionManager))
|
|
24
|
-
return;
|
|
25
|
-
const interval = setInterval(() => {
|
|
26
|
-
setSessionTokenState(sessionManager.getTokenState());
|
|
27
|
-
}, 5000);
|
|
28
|
-
sessionManager
|
|
29
|
-
.getToken()
|
|
30
|
-
.then(() => {
|
|
31
|
-
setSessionTokenState(sessionManager.getTokenState());
|
|
32
|
-
})
|
|
33
|
-
.catch((err) => {
|
|
34
|
-
console.error("[EmbeddedProvider] Initial token request failed:", err);
|
|
35
|
-
});
|
|
36
|
-
return () => {
|
|
37
|
-
clearInterval(interval);
|
|
38
|
-
};
|
|
39
|
-
}, [sessionManager]);
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (!sessionManager)
|
|
42
|
-
return;
|
|
43
|
-
// Make sessionManager globally accessible for middleware
|
|
44
|
-
window.__embeddedSessionManager = sessionManager;
|
|
45
|
-
}, [sessionManager]);
|
|
46
|
-
return { sessionManager, sessionTokenState };
|
|
47
|
-
}
|
package/dist/tanstack/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tanstack/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/tanstack/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authConfig.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,wBAAgB,aAAa,IAAI,UAAU,CAc1C"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { env } from "cloudflare:workers";
|
|
2
|
-
import { isBypassGatewayLocalOnlyServer } from "../../shared/bypassGatewayLocalOnly.js";
|
|
3
|
-
export function getAuthConfig() {
|
|
4
|
-
const bypassGatewayLocalOnlyEnv = env.BYPASS_GATEWAY_LOCAL_ONLY;
|
|
5
|
-
const isBypassGatewayLocalOnly = import.meta.env.PROD !== true &&
|
|
6
|
-
(bypassGatewayLocalOnlyEnv === "true" ||
|
|
7
|
-
isBypassGatewayLocalOnlyServer() === true);
|
|
8
|
-
const issuer = env.GATEWAY_URL || (isBypassGatewayLocalOnly ? "local" : "");
|
|
9
|
-
return {
|
|
10
|
-
issuer,
|
|
11
|
-
audience: import.meta.env.VITE_APP_ID,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { AuthConfig } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* JWT payload structure for embedded app session tokens.
|
|
4
|
-
* Contains minimal claims for security - only what's needed for authentication.
|
|
5
|
-
*/
|
|
6
|
-
interface SessionTokenPayload {
|
|
7
|
-
/** User ID (subject claim) */
|
|
8
|
-
sub: string;
|
|
9
|
-
/** Gateway URL (issuer claim) */
|
|
10
|
-
iss: string;
|
|
11
|
-
/** App ID (audience claim) - scopes token to specific app */
|
|
12
|
-
aud: string;
|
|
13
|
-
/** Expiration timestamp */
|
|
14
|
-
exp: number;
|
|
15
|
-
/** Issued at timestamp */
|
|
16
|
-
iat: number;
|
|
17
|
-
/** User email - used for user provisioning in apps */
|
|
18
|
-
email?: string;
|
|
19
|
-
}
|
|
20
|
-
export declare function authenticateRequest(authConfig: AuthConfig, providedRequest?: Request): Promise<SessionTokenPayload | null>;
|
|
21
|
-
/**
|
|
22
|
-
* Extracts the bearer token from an Authorization header.
|
|
23
|
-
*
|
|
24
|
-
* @param authHeader - The Authorization header value (e.g., "Bearer eyJ...")
|
|
25
|
-
* @returns The token string if valid, null otherwise
|
|
26
|
-
*/
|
|
27
|
-
export declare function extractBearerToken(authHeader: string | null): string | null;
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=authenticateRequest.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authenticateRequest.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authenticateRequest.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C;;;GAGG;AACH,UAAU,mBAAmB;IAC3B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,UAAU,EACtB,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAoDrC;AAyCD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK3E"}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { getRequest } from "@tanstack/react-start/server";
|
|
2
|
-
import { createLocalJWKSet, jwtVerify, } from "jose";
|
|
3
|
-
import { env } from "cloudflare:workers";
|
|
4
|
-
import { BYPASS_GATEWAY_LOCAL_ONLY_TOKEN, createBypassGatewayLocalOnlySessionPayload, isBypassGatewayLocalOnlyServer, } from "../../shared/bypassGatewayLocalOnly.js";
|
|
5
|
-
export async function authenticateRequest(authConfig, providedRequest) {
|
|
6
|
-
const request = providedRequest || getRequest();
|
|
7
|
-
const authHeader = request.headers.get("authorization");
|
|
8
|
-
const bypassGatewayLocalOnlyEnv = env.BYPASS_GATEWAY_LOCAL_ONLY;
|
|
9
|
-
const isBypassGatewayLocalOnly = import.meta.env.PROD !== true &&
|
|
10
|
-
(bypassGatewayLocalOnlyEnv === "true" ||
|
|
11
|
-
isBypassGatewayLocalOnlyServer() === true);
|
|
12
|
-
if (!authHeader) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
const token = extractBearerToken(authHeader);
|
|
16
|
-
if (!token) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
if (isBypassGatewayLocalOnly) {
|
|
20
|
-
if (token !== BYPASS_GATEWAY_LOCAL_ONLY_TOKEN) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
return createBypassGatewayLocalOnlySessionPayload(authConfig.audience);
|
|
24
|
-
}
|
|
25
|
-
try {
|
|
26
|
-
const session = await verifySessionToken(token, authConfig);
|
|
27
|
-
return session;
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
const isProd = import.meta.env.PROD === true;
|
|
31
|
-
console.error(JSON.stringify({
|
|
32
|
-
message: "Error verifying session token",
|
|
33
|
-
error: error instanceof Error ? error.message : String(error),
|
|
34
|
-
stack: isProd === true
|
|
35
|
-
? undefined
|
|
36
|
-
: error instanceof Error
|
|
37
|
-
? error.stack
|
|
38
|
-
: undefined,
|
|
39
|
-
errorType: error instanceof Error ? error.constructor.name : "Unknown",
|
|
40
|
-
issuer: authConfig.issuer,
|
|
41
|
-
audience: authConfig.audience,
|
|
42
|
-
}));
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async function verifySessionToken(token, config) {
|
|
47
|
-
const { issuer, audience } = config;
|
|
48
|
-
if (!issuer) {
|
|
49
|
-
throw new Error("Issuer must be provided for token verification");
|
|
50
|
-
}
|
|
51
|
-
if (!audience) {
|
|
52
|
-
throw new Error("Audience must be provided for token verification");
|
|
53
|
-
}
|
|
54
|
-
// Fetch JWKS - use service binding in production, direct fetch in development
|
|
55
|
-
const jwksResponse = import.meta.env.PROD && env.EVERY_APP_GATEWAY
|
|
56
|
-
? await env.EVERY_APP_GATEWAY.fetch("http://localhost/api/embedded/jwks")
|
|
57
|
-
: await fetch(`${env.GATEWAY_URL}/api/embedded/jwks`);
|
|
58
|
-
if (!jwksResponse.ok) {
|
|
59
|
-
throw new Error(`Failed to fetch JWKS: ${jwksResponse.status} ${jwksResponse.statusText}`);
|
|
60
|
-
}
|
|
61
|
-
const jwks = (await jwksResponse.json());
|
|
62
|
-
const localJWKS = createLocalJWKSet(jwks);
|
|
63
|
-
const options = {
|
|
64
|
-
issuer,
|
|
65
|
-
audience,
|
|
66
|
-
algorithms: ["RS256"],
|
|
67
|
-
};
|
|
68
|
-
const { payload } = await jwtVerify(token, localJWKS, options);
|
|
69
|
-
return payload;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Extracts the bearer token from an Authorization header.
|
|
73
|
-
*
|
|
74
|
-
* @param authHeader - The Authorization header value (e.g., "Bearer eyJ...")
|
|
75
|
-
* @returns The token string if valid, null otherwise
|
|
76
|
-
*/
|
|
77
|
-
export function extractBearerToken(authHeader) {
|
|
78
|
-
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
return authHeader.substring(7);
|
|
82
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SessionManager } from "../core/sessionManager.js";
|
|
2
|
-
interface UseEveryAppRouterParams {
|
|
3
|
-
sessionManager: SessionManager | null;
|
|
4
|
-
}
|
|
5
|
-
export declare function useEveryAppRouter({ sessionManager }: UseEveryAppRouterParams): void;
|
|
6
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=useEveryAppRouter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useEveryAppRouter.d.ts","sourceRoot":"","sources":["../../src/tanstack/useEveryAppRouter.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,UAAU,uBAAuB;IAC/B,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,iBAAiB,CAAC,EAAE,cAAc,EAAE,EAAE,uBAAuB,QAyE5E"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
2
|
-
import { useRouter } from "@tanstack/react-router";
|
|
3
|
-
import { parseMessagePayload } from "../shared/parseMessagePayload.js";
|
|
4
|
-
export function useEveryAppRouter({ sessionManager }) {
|
|
5
|
-
const router = useRouter();
|
|
6
|
-
// Route synchronization effect
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
if (!sessionManager)
|
|
9
|
-
return;
|
|
10
|
-
// Listen for route sync messages from parent
|
|
11
|
-
const handleMessage = (event) => {
|
|
12
|
-
// Validate origin based on environment
|
|
13
|
-
if (!sessionManager.isTrustedHostMessage(event))
|
|
14
|
-
return;
|
|
15
|
-
const data = parseMessagePayload(event.data);
|
|
16
|
-
if (!data)
|
|
17
|
-
return;
|
|
18
|
-
if (data.type === "ROUTE_CHANGE" &&
|
|
19
|
-
data.direction === "parent-to-child") {
|
|
20
|
-
const targetRoute = typeof data.route === "string" ? data.route : null;
|
|
21
|
-
const currentRoute = window.location.pathname;
|
|
22
|
-
// Only navigate if the route is different from current location
|
|
23
|
-
if (targetRoute && targetRoute !== currentRoute) {
|
|
24
|
-
router.navigate({ to: targetRoute });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
window.addEventListener("message", handleMessage);
|
|
29
|
-
// Simplified route change detection with 2 reliable methods
|
|
30
|
-
let lastReportedPath = window.location.pathname;
|
|
31
|
-
const handleRouteChange = () => {
|
|
32
|
-
const currentPath = window.location.pathname;
|
|
33
|
-
// Only report if the path actually changed
|
|
34
|
-
if (currentPath === lastReportedPath) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
lastReportedPath = currentPath;
|
|
38
|
-
const message = {
|
|
39
|
-
type: "ROUTE_CHANGE",
|
|
40
|
-
route: currentPath,
|
|
41
|
-
appId: sessionManager.appId,
|
|
42
|
-
direction: "child-to-parent",
|
|
43
|
-
};
|
|
44
|
-
try {
|
|
45
|
-
sessionManager.postToHost(message);
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
// Listen to popstate for browser back/forward
|
|
52
|
-
window.addEventListener("popstate", handleRouteChange);
|
|
53
|
-
// Polling to detect route changes (catches router navigation)
|
|
54
|
-
const pollInterval = setInterval(() => {
|
|
55
|
-
const currentPath = window.location.pathname;
|
|
56
|
-
if (currentPath !== lastReportedPath) {
|
|
57
|
-
handleRouteChange();
|
|
58
|
-
}
|
|
59
|
-
}, 100);
|
|
60
|
-
return () => {
|
|
61
|
-
window.removeEventListener("message", handleMessage);
|
|
62
|
-
window.removeEventListener("popstate", handleRouteChange);
|
|
63
|
-
clearInterval(pollInterval);
|
|
64
|
-
};
|
|
65
|
-
}, [sessionManager]);
|
|
66
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSessionTokenClientMiddleware.d.ts","sourceRoot":"","sources":["../../src/tanstack/useSessionTokenClientMiddleware.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,+BAA+B,6GAmC1C,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { createMiddleware } from "@tanstack/react-start";
|
|
2
|
-
import { BYPASS_GATEWAY_LOCAL_ONLY_TOKEN, isBypassGatewayLocalOnlyClient, } from "../shared/bypassGatewayLocalOnly.js";
|
|
3
|
-
export const useSessionTokenClientMiddleware = createMiddleware({
|
|
4
|
-
type: "function",
|
|
5
|
-
}).client(async ({ next }) => {
|
|
6
|
-
if (isBypassGatewayLocalOnlyClient()) {
|
|
7
|
-
return next({
|
|
8
|
-
headers: {
|
|
9
|
-
Authorization: `Bearer ${BYPASS_GATEWAY_LOCAL_ONLY_TOKEN}`,
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
// Get the global sessionManager - this MUST be available for embedded apps
|
|
14
|
-
const sessionManager = window
|
|
15
|
-
.__embeddedSessionManager;
|
|
16
|
-
if (!sessionManager) {
|
|
17
|
-
throw new Error("[AuthMiddleware] SessionManager not available - embedded provider not initialized");
|
|
18
|
-
}
|
|
19
|
-
// INVARIANT: This is just an extra check and should never be the case if the sessionManager exists.
|
|
20
|
-
if (typeof sessionManager.getToken !== "function") {
|
|
21
|
-
throw new Error("[AuthMiddleware] SessionManager.getToken is not a function");
|
|
22
|
-
}
|
|
23
|
-
const token = await sessionManager.getToken();
|
|
24
|
-
return next({
|
|
25
|
-
headers: {
|
|
26
|
-
Authorization: `Bearer ${token}`,
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
});
|