@every-app/sdk 0.0.4 → 0.0.6
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/client/EmbeddedAppProvider.d.ts +33 -0
- package/dist/client/EmbeddedAppProvider.d.ts.map +1 -0
- package/dist/client/EmbeddedAppProvider.js +55 -0
- package/dist/client/_internal/useEveryAppRouter.d.ts +9 -0
- package/dist/client/_internal/useEveryAppRouter.d.ts.map +1 -0
- package/dist/client/_internal/useEveryAppRouter.js +60 -0
- package/dist/client/_internal/useEveryAppSession.d.ts +15 -0
- package/dist/client/_internal/useEveryAppSession.d.ts.map +1 -0
- package/dist/client/_internal/useEveryAppSession.js +31 -0
- package/dist/client/authenticatedFetch.d.ts +12 -0
- package/dist/client/authenticatedFetch.d.ts.map +1 -0
- package/dist/client/authenticatedFetch.js +27 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +5 -0
- package/dist/client/lazyInitForWorkers.d.ts +24 -0
- package/dist/client/lazyInitForWorkers.d.ts.map +1 -0
- package/dist/client/lazyInitForWorkers.js +68 -0
- package/dist/client/session-manager.d.ts +27 -0
- package/dist/client/session-manager.d.ts.map +1 -0
- package/dist/client/session-manager.js +141 -0
- package/dist/client/useSessionTokenClientMiddleware.d.ts +8 -0
- package/dist/client/useSessionTokenClientMiddleware.d.ts.map +1 -0
- package/dist/client/useSessionTokenClientMiddleware.js +24 -0
- package/dist/server/auth-config.d.ts +3 -0
- package/dist/server/auth-config.d.ts.map +1 -0
- package/dist/server/auth-config.js +7 -0
- package/dist/server/authenticateRequest.d.ts +26 -0
- package/dist/server/authenticateRequest.d.ts.map +1 -0
- package/dist/server/authenticateRequest.js +71 -0
- package/dist/server/getLocalD1Url.d.ts +2 -0
- package/dist/server/getLocalD1Url.d.ts.map +1 -0
- package/dist/server/getLocalD1Url.js +53 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +2 -0
- package/dist/server/types.d.ts +5 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +1 -0
- package/package.json +23 -7
- package/src/client/_internal/useEveryAppRouter.tsx +3 -3
- package/src/client/_internal/useEveryAppSession.tsx +1 -6
- package/src/client/session-manager.test.ts +796 -0
- package/src/client/session-manager.ts +90 -179
- package/src/server/auth-config.ts +0 -1
- package/src/server/authenticateRequest.test.ts +416 -0
- package/src/server/authenticateRequest.ts +11 -6
- package/src/server/getLocalD1Url.ts +10 -12
- package/src/server/types.ts +0 -4
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { getRequest } from "@tanstack/react-start/server";
|
|
2
|
+
import { createLocalJWKSet, jwtVerify } from "jose";
|
|
3
|
+
import { env } from "cloudflare:workers";
|
|
4
|
+
export async function authenticateRequest(authConfig, providedRequest) {
|
|
5
|
+
const request = providedRequest || getRequest();
|
|
6
|
+
const authHeader = request.headers.get("authorization");
|
|
7
|
+
if (!authHeader) {
|
|
8
|
+
console.log("No auth header found");
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const token = extractBearerToken(authHeader);
|
|
12
|
+
if (!token) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const session = await verifySessionToken(token, authConfig);
|
|
17
|
+
return session;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error(
|
|
20
|
+
JSON.stringify({
|
|
21
|
+
message: "Error verifying session token",
|
|
22
|
+
error: error instanceof Error ? error.message : String(error),
|
|
23
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
24
|
+
errorType: error instanceof Error ? error.constructor.name : "Unknown",
|
|
25
|
+
issuer: authConfig.issuer,
|
|
26
|
+
audience: authConfig.audience,
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function verifySessionToken(token, config) {
|
|
33
|
+
const { issuer, audience } = config;
|
|
34
|
+
if (!issuer) {
|
|
35
|
+
throw new Error("Issuer must be provided for token verification");
|
|
36
|
+
}
|
|
37
|
+
if (!audience) {
|
|
38
|
+
throw new Error("Audience must be provided for token verification");
|
|
39
|
+
}
|
|
40
|
+
// Fetch JWKS - use service binding in production, direct fetch in development
|
|
41
|
+
const jwksResponse =
|
|
42
|
+
import.meta.env.PROD && env.EVERY_APP_GATEWAY
|
|
43
|
+
? await env.EVERY_APP_GATEWAY.fetch("http://localhost/api/embedded/jwks")
|
|
44
|
+
: await fetch(`${env.GATEWAY_URL}/api/embedded/jwks`);
|
|
45
|
+
if (!jwksResponse.ok) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Failed to fetch JWKS: ${jwksResponse.status} ${jwksResponse.statusText}`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const jwks = await jwksResponse.json();
|
|
51
|
+
const localJWKS = createLocalJWKSet(jwks);
|
|
52
|
+
const options = {
|
|
53
|
+
issuer,
|
|
54
|
+
audience,
|
|
55
|
+
algorithms: ["RS256"],
|
|
56
|
+
};
|
|
57
|
+
const { payload } = await jwtVerify(token, localJWKS, options);
|
|
58
|
+
return payload;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extracts the bearer token from an Authorization header.
|
|
62
|
+
*
|
|
63
|
+
* @param authHeader - The Authorization header value (e.g., "Bearer eyJ...")
|
|
64
|
+
* @returns The token string if valid, null otherwise
|
|
65
|
+
*/
|
|
66
|
+
export function extractBearerToken(authHeader) {
|
|
67
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return authHeader.substring(7);
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getLocalD1Url.d.ts","sourceRoot":"","sources":["../../src/server/getLocalD1Url.ts"],"names":[],"mappings":"AAWA,wBAAgB,aAAa,kBAoD5B"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import { parse } from "jsonc-parser";
|
|
5
|
+
function findSqliteFile(basePath) {
|
|
6
|
+
return fs
|
|
7
|
+
.readdirSync(basePath, { encoding: "utf-8", recursive: true })
|
|
8
|
+
.find((f) => f.endsWith(".sqlite"));
|
|
9
|
+
}
|
|
10
|
+
export function getLocalD1Url() {
|
|
11
|
+
const basePath = path.resolve(".wrangler");
|
|
12
|
+
// Check if .wrangler directory exists
|
|
13
|
+
if (!fs.existsSync(basePath)) {
|
|
14
|
+
console.error(
|
|
15
|
+
"================================================================================",
|
|
16
|
+
);
|
|
17
|
+
console.error("WARNING: .wrangler directory not found");
|
|
18
|
+
console.error("This is expected in CI/non-development environments.");
|
|
19
|
+
console.error(
|
|
20
|
+
"The local D1 database is only available after running 'wrangler dev' which you can trigger by running 'npm run dev'.",
|
|
21
|
+
);
|
|
22
|
+
console.error(
|
|
23
|
+
"================================================================================",
|
|
24
|
+
);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
let dbFile = findSqliteFile(basePath);
|
|
28
|
+
if (!dbFile) {
|
|
29
|
+
// Read wrangler.jsonc to get the database name
|
|
30
|
+
const wranglerConfigPath = path.resolve("wrangler.jsonc");
|
|
31
|
+
const wranglerConfig = parse(fs.readFileSync(wranglerConfigPath, "utf-8"));
|
|
32
|
+
const databaseName = wranglerConfig.d1_databases?.[0]?.database_name;
|
|
33
|
+
if (!databaseName) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"Could not find database_name in wrangler.jsonc d1_databases configuration",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
// Execute the command to initialize the local database
|
|
39
|
+
console.log(`Initializing local D1 database: ${databaseName}...`);
|
|
40
|
+
execSync(
|
|
41
|
+
`npx wrangler d1 execute ${databaseName} --local --command "SELECT 1;"`,
|
|
42
|
+
{ stdio: "pipe" },
|
|
43
|
+
);
|
|
44
|
+
// Try to find the db file again after initialization
|
|
45
|
+
dbFile = findSqliteFile(basePath);
|
|
46
|
+
if (!dbFile) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Failed to initialize local D1 database. The sqlite file was not created.`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return path.resolve(basePath, dbFile);
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,20 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@every-app/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./
|
|
5
|
+
"main": "./dist/client/index.js",
|
|
6
|
+
"types": "./dist/client/index.d.ts",
|
|
6
7
|
"exports": {
|
|
7
|
-
"./client":
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
"./client": {
|
|
9
|
+
"types": "./dist/client/index.d.ts",
|
|
10
|
+
"default": "./dist/client/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./server": {
|
|
13
|
+
"types": "./dist/server/index.d.ts",
|
|
14
|
+
"default": "./dist/server/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./server/getLocalD1Url": {
|
|
17
|
+
"types": "./dist/server/getLocalD1Url.d.ts",
|
|
18
|
+
"default": "./dist/server/getLocalD1Url.js"
|
|
19
|
+
}
|
|
10
20
|
},
|
|
11
21
|
"files": [
|
|
22
|
+
"dist",
|
|
12
23
|
"src"
|
|
13
24
|
],
|
|
14
25
|
"scripts": {
|
|
26
|
+
"build": "tsc -p tsconfig.build.json",
|
|
15
27
|
"types:check": "tsc --noEmit",
|
|
16
28
|
"format:check": "prettier --check .",
|
|
17
|
-
"format:write": "prettier . --write"
|
|
29
|
+
"format:write": "prettier . --write",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest"
|
|
18
32
|
},
|
|
19
33
|
"dependencies": {
|
|
20
34
|
"jsonc-parser": "^3.3.1"
|
|
@@ -35,6 +49,8 @@
|
|
|
35
49
|
"prettier": "^3.6.2",
|
|
36
50
|
"react": "^19.0.0",
|
|
37
51
|
"typescript": "^5.9.3",
|
|
38
|
-
"vite": "^7.1.2"
|
|
52
|
+
"vite": "^7.1.2",
|
|
53
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
54
|
+
"vitest": "^3.2.4"
|
|
39
55
|
}
|
|
40
56
|
}
|
|
@@ -12,7 +12,7 @@ export function useEveryAppRouter({ sessionManager }: UseEveryAppRouterParams) {
|
|
|
12
12
|
if (!sessionManager) return;
|
|
13
13
|
// Listen for route sync messages from parent
|
|
14
14
|
const handleMessage = (event: MessageEvent) => {
|
|
15
|
-
if (event.origin !== sessionManager.
|
|
15
|
+
if (event.origin !== sessionManager.parentOrigin) return;
|
|
16
16
|
|
|
17
17
|
if (
|
|
18
18
|
event.data.type === "ROUTE_CHANGE" &&
|
|
@@ -48,10 +48,10 @@ export function useEveryAppRouter({ sessionManager }: UseEveryAppRouterParams) {
|
|
|
48
48
|
{
|
|
49
49
|
type: "ROUTE_CHANGE",
|
|
50
50
|
route: currentPath,
|
|
51
|
-
appId: sessionManager.
|
|
51
|
+
appId: sessionManager.appId,
|
|
52
52
|
direction: "child-to-parent",
|
|
53
53
|
},
|
|
54
|
-
sessionManager.
|
|
54
|
+
sessionManager.parentOrigin,
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
};
|
|
@@ -26,11 +26,7 @@ export function useEveryAppSession({
|
|
|
26
26
|
if (!sessionManager) return;
|
|
27
27
|
const interval = setInterval(() => {
|
|
28
28
|
setSessionTokenState(sessionManager.getTokenState());
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
const unsubscribe = sessionManager.onDebugEvent(() => {
|
|
32
|
-
setSessionTokenState(sessionManager.getTokenState());
|
|
33
|
-
});
|
|
29
|
+
}, 5000);
|
|
34
30
|
|
|
35
31
|
sessionManager.getToken().catch((err) => {
|
|
36
32
|
console.error("[EmbeddedProvider] Initial token request failed:", err);
|
|
@@ -38,7 +34,6 @@ export function useEveryAppSession({
|
|
|
38
34
|
|
|
39
35
|
return () => {
|
|
40
36
|
clearInterval(interval);
|
|
41
|
-
unsubscribe();
|
|
42
37
|
};
|
|
43
38
|
}, [sessionManager]);
|
|
44
39
|
|