diff --git a/forge.config.ts b/forge.config.ts index eebd778..ef84c34 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -22,6 +22,9 @@ const ignore = (file: string) => { if (file.startsWith("/scaffold")) { return false; } + if (file.startsWith("/worker")) { + return false; + } if (file.startsWith("/node_modules/better-sqlite3")) { return false; } diff --git a/package-lock.json b/package-lock.json index db5997a..27873db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dyad", - "version": "0.4.0", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dyad", - "version": "0.4.0", + "version": "0.5.0", "license": "MIT", "dependencies": { "@ai-sdk/anthropic": "^1.2.8", @@ -66,6 +66,7 @@ "shell-env": "^4.0.1", "shiki": "^3.2.1", "sonner": "^2.0.3", + "stacktrace-js": "^2.0.2", "tailwind-merge": "^3.1.0", "tailwindcss": "^4.1.3", "tree-kill": "^1.2.2", @@ -9657,6 +9658,15 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, "node_modules/es-abstract": { "version": "1.23.9", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", @@ -17564,6 +17574,15 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -17592,6 +17611,42 @@ "dev": true, "license": "MIT" }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "license": "MIT", + "dependencies": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + } + }, + "node_modules/stacktrace-gps/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, "node_modules/state-local": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", diff --git a/package.json b/package.json index 982c585..8519e5e 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,7 @@ "shell-env": "^4.0.1", "shiki": "^3.2.1", "sonner": "^2.0.3", + "stacktrace-js": "^2.0.2", "tailwind-merge": "^3.1.0", "tailwindcss": "^4.1.3", "tree-kill": "^1.2.2", diff --git a/scaffold/package.json b/scaffold/package.json index 470a8b1..c9ee5c3 100644 --- a/scaffold/package.json +++ b/scaffold/package.json @@ -56,7 +56,6 @@ "react-router-dom": "^6.26.2", "recharts": "^2.12.7", "sonner": "^1.5.0", - "stacktrace-js": "^2.0.2", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.3", diff --git a/scaffold/pnpm-lock.yaml b/scaffold/pnpm-lock.yaml index fd77d4f..dd336eb 100644 --- a/scaffold/pnpm-lock.yaml +++ b/scaffold/pnpm-lock.yaml @@ -143,9 +143,6 @@ importers: sonner: specifier: ^1.5.0 version: 1.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - stacktrace-js: - specifier: ^2.0.2 - version: 2.0.2 tailwind-merge: specifier: ^2.5.2 version: 2.6.0 @@ -1618,9 +1615,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - error-stack-parser@2.1.4: - resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} - esbuild@0.25.3: resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} engines: {node: '>=18'} @@ -2230,22 +2224,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.5.6: - resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} - engines: {node: '>=0.10.0'} - - stack-generator@2.0.10: - resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} - - stackframe@1.3.4: - resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - - stacktrace-gps@3.1.2: - resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} - - stacktrace-js@2.0.2: - resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3782,10 +3760,6 @@ snapshots: emoji-regex@9.2.2: {} - error-stack-parser@2.1.4: - dependencies: - stackframe: 1.3.4 - esbuild@0.25.3: optionalDependencies: '@esbuild/aix-ppc64': 0.25.3 @@ -4389,25 +4363,6 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.5.6: {} - - stack-generator@2.0.10: - dependencies: - stackframe: 1.3.4 - - stackframe@1.3.4: {} - - stacktrace-gps@3.1.2: - dependencies: - source-map: 0.5.6 - stackframe: 1.3.4 - - stacktrace-js@2.0.2: - dependencies: - error-stack-parser: 2.1.4 - stack-generator: 2.0.10 - stacktrace-gps: 3.1.2 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 diff --git a/scaffold/vite.config.ts b/scaffold/vite.config.ts index fec7dae..19e7eca 100644 --- a/scaffold/vite.config.ts +++ b/scaffold/vite.config.ts @@ -1,98 +1,13 @@ -import { defineConfig, Plugin, HtmlTagDescriptor } from "vite"; +import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import path from "path"; -import fs from "fs"; - -export function devErrorAndNavigationPlugin(): Plugin { - let stacktraceJsContent: string | null = null; - let dyadShimContent: string | null = null; - - return { - name: "dev-error-and-navigation-handler", - apply: "serve", - - configResolved() { - const stackTraceLibPath = path.join( - "node_modules", - "stacktrace-js", - "dist", - "stacktrace.min.js", - ); - if (stackTraceLibPath) { - try { - stacktraceJsContent = fs.readFileSync(stackTraceLibPath, "utf-8"); - } catch (error) { - console.error( - `[dyad-shim] Failed to read stacktrace.js from ${stackTraceLibPath}:`, - error, - ); - stacktraceJsContent = null; - } - } else { - console.error(`[dyad-shim] stacktrace.js not found.`); - } - - const dyadShimPath = path.join("dyad-shim.js"); - if (dyadShimPath) { - try { - dyadShimContent = fs.readFileSync(dyadShimPath, "utf-8"); - } catch (error) { - console.error( - `[dyad-shim] Failed to read dyad-shim from ${dyadShimPath}:`, - error, - ); - dyadShimContent = null; - } - } else { - console.error(`[dyad-shim] stacktrace.js not found.`); - } - }, - - transformIndexHtml(html) { - const tags: HtmlTagDescriptor[] = []; - - // 1. Inject stacktrace.js - if (stacktraceJsContent) { - tags.push({ - tag: "script", - injectTo: "head-prepend", - children: stacktraceJsContent, - }); - } else { - tags.push({ - tag: "script", - injectTo: "head-prepend", - children: - "console.warn('[dyad-shim] stacktrace.js library was not injected.');", - }); - } - - // 2. Inject dyad shim - if (dyadShimContent) { - tags.push({ - tag: "script", - injectTo: "head-prepend", - children: dyadShimContent, - }); - } else { - tags.push({ - tag: "script", - injectTo: "head-prepend", - children: "console.warn('[dyad-shim] dyad shim was not injected.');", - }); - } - - return { html, tags }; - }, - }; -} export default defineConfig(() => ({ server: { host: "::", port: 8080, }, - plugins: [react(), devErrorAndNavigationPlugin()], + plugins: [react()], resolve: { alias: { "@": path.resolve(__dirname, "./src"), diff --git a/src/atoms/appAtoms.ts b/src/atoms/appAtoms.ts index 3685758..efa9309 100644 --- a/src/atoms/appAtoms.ts +++ b/src/atoms/appAtoms.ts @@ -11,8 +11,9 @@ export const previewModeAtom = atom<"preview" | "code">("preview"); export const selectedVersionIdAtom = atom(null); export const appOutputAtom = atom([]); export const appUrlAtom = atom< - { appUrl: string; appId: number } | { appUrl: null; appId: null } ->({ appUrl: null, appId: null }); + | { appUrl: string; appId: number; originalUrl: string } + | { appUrl: null; appId: null; originalUrl: null } +>({ appUrl: null, appId: null, originalUrl: null }); export const userSettingsAtom = atom(null); // Atom for storing allow-listed environment variables diff --git a/src/components/preview_panel/PreviewIframe.tsx b/src/components/preview_panel/PreviewIframe.tsx index 01ca2bb..80acf25 100644 --- a/src/components/preview_panel/PreviewIframe.tsx +++ b/src/components/preview_panel/PreviewIframe.tsx @@ -106,7 +106,7 @@ const ErrorBanner = ({ error, onDismiss, onAIFix }: ErrorBannerProps) => { // Preview iframe component export const PreviewIframe = ({ loading }: { loading: boolean }) => { const selectedAppId = useAtomValue(selectedAppIdAtom); - const { appUrl } = useAtomValue(appUrlAtom); + const { appUrl, originalUrl } = useAtomValue(appUrlAtom); const setAppOutput = useSetAtom(appOutputAtom); // State to trigger iframe reload const [reloadKey, setReloadKey] = useState(0); @@ -429,8 +429,8 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {