Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function DashboardDetailContent({
<PageLayout fillWidth noPadding>
{/* Both panels are always in the DOM so the iframe never unmounts/reloads.
The chat panel animates its width; the dashboard panel adjusts via flex-1. */}
<div data-full-bleed className="flex h-full">
<div data-full-bleed className="flex h-[calc(100vh-4.5rem)] dark:h-[calc(100vh-5.75rem)]">
Comment thread
aadesh18 marked this conversation as resolved.
Comment thread
aadesh18 marked this conversation as resolved.
{/* Dashboard iframe panel */}
<div
className={cn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,42 @@ type DashboardArtifact = {
function html(strings: TemplateStringsArray, ...values: unknown[]): string {
return strings.reduce<string>((result, str, i) => result + str + (values[i] ?? ''), '');
}

const isDev = process.env.NODE_ENV === "development";

function getEsmFallbackVersion(version: string): string {
const parts = version.split(".");
if (parts.length !== 3) return version;
const patch = Number(parts[2]);
if (!Number.isInteger(patch) || patch <= 0) return version;
return `${parts[0]}.${parts[1]}.${patch - 1}`;
}
Comment thread
aadesh18 marked this conversation as resolved.
Comment thread
aadesh18 marked this conversation as resolved.

function getDependencyScripts(esmVersion: string, esmFallbackVersion: string, dashboardUrl: string): string {
if (isDev) {
return html`
<script type="module">
function formatDependencyError(error) {
return error instanceof Error ? error.message : String(error);
}

function reportDependencyError(message, error) {
window.parent.postMessage({
type: 'dashboard-sandbox-dependency-error',
message,
stack: error instanceof Error ? error.stack : undefined,
}, '*');
}

function failDependencyLoad(message, error) {
reportDependencyError(message, error);
window.__depsError = {
message,
stack: error instanceof Error ? error.stack : undefined,
};
window.__depsReady = true;
window.dispatchEvent(new Event('deps-ready'));
}

import React from 'https://esm.sh/react@19.2.3';
import * as ReactDOM from 'https://esm.sh/react-dom@19.2.3?deps=react@19.2.3';
import * as ReactDOMClient from 'https://esm.sh/react-dom@19.2.3/client?deps=react@19.2.3';
Expand All @@ -41,14 +70,14 @@ function getDependencyScripts(esmVersion: string, esmFallbackVersion: string, da
window.StackServerApp = StackSDK.StackServerApp;
window.StackSDK = StackSDK;
} catch (e) {
window.parent.postMessage({ type: 'dashboard-error-boundary', message: '[sandbox] Stack SDK failed at version ${esmVersion}, trying fallback ${esmFallbackVersion}: ' + e?.message }, '*');
reportDependencyError('[sandbox] @stackframe/js failed at version ${esmVersion}; trying fallback ${esmFallbackVersion}: ' + formatDependencyError(e), e);
try {
const StackSDK = await import('https://esm.sh/@stackframe/js@${esmFallbackVersion}');
window.StackAdminApp = StackSDK.StackAdminApp;
window.StackServerApp = StackSDK.StackServerApp;
window.StackSDK = StackSDK;
} catch (e2) {
window.parent.postMessage({ type: 'dashboard-error-boundary', message: '[sandbox] Stack SDK fallback also failed: ' + e2?.message }, '*');
failDependencyLoad('[sandbox] @stackframe/js fallback failed at version ${esmFallbackVersion}: ' + formatDependencyError(e2), e2);
}
}
window.generateUuid = () => crypto.randomUUID();
Expand All @@ -61,17 +90,39 @@ function getDependencyScripts(esmVersion: string, esmFallbackVersion: string, da
window.dispatchEvent(new Event('deps-ready'));
};
script.onerror = (e) => {
window.parent.postMessage({
type: 'dashboard-error-boundary',
message: 'Failed to load dashboard-ui-components IIFE bundle',
}, '*');
const message = '[sandbox] Failed to load local dashboard-ui-components IIFE bundle. Run pnpm --filter @stackframe/dashboard-ui-components dev or pnpm --filter @stackframe/dashboard-ui-components build so apps/dashboard/public/dashboard-ui-components.iife.js exists.';
failDependencyLoad(message, e instanceof Error ? e : new Error(message));
};
document.head.appendChild(script);
</script>`;
}

return html`
<script type="module">
const CUSTOM_DASHBOARD_LOAD_ERROR_MESSAGE = 'There was a problem loading custom dashboards. Please refresh the page and try again.';

function formatDependencyError(error) {
return error instanceof Error ? error.message : String(error);
}

function reportDependencyError(message, error) {
window.parent.postMessage({
type: 'dashboard-sandbox-dependency-error',
message,
stack: error instanceof Error ? error.stack : undefined,
}, '*');
}

function failDependencyLoad(message, error) {
reportDependencyError(message, error);
window.__depsError = {
message: CUSTOM_DASHBOARD_LOAD_ERROR_MESSAGE,
stack: error instanceof Error ? error.stack : undefined,
};
window.__depsReady = true;
window.dispatchEvent(new Event('deps-ready'));
}

import React from 'https://esm.sh/react@19.2.3';
import * as ReactDOM from 'https://esm.sh/react-dom@19.2.3?deps=react@19.2.3';
import * as ReactDOMClient from 'https://esm.sh/react-dom@19.2.3/client?deps=react@19.2.3';
Expand All @@ -89,21 +140,27 @@ function getDependencyScripts(esmVersion: string, esmFallbackVersion: string, da
import('https://esm.sh/@stackframe/js@${esmVersion}'),
]);
} catch (e) {
window.parent.postMessage({ type: 'dashboard-error-boundary', message: '[sandbox] Failed to load at version ${esmVersion}, trying fallback ${esmFallbackVersion}: ' + e?.message }, '*');
[DashboardUIComponents, StackSDK] = await Promise.all([
import('https://esm.sh/@stackframe/dashboard-ui-components@${esmFallbackVersion}?deps=react@19.2.3,react-dom@19.2.3'),
import('https://esm.sh/@stackframe/js@${esmFallbackVersion}'),
]);
reportDependencyError('[sandbox] Custom dashboard packages failed at version ${esmVersion}; trying fallback ${esmFallbackVersion}: ' + formatDependencyError(e), e);
try {
[DashboardUIComponents, StackSDK] = await Promise.all([
import('https://esm.sh/@stackframe/dashboard-ui-components@${esmFallbackVersion}?deps=react@19.2.3,react-dom@19.2.3'),
import('https://esm.sh/@stackframe/js@${esmFallbackVersion}'),
]);
} catch (e2) {
failDependencyLoad('[sandbox] Custom dashboard package fallback failed at version ${esmFallbackVersion}: ' + formatDependencyError(e2), e2);
}
}

window.DashboardUI = DashboardUIComponents;
window.StackAdminApp = StackSDK.StackAdminApp;
window.StackServerApp = StackSDK.StackServerApp;
window.StackSDK = StackSDK;
window.generateUuid = () => crypto.randomUUID();
if (!window.__depsError) {
window.DashboardUI = DashboardUIComponents;
window.StackAdminApp = StackSDK.StackAdminApp;
window.StackServerApp = StackSDK.StackServerApp;
window.StackSDK = StackSDK;
window.generateUuid = () => crypto.randomUUID();

window.__depsReady = true;
window.dispatchEvent(new Event('deps-ready'));
window.__depsReady = true;
window.dispatchEvent(new Event('deps-ready'));
}
</script>`;
}

Expand All @@ -118,7 +175,7 @@ function getSandboxDocument(artifact: DashboardArtifact, baseUrl: string, dashbo
const sourceCode = escapeScriptContent(artifact.runtimeCodegen.uiRuntimeSourceCode);
const darkClass = initialTheme === "dark" ? "dark" : "";
const esmVersion = packageJson.version;
const esmFallbackVersion = "2.8.71";
const esmFallbackVersion = getEsmFallbackVersion(esmVersion);
Comment on lines 177 to +178
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the version-sync assumption: is the dashboard app version always == the SDK package versions?
echo "=== Dashboard app version ==="
jq -r '.version' apps/dashboard/package.json 2>/dev/null

echo
echo "=== `@stackframe/js` package version (in repo) ==="
fd -t f 'package.json' | xargs -I{} sh -c 'jq -e ".name == \"@stackframe/js\"" {} >/dev/null 2>&1 && echo "{}: $(jq -r .version {})"'

echo
echo "=== `@stackframe/dashboard-ui-components` package version (in repo) ==="
fd -t f 'package.json' | xargs -I{} sh -c 'jq -e ".name == \"@stackframe/dashboard-ui-components\"" {} >/dev/null 2>&1 && echo "{}: $(jq -r .version {})"'

echo
echo "=== Release config / changesets coupling ==="
fd -t f -e json -e md . .changeset 2>/dev/null | head -n 20
fd -t f 'release.config*' 2>/dev/null
rg -nP --no-heading -C2 '"version"\s*:' --glob 'package.json' --glob '!**/node_modules/**' | head -n 80

Repository: hexclave/stack-auth

Length of output: 5147


🏁 Script executed:

#!/bin/bash
# Understand the release strategy and version coupling

echo "=== Changeset config ==="
cat .changeset/config.json 2>/dev/null | head -40

echo
echo "=== Release config files ==="
find . -maxdepth 2 -name 'release.config*' -o -name '.releaserc*' 2>/dev/null

echo
echo "=== GitHub Actions workflow files related to release/publish ==="
fd -t f '.github/workflows' | xargs -I{} sh -c 'rg -l "release|publish|version" "{}" 2>/dev/null' | head -10

echo
echo "=== Check for monorepo configuration (lerna.json, pnpm-workspace) ==="
ls -la lerna.json pnpm-workspace.yaml package-lock.json yarn.lock 2>/dev/null | grep -v "cannot access"

echo
echo "=== Look at root package.json for workspaces/publishing ==="
jq '.workspaces, .publishConfig, .version' package.json 2>/dev/null

echo
echo "=== Check if dashboard is listed in changesets for independent publishing ==="
rg -i "dashboard" .changeset/ --type md -A2 2>/dev/null | head -30

Repository: hexclave/stack-auth

Length of output: 1128


🏁 Script executed:

#!/bin/bash
# Verify the pnpm workspace and release workflow

echo "=== pnpm workspace config ==="
cat pnpm-workspace.yaml

echo
echo "=== GitHub Actions workflows (corrected) ==="
fd . '.github/workflows' -type f | head -20

echo
echo "=== Look for publish/release workflow content ==="
fd . '.github/workflows' -type f | xargs grep -l "publish\|release" 2>/dev/null | head -5 | xargs cat 2>/dev/null | head -100

Repository: hexclave/stack-auth

Length of output: 692


🏁 Script executed:

#!/bin/bash
# Find workflows correctly

echo "=== GitHub Actions workflows ==="
find .github/workflows -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -20

echo
echo "=== Publish/Release workflows ==="
find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null | xargs grep -l "publish\|release" 2>/dev/null

echo
echo "=== Changesets related config and workflow ==="
find . -maxdepth 3 -name "*changeset*" -o -name "*release*" 2>/dev/null | grep -v node_modules | head -20

echo
echo "=== Inspect the main publish/release workflow if it exists ==="
find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) -exec grep -l changesets {} \; 2>/dev/null | xargs cat 2>/dev/null | head -150

Repository: hexclave/stack-auth

Length of output: 1221


🏁 Script executed:

#!/bin/bash
# Examine the npm-publish workflow

echo "=== npm-publish.yaml workflow ==="
cat .github/workflows/npm-publish.yaml

echo
echo "=== Check for any release-please or conventional commits ==="
rg "release-please|conventional" . --type yaml -A3 -B3 2>/dev/null

echo
echo "=== Changeset documentation in repo ==="
find . -name "CHANGELOG*" -o -name "RELEASE*" 2>/dev/null | head -10

Repository: hexclave/stack-auth

Length of output: 2047


Add a comment documenting the version-sync invariant.

The version assumption is enforced by the monorepo's changesets configuration, which uses "fixed": [["**"]] to ensure all packages—including apps/dashboard, @stackframe/js, and @stackframe/dashboard-ui-components—must release with the same version number. However, this constraint isn't obvious from the code alone. Add a brief comment near line 176 explaining that the changesets fixed-versioning scheme guarantees that esmVersion will always correspond to a published version of the ESM modules, keeping the fallback strategy effective.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/dashboard/src/components/commands/create-dashboard/dashboard-sandbox-host.tsx`
around lines 176 - 177, Add a brief code comment above the lines that set
esmVersion and esmFallbackVersion (the variables esmVersion, esmFallbackVersion
and the call getEsmFallbackVersion(packageJson.version)) documenting the
invariant: explain that the monorepo uses changesets with fixed-versioning
("fixed": [["**"]]) so all packages (e.g., apps/dashboard, `@stackframe/js`,
`@stackframe/dashboard-ui-components`) share the same release version, and
therefore esmVersion will always match a published ESM module version making the
fallback strategy valid. Keep the comment short and placed next to the existing
packageJson.version usage.

const devScriptSrc = isDev ? ` ${dashboardUrl}` : '';
const devConnectSrc = isDev ? ` ${dashboardUrl}` : '';

Expand Down Expand Up @@ -307,10 +364,18 @@ function getSandboxDocument(artifact: DashboardArtifact, baseUrl: string, dashbo
};

async function waitForDeps() {
if (window.__depsReady) return;
await new Promise(resolve => {
window.addEventListener('deps-ready', resolve, { once: true });
});
if (!window.__depsReady) {
await new Promise(resolve => {
window.addEventListener('deps-ready', resolve, { once: true });
});
}
if (window.__depsError) {
const error = new Error(window.__depsError.message || 'There was a problem loading custom dashboards. Please refresh the page and try again.');
if (window.__depsError.stack) {
error.stack = window.__depsError.stack;
}
throw error;
}
}

async function requestAccessToken() {
Expand Down Expand Up @@ -735,6 +800,13 @@ export const DashboardSandboxHost = memo(function DashboardSandboxHost({
return;
}

if (type === "dashboard-sandbox-dependency-error") {
const err = new Error(event.data.message ?? 'Unknown custom dashboard dependency error');
if (event.data.stack) err.stack = event.data.stack;
captureError('dashboard-sandbox-dependency-error', err);
return;
}

if (type === "dashboard-error-boundary") {
const err = new Error(event.data.message ?? 'Unknown dashboard error');
if (event.data.stack) err.stack = event.data.stack;
Expand Down
Loading