@sylphx/sdk 0.11.2 → 0.12.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.
@@ -142,6 +142,16 @@ interface SylphxMiddlewareConfig {
142
142
  * @default resolved from SYLPHX_SECRET_URL, SYLPHX_URL, SYLPHX_BAAS_URL, or SYLPHX_RUNTIME_URL
143
143
  */
144
144
  platformUrl?: string;
145
+ /**
146
+ * Canonical public application URL used for OAuth callback URLs.
147
+ *
148
+ * Set this when the app is served behind a proxy, custom domain, or platform
149
+ * generated hostname where the request URL may not be the user-facing origin.
150
+ * Only the origin is used; callback path remains owned by `authPrefix`.
151
+ *
152
+ * @default request URL origin
153
+ */
154
+ appUrl?: string;
145
155
  /**
146
156
  * Callback to add custom headers/logic to responses.
147
157
  * Called for every non-auth-route request after SDK processing.
@@ -7,7 +7,13 @@ var ENV_PUBLIC_URL = "NEXT_PUBLIC_SYLPHX_URL";
7
7
  var ENV_SECRET_URL = "SYLPHX_SECRET_URL";
8
8
  var SDK_API_PATH = `/v1`;
9
9
  var DEFAULT_SDK_API_HOST = "api.sylphx.com";
10
- var SDK_PLATFORM = typeof window !== "undefined" ? "browser" : typeof process !== "undefined" && process.versions?.node ? "node" : "unknown";
10
+ function detectSdkPlatform() {
11
+ if (typeof window !== "undefined") return "browser";
12
+ const runtimeGlobal = globalThis;
13
+ if (typeof runtimeGlobal.EdgeRuntime !== "undefined") return "edge";
14
+ return "node";
15
+ }
16
+ var SDK_PLATFORM = detectSdkPlatform();
11
17
  var TOKEN_EXPIRY_BUFFER_MS = 3e4;
12
18
  var SESSION_TOKEN_LIFETIME_SECONDS = 5 * 60;
13
19
  var SESSION_TOKEN_LIFETIME_MS = SESSION_TOKEN_LIFETIME_SECONDS * 1e3;
@@ -595,6 +601,19 @@ function resolveSameOriginUrl(request, value, fallbackPath) {
595
601
  return null;
596
602
  }
597
603
  }
604
+ function normalizeAppUrl(value) {
605
+ if (!value?.trim()) return null;
606
+ try {
607
+ const url = new URL(value);
608
+ return url.origin;
609
+ } catch {
610
+ return null;
611
+ }
612
+ }
613
+ function resolveOAuthCallbackUrl(request, ctx) {
614
+ const origin = ctx.config.appUrl ?? new URL(request.url).origin;
615
+ return new URL(`${ctx.config.authPrefix}/callback`, origin);
616
+ }
598
617
  function bytesToBase64Url(bytes) {
599
618
  let binary = "";
600
619
  for (const byte of bytes) binary += String.fromCharCode(byte);
@@ -798,7 +817,7 @@ async function handleOAuthAuthorize(request, ctx) {
798
817
  return NextResponse.json({ error: "provider is required" }, { status: 400 });
799
818
  }
800
819
  const redirectTo = resolveSafeRelativeRedirectPath(rawRedirectTo, ctx.config.afterSignInUrl);
801
- const redirectUri = new URL(`${ctx.config.authPrefix}/callback`, request.url);
820
+ const redirectUri = resolveOAuthCallbackUrl(request, ctx);
802
821
  redirectUri.searchParams.set("redirect_to", redirectTo);
803
822
  const verifier = randomBase64Url(32);
804
823
  const challenge = await sha256Base64Url(verifier);
@@ -1340,6 +1359,7 @@ function createSylphxMiddleware(userConfig = {}) {
1340
1359
  afterSignInUrl: userConfig.afterSignInUrl ?? "/dashboard",
1341
1360
  authPrefix: userConfig.authPrefix ?? "/auth",
1342
1361
  baasPrefix: userConfig.baasPrefix === false ? null : normalizeRoutePrefix(userConfig.baasPrefix ?? DEFAULT_BAAS_PREFIX),
1362
+ appUrl: normalizeAppUrl(userConfig.appUrl),
1343
1363
  debug: userConfig.debug ?? false,
1344
1364
  orgRequired: userConfig.orgRequired ?? false,
1345
1365
  orgSelectionUrl: userConfig.orgSelectionUrl ?? "/select-organization",