@protobase/server 0.31.2 → 0.32.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.
@@ -0,0 +1,36 @@
1
+ import { authBasePath } from "./auth-base-path.js";
2
+ //#region src/better-auth/without-session-tokens.ts
3
+ const apiTokenPath = `${authBasePath}/token`;
4
+ const withoutTokens = (value) => {
5
+ if (Array.isArray(value)) return value.map(withoutTokens);
6
+ if (value === null || typeof value !== "object") return value;
7
+ return Object.fromEntries(Object.entries(value).filter(([key, field]) => !(key === "token" && typeof field === "string")).map(([key, field]) => [key, withoutTokens(field)]));
8
+ };
9
+ const parsed = (text) => {
10
+ try {
11
+ return JSON.parse(text);
12
+ } catch (error) {
13
+ if (error instanceof SyntaxError) throw new Error("Better Auth answered malformed JSON");
14
+ throw error;
15
+ }
16
+ };
17
+ /**
18
+ * Better Auth's answer to the page without the session tokens in its JSON, such as `get-session`'s `session.token` or a
19
+ * sign-in's `token`: the session is the httpOnly cookie's alone, so script on the page never holds a long-lived credential.
20
+ */
21
+ const withoutSessionTokens = async (request, response) => {
22
+ if (new URL(request.url).pathname === apiTokenPath) return response;
23
+ if (response.body === null) return response;
24
+ if (!response.headers.get("content-type")?.toLowerCase().includes("application/json")) return response;
25
+ const text = await response.text();
26
+ const headers = new Headers(response.headers);
27
+ headers.delete("content-length");
28
+ const body = text ? JSON.stringify(withoutTokens(parsed(text))) : null;
29
+ return new Response(body, {
30
+ status: response.status,
31
+ statusText: response.statusText,
32
+ headers
33
+ });
34
+ };
35
+ //#endregion
36
+ export { withoutSessionTokens };
@@ -22,6 +22,7 @@ import { readAppName } from "./app-name.js";
22
22
  import { realtimePath, restPath, storagePath, supabaseFunctionsPath, supabasePath } from "./supabase-paths.js";
23
23
  import { goTruePath } from "./gotrue/keys.js";
24
24
  import { authBasePath } from "./better-auth/auth-base-path.js";
25
+ import { withoutSessionTokens } from "./better-auth/without-session-tokens.js";
25
26
  import { organizationRoutes } from "./better-auth/organizations/admin-routes.js";
26
27
  import { statusRoute } from "./better-auth/status-route.js";
27
28
  import { goTrueTokens } from "./gotrue/access-tokens.js";
@@ -253,7 +254,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
253
254
  registry,
254
255
  db
255
256
  }));
256
- app.on(["GET", "POST"], `${authBasePath}/*`, (c) => auth.handler(c.req.raw));
257
+ app.on(["GET", "POST"], `${authBasePath}/*`, async (c) => withoutSessionTokens(c.req.raw, await auth.handler(c.req.raw)));
257
258
  app.route(goTruePath, goTrueRoutes(auth));
258
259
  if (auth.origins.length > 1) app.get(webauthnPath, (c) => c.json({ origins: auth.origins }));
259
260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.31.2",
3
+ "version": "0.32.0",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@better-auth/passkey": "^1.7.7",
34
34
  "@better-auth/sso": "^1.7.7",
35
- "@protobase/layout": "0.31.2",
36
- "@protobase/query": "0.31.2",
37
- "@protobase/schema": "0.31.2",
35
+ "@protobase/layout": "0.32.0",
36
+ "@protobase/query": "0.32.0",
37
+ "@protobase/schema": "0.32.0",
38
38
  "@react-email/render": "^2.1.0",
39
39
  "@scalar/hono-api-reference": "^0.12.10",
40
40
  "@sentry/core": "^11.7.0",