@sentry/junior-dashboard 0.97.0 → 0.97.1

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/app.js CHANGED
@@ -54,7 +54,7 @@ function stripTrailingSlashes(value) {
54
54
  return end === value.length ? value : value.slice(0, end);
55
55
  }
56
56
  function resolveDashboardBaseURL(config = {}) {
57
- const explicit = config.baseURL ?? process.env.BETTER_AUTH_URL ?? process.env.JUNIOR_BASE_URL;
57
+ const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
58
58
  if (explicit?.trim()) {
59
59
  return stripTrailingSlashes(withHttps(explicit.trim()));
60
60
  }
@@ -1912,9 +1912,9 @@ function requestedReturnPath(url, basePath) {
1912
1912
  }
1913
1913
  return `${returnUrl.pathname}${returnUrl.search}`;
1914
1914
  }
1915
- function dashboardLoginUrl(request, basePath) {
1915
+ function dashboardLoginUrl(request, basePath, canonicalBaseURL) {
1916
1916
  const requestUrl = new URL(request.url);
1917
- const url = new URL(request.url);
1917
+ const url = canonicalBaseURL ? new URL(canonicalBaseURL) : new URL(request.url);
1918
1918
  url.pathname = dashboardLoginPath(basePath);
1919
1919
  url.search = "";
1920
1920
  const returnPath = dashboardReturnPath(requestUrl, basePath);
@@ -1923,6 +1923,19 @@ function dashboardLoginUrl(request, basePath) {
1923
1923
  }
1924
1924
  return url.toString();
1925
1925
  }
1926
+ function canonicalLoginUrl(request, canonicalBaseURL) {
1927
+ if (!canonicalBaseURL) {
1928
+ return void 0;
1929
+ }
1930
+ const requestUrl = new URL(request.url);
1931
+ const canonicalUrl = new URL(canonicalBaseURL);
1932
+ if (requestUrl.origin === canonicalUrl.origin) {
1933
+ return void 0;
1934
+ }
1935
+ canonicalUrl.pathname = requestUrl.pathname;
1936
+ canonicalUrl.search = requestUrl.search;
1937
+ return canonicalUrl.toString();
1938
+ }
1926
1939
  function dashboardLoginPath(basePath) {
1927
1940
  return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
1928
1941
  }
@@ -1950,11 +1963,14 @@ function isAuthorized(session, allowedDomains, allowedEmails) {
1950
1963
  session.user.emailVerified && domain && allowedDomains.includes(domain)
1951
1964
  );
1952
1965
  }
1953
- function unauthorized(request, basePath) {
1966
+ function unauthorized(request, basePath, canonicalBaseURL) {
1954
1967
  if (isJsonRoute(new URL(request.url).pathname)) {
1955
1968
  return Response.json({ error: "unauthenticated" }, { status: 401 });
1956
1969
  }
1957
- return Response.redirect(dashboardLoginUrl(request, basePath), 302);
1970
+ return Response.redirect(
1971
+ dashboardLoginUrl(request, basePath, canonicalBaseURL),
1972
+ 302
1973
+ );
1958
1974
  }
1959
1975
  function forbidden(request) {
1960
1976
  if (!isJsonRoute(new URL(request.url).pathname)) {
@@ -2163,6 +2179,11 @@ function createDashboardApp(rawOptions) {
2163
2179
  const allowedDomains = normalizeValues(options.allowedGoogleDomains);
2164
2180
  const allowedEmails = normalizeValues(options.allowedEmails);
2165
2181
  const authRequired = options.authRequired !== false;
2182
+ const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
2183
+ let canonicalBaseURL;
2184
+ if (authRequired && (configuredBaseURL || !options.auth)) {
2185
+ canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
2186
+ }
2166
2187
  if (authRequired && allowedDomains.length === 0 && allowedEmails.length === 0) {
2167
2188
  throw new Error(
2168
2189
  "Junior dashboard auth requires allowedGoogleDomains or allowedEmails"
@@ -2177,6 +2198,10 @@ function createDashboardApp(rawOptions) {
2177
2198
  }) : void 0;
2178
2199
  const app = new Hono();
2179
2200
  app.get(dashboardLoginPath(basePath), async (c) => {
2201
+ const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
2202
+ if (canonicalUrl) {
2203
+ return Response.redirect(canonicalUrl, 302);
2204
+ }
2180
2205
  const returnUrl = callbackUrl(c.req.raw, basePath);
2181
2206
  if (!auth) {
2182
2207
  return Response.redirect(returnUrl, 302);
@@ -2198,11 +2223,11 @@ function createDashboardApp(rawOptions) {
2198
2223
  return;
2199
2224
  }
2200
2225
  if (!auth) {
2201
- return unauthorized(c.req.raw, basePath);
2226
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
2202
2227
  }
2203
2228
  const session = await auth.getSession(c.req.raw);
2204
2229
  if (!session) {
2205
- return unauthorized(c.req.raw, basePath);
2230
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
2206
2231
  }
2207
2232
  if (!isAuthorized(session, allowedDomains, allowedEmails)) {
2208
2233
  return forbidden(c.req.raw);
package/dist/index.js CHANGED
@@ -54,7 +54,7 @@ function stripTrailingSlashes(value) {
54
54
  return end === value.length ? value : value.slice(0, end);
55
55
  }
56
56
  function resolveDashboardBaseURL(config = {}) {
57
- const explicit = config.baseURL ?? process.env.BETTER_AUTH_URL ?? process.env.JUNIOR_BASE_URL;
57
+ const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
58
58
  if (explicit?.trim()) {
59
59
  return stripTrailingSlashes(withHttps(explicit.trim()));
60
60
  }
@@ -1912,9 +1912,9 @@ function requestedReturnPath(url, basePath) {
1912
1912
  }
1913
1913
  return `${returnUrl.pathname}${returnUrl.search}`;
1914
1914
  }
1915
- function dashboardLoginUrl(request, basePath) {
1915
+ function dashboardLoginUrl(request, basePath, canonicalBaseURL) {
1916
1916
  const requestUrl = new URL(request.url);
1917
- const url = new URL(request.url);
1917
+ const url = canonicalBaseURL ? new URL(canonicalBaseURL) : new URL(request.url);
1918
1918
  url.pathname = dashboardLoginPath(basePath);
1919
1919
  url.search = "";
1920
1920
  const returnPath = dashboardReturnPath(requestUrl, basePath);
@@ -1923,6 +1923,19 @@ function dashboardLoginUrl(request, basePath) {
1923
1923
  }
1924
1924
  return url.toString();
1925
1925
  }
1926
+ function canonicalLoginUrl(request, canonicalBaseURL) {
1927
+ if (!canonicalBaseURL) {
1928
+ return void 0;
1929
+ }
1930
+ const requestUrl = new URL(request.url);
1931
+ const canonicalUrl = new URL(canonicalBaseURL);
1932
+ if (requestUrl.origin === canonicalUrl.origin) {
1933
+ return void 0;
1934
+ }
1935
+ canonicalUrl.pathname = requestUrl.pathname;
1936
+ canonicalUrl.search = requestUrl.search;
1937
+ return canonicalUrl.toString();
1938
+ }
1926
1939
  function dashboardLoginPath(basePath) {
1927
1940
  return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
1928
1941
  }
@@ -1950,11 +1963,14 @@ function isAuthorized(session, allowedDomains, allowedEmails) {
1950
1963
  session.user.emailVerified && domain && allowedDomains.includes(domain)
1951
1964
  );
1952
1965
  }
1953
- function unauthorized(request, basePath) {
1966
+ function unauthorized(request, basePath, canonicalBaseURL) {
1954
1967
  if (isJsonRoute(new URL(request.url).pathname)) {
1955
1968
  return Response.json({ error: "unauthenticated" }, { status: 401 });
1956
1969
  }
1957
- return Response.redirect(dashboardLoginUrl(request, basePath), 302);
1970
+ return Response.redirect(
1971
+ dashboardLoginUrl(request, basePath, canonicalBaseURL),
1972
+ 302
1973
+ );
1958
1974
  }
1959
1975
  function forbidden(request) {
1960
1976
  if (!isJsonRoute(new URL(request.url).pathname)) {
@@ -2163,6 +2179,11 @@ function createDashboardApp(rawOptions) {
2163
2179
  const allowedDomains = normalizeValues(options.allowedGoogleDomains);
2164
2180
  const allowedEmails = normalizeValues(options.allowedEmails);
2165
2181
  const authRequired = options.authRequired !== false;
2182
+ const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
2183
+ let canonicalBaseURL;
2184
+ if (authRequired && (configuredBaseURL || !options.auth)) {
2185
+ canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
2186
+ }
2166
2187
  if (authRequired && allowedDomains.length === 0 && allowedEmails.length === 0) {
2167
2188
  throw new Error(
2168
2189
  "Junior dashboard auth requires allowedGoogleDomains or allowedEmails"
@@ -2177,6 +2198,10 @@ function createDashboardApp(rawOptions) {
2177
2198
  }) : void 0;
2178
2199
  const app = new Hono();
2179
2200
  app.get(dashboardLoginPath(basePath), async (c) => {
2201
+ const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
2202
+ if (canonicalUrl) {
2203
+ return Response.redirect(canonicalUrl, 302);
2204
+ }
2180
2205
  const returnUrl = callbackUrl(c.req.raw, basePath);
2181
2206
  if (!auth) {
2182
2207
  return Response.redirect(returnUrl, 302);
@@ -2198,11 +2223,11 @@ function createDashboardApp(rawOptions) {
2198
2223
  return;
2199
2224
  }
2200
2225
  if (!auth) {
2201
- return unauthorized(c.req.raw, basePath);
2226
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
2202
2227
  }
2203
2228
  const session = await auth.getSession(c.req.raw);
2204
2229
  if (!session) {
2205
- return unauthorized(c.req.raw, basePath);
2230
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
2206
2231
  }
2207
2232
  if (!isAuthorized(session, allowedDomains, allowedEmails)) {
2208
2233
  return forbidden(c.req.raw);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-dashboard",
3
- "version": "0.97.0",
3
+ "version": "0.97.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -34,8 +34,8 @@
34
34
  "recharts": "^3.8.1",
35
35
  "shiki": "4.1.0",
36
36
  "zod": "^4.4.3",
37
- "@sentry/junior": "0.97.0",
38
- "@sentry/junior-plugin-api": "0.97.0"
37
+ "@sentry/junior": "0.97.1",
38
+ "@sentry/junior-plugin-api": "0.97.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@tailwindcss/cli": "^4.3.0",
package/src/app.ts CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  readMockConversationStats,
33
33
  readMockConversationSubagent,
34
34
  } from "./mock-conversations";
35
+ import { resolveDashboardBaseURL } from "./url";
35
36
 
36
37
  const DEFAULT_BASE_PATH = "/";
37
38
  const DEFAULT_AUTH_PATH = "/api/auth";
@@ -196,9 +197,15 @@ function requestedReturnPath(url: URL, basePath: string): string | undefined {
196
197
  return `${returnUrl.pathname}${returnUrl.search}`;
197
198
  }
198
199
 
199
- function dashboardLoginUrl(request: Request, basePath: string): string {
200
+ function dashboardLoginUrl(
201
+ request: Request,
202
+ basePath: string,
203
+ canonicalBaseURL?: string,
204
+ ): string {
200
205
  const requestUrl = new URL(request.url);
201
- const url = new URL(request.url);
206
+ const url = canonicalBaseURL
207
+ ? new URL(canonicalBaseURL)
208
+ : new URL(request.url);
202
209
  url.pathname = dashboardLoginPath(basePath);
203
210
  url.search = "";
204
211
  const returnPath = dashboardReturnPath(requestUrl, basePath);
@@ -208,6 +215,25 @@ function dashboardLoginUrl(request: Request, basePath: string): string {
208
215
  return url.toString();
209
216
  }
210
217
 
218
+ function canonicalLoginUrl(
219
+ request: Request,
220
+ canonicalBaseURL: string | undefined,
221
+ ): string | undefined {
222
+ if (!canonicalBaseURL) {
223
+ return undefined;
224
+ }
225
+
226
+ const requestUrl = new URL(request.url);
227
+ const canonicalUrl = new URL(canonicalBaseURL);
228
+ if (requestUrl.origin === canonicalUrl.origin) {
229
+ return undefined;
230
+ }
231
+
232
+ canonicalUrl.pathname = requestUrl.pathname;
233
+ canonicalUrl.search = requestUrl.search;
234
+ return canonicalUrl.toString();
235
+ }
236
+
211
237
  function dashboardLoginPath(basePath: string): string {
212
238
  return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
213
239
  }
@@ -244,11 +270,18 @@ function isAuthorized(
244
270
  );
245
271
  }
246
272
 
247
- function unauthorized(request: Request, basePath: string): Response {
273
+ function unauthorized(
274
+ request: Request,
275
+ basePath: string,
276
+ canonicalBaseURL?: string,
277
+ ): Response {
248
278
  if (isJsonRoute(new URL(request.url).pathname)) {
249
279
  return Response.json({ error: "unauthenticated" }, { status: 401 });
250
280
  }
251
- return Response.redirect(dashboardLoginUrl(request, basePath), 302);
281
+ return Response.redirect(
282
+ dashboardLoginUrl(request, basePath, canonicalBaseURL),
283
+ 302,
284
+ );
252
285
  }
253
286
 
254
287
  function forbidden(request: Request): Response {
@@ -492,6 +525,11 @@ export function createDashboardApp(
492
525
  const allowedEmails = normalizeValues(options.allowedEmails);
493
526
 
494
527
  const authRequired = options.authRequired !== false;
528
+ const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
529
+ let canonicalBaseURL: string | undefined;
530
+ if (authRequired && (configuredBaseURL || !options.auth)) {
531
+ canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
532
+ }
495
533
 
496
534
  if (
497
535
  authRequired &&
@@ -516,6 +554,10 @@ export function createDashboardApp(
516
554
  const app = new Hono<{ Variables: Variables }>();
517
555
 
518
556
  app.get(dashboardLoginPath(basePath), async (c) => {
557
+ const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
558
+ if (canonicalUrl) {
559
+ return Response.redirect(canonicalUrl, 302);
560
+ }
519
561
  const returnUrl = callbackUrl(c.req.raw, basePath);
520
562
  if (!auth) {
521
563
  return Response.redirect(returnUrl, 302);
@@ -548,11 +590,11 @@ export function createDashboardApp(
548
590
  }
549
591
 
550
592
  if (!auth) {
551
- return unauthorized(c.req.raw, basePath);
593
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
552
594
  }
553
595
  const session = await auth.getSession(c.req.raw);
554
596
  if (!session) {
555
- return unauthorized(c.req.raw, basePath);
597
+ return unauthorized(c.req.raw, basePath, canonicalBaseURL);
556
598
  }
557
599
  if (!isAuthorized(session, allowedDomains, allowedEmails)) {
558
600
  return forbidden(c.req.raw);
package/src/url.ts CHANGED
@@ -33,10 +33,7 @@ export function normalizeDashboardPath(
33
33
  export function resolveDashboardBaseURL(
34
34
  config: DashboardBaseURLConfig = {},
35
35
  ): string {
36
- const explicit =
37
- config.baseURL ??
38
- process.env.BETTER_AUTH_URL ??
39
- process.env.JUNIOR_BASE_URL;
36
+ const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
40
37
  if (explicit?.trim()) {
41
38
  return stripTrailingSlashes(withHttps(explicit.trim()));
42
39
  }