Skip to content

Conversation

@Kitenite
Copy link
Contributor

@Kitenite Kitenite commented Aug 31, 2025

Description

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Release
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes


Important

Upgrade @codesandbox/sdk to ^2.1.0, update related code, and modify database schema and constraints.

  • Dependencies:
    • Upgrade @codesandbox/sdk to ^2.1.0 and add @codesandbox/pitcher-client ^1.1.7 in package.json.
    • Update bun.lock with new dependencies and versions, including @codesandbox/api, @codesandbox/nodebox, and others.
  • Code Changes:
    • Update CodesandboxProvider in index.ts to use SandboxClient and SandboxSession from the new SDK.
    • Modify initialize() and createSession() methods to align with the new SDK API.
    • Update readRemoteFile() in utils.ts to use SandboxClient.
  • Database:
    • Add feedbacks table and modify constraints in 0017_small_xavin.sql.
    • Update 0017_snapshot.json to reflect new database schema.

This description was created by Ellipsis for fa5068e. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • New Features

    • Upgraded CodeSandbox integration to the latest SDK for more reliable editor sessions and file operations.
    • Refreshed default templates for Blank and Next.js projects to improve project creation.
  • Bug Fixes

    • Improved session validation to prevent failed sandbox connections.
  • Chores

    • Database updates to support feedback collection (including attachments) and future project tags; no UI changes yet.
    • Added indexing and updated constraints to improve invitation and domain/deployment reliability.

@vercel
Copy link

vercel bot commented Aug 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
docs Ready Ready Preview Comment Aug 31, 2025 11:05pm
web Error Error Aug 31, 2025 11:05pm

@coderabbitai
Copy link

coderabbitai bot commented Aug 31, 2025

Walkthrough

Introduces a new feedbacks table with RLS, updates project-related FKs and indexes, adds tags and updated_preview_img_at to projects, and records the migration snapshot/journal. Migrates CodeSandbox integration to SDK v2 types (SandboxSession/SandboxClient), updates related utilities and package dependencies, adjusts client-side type casts, and updates template IDs.

Changes

Cohort / File(s) Summary
Database migration
apps/backend/supabase/migrations/0017_small_xavin.sql, apps/backend/supabase/migrations/meta/0017_snapshot.json, apps/backend/supabase/migrations/meta/_journal.json
Adds feedbacks table with RLS and user FK; adds projects.tags and projects.updated_preview_img_at; redefines FKs on several tables with ON DELETE CASCADE; replaces a unique constraint with a composite index on project_invitations; updates schema snapshot and migration journal.
CodeSandbox provider SDK v2 migration
packages/code-provider/package.json, packages/code-provider/src/providers/codesandbox/index.ts, packages/code-provider/src/providers/codesandbox/utils/list-files.ts, .../utils/read-file.ts, .../utils/utils.ts, .../utils/write-file.ts
Bumps @codesandbox/sdk to ^2.1.0 and adds @codesandbox/pitcher-client; replaces WebSocketSession/SandboxBrowserSession with SandboxSession/SandboxClient across provider and utils; adjusts public types (getSession return, CreateSession output, FileWatcher ctor); uses sandbox.createSession and validates session existence.
Web client session typing
apps/web/client/src/app/projects/import/local/_context/index.tsx, apps/web/client/src/components/store/editor/sandbox/session.ts
Adds type-only SandboxSession imports and casts session results to SandboxSession to align with provider changes; no runtime logic changes.
Constants update
packages/constants/src/csb.ts
Updates SandboxTemplates IDs for BLANK and EMPTY_NEXTJS to a new common template ID; structure unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as UI
  participant Provider as CodesandboxProvider
  participant SDK as SandboxClient (SDK v2)
  participant SB as Sandbox

  UI->>Provider: createSession(project)
  Provider->>SB: sandbox.createSession(projectSpec)
  SB-->>Provider: SandboxSession
  Note right of Provider: Validate session exists<br/>(throws if null)
  Provider->>SDK: connect(session)
  SDK-->>Provider: connected client
  Provider-->>UI: SandboxSession (SDK v2)

  rect rgba(230,245,255,0.5)
    note over UI,SDK: File operations via SandboxClient
    UI->>Provider: readFile/writeFile/listFiles
    Provider->>SDK: fs.readTextFile/fs.readFile/fs.writeFile
    SDK-->>Provider: result
    Provider-->>UI: result
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

A rabbit taps keys with a twitch of delight,
New sessions hop in with SDK light.
Feedback burrows safely under RLS trees,
Tags sprout on projects with database ease.
Templates align, IDs in a row—
Thump-thump! To prod we merrily go. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/upgrade-csb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@supabase
Copy link

supabase bot commented Aug 31, 2025

Updates to Preview Branch (chore/upgrade-csb) ↗︎

Deployments Status Updated
Database Sun, 31 Aug 2025 23:00:16 UTC
Services Sun, 31 Aug 2025 23:00:16 UTC
APIs Sun, 31 Aug 2025 23:00:16 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Sun, 31 Aug 2025 23:00:26 UTC
Migrations Sun, 31 Aug 2025 23:00:28 UTC
Seeding Sun, 31 Aug 2025 23:00:28 UTC
Edge Functions Sun, 31 Aug 2025 23:00:31 UTC

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/client/src/app/projects/import/local/_context/index.tsx (1)

135-156: Ensure provider is always destroyed on failures (avoid session/file-handle leaks)

If upload/setup throws before Line 156, destroy() is skipped. Move destroy() to finally.

Apply:

-            const provider = await createCodeProviderClient(CodeProvider.CodeSandbox, {
+            let provider: Provider | null = await createCodeProviderClient(CodeProvider.CodeSandbox, {
               /* ... */
             });
 
-            await uploadToSandbox(projectData.files, provider);
-            await provider.setup({});
-            await provider.destroy();
+            await uploadToSandbox(projectData.files, provider);
+            await provider.setup({});
             /* ... */
         } catch (error) {
             console.error('Error creating project:', error);
             setError('Failed to create project');
             return;
         } finally {
             setIsFinalizing(false);
+            try {
+                // Best-effort cleanup
+                // provider may be null if creation failed early
+                const p = (typeof provider !== 'undefined' ? provider : null) as Provider | null;
+                if (p) await p.destroy();
+            } catch {}
         }

Also applies to: 176-178

♻️ Duplicate comments (1)
apps/backend/supabase/migrations/meta/0017_snapshot.json (1)

322-406: Snapshot reflects feedbacks with RLS and no policies; align with access plan.
Mirror of the SQL migration; ensure policies exist if clients need direct access. Otherwise, confirm all writes go through service role.

🧹 Nitpick comments (18)
apps/backend/supabase/migrations/0017_small_xavin.sql (6)

2-12: Feedbacks table: add updated_at and basic indexes.
Consider an updated_at column and indexes for common lookups.

 CREATE TABLE "feedbacks" (
   "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
   "user_id" uuid,
   "email" text,
   "message" text NOT NULL,
   "page_url" text,
   "user_agent" text,
   "attachments" jsonb DEFAULT '[]'::jsonb NOT NULL,
   "metadata" jsonb DEFAULT '{}'::jsonb NOT NULL,
   "created_at" timestamp with time zone DEFAULT now() NOT NULL
 );
+-- optional: track updates
+ALTER TABLE "feedbacks" ADD COLUMN "updated_at" timestamp with time zone DEFAULT now() NOT NULL;
+-- optional: indexes for joins and sorting
+CREATE INDEX "feedbacks_user_id_idx" ON "feedbacks" ("user_id");
+CREATE INDEX "feedbacks_created_at_idx" ON "feedbacks" ("created_at" DESC);

14-14: RLS enabled but no policies; confirm access pattern.
Without policies, client inserts/selects will be denied (service role bypasses RLS). If clients submit feedback directly, add minimal policies.

Example policies (choose per product requirements):

-- Authenticated users can insert/select their own feedback
CREATE POLICY "feedbacks_insert_own" ON feedbacks FOR INSERT
  TO authenticated WITH CHECK (user_id = auth.uid());
CREATE POLICY "feedbacks_select_own" ON feedbacks FOR SELECT
  TO authenticated USING (user_id = auth.uid());

-- If anonymous feedback is desired:
CREATE POLICY "feedbacks_insert_anon" ON feedbacks FOR INSERT TO anon WITH CHECK (true);

15-15: Dropping invitee_email+project_id uniqueness: intentional?
This allows multiple active invites per email per project. If that’s intended, fine; otherwise replace with a uniqueness rule.

Option: retain one active invite per email+project using a partial unique index (adjust predicates to match your schema):

-- example if you later add status/expiry semantics
-- CREATE UNIQUE INDEX CONCURRENTLY project_invitations_email_project_active_uq
-- ON project_invitations (invitee_email, project_id)
-- WHERE expires_at > now();

Also consider CITEXT for case-insensitive emails long-term.


16-27: FKs switched to CASCADE; add supporting indexes and confirm data hygiene.
Cascade is OK but can be expensive without indexes and will delete dependent rows; ensure that’s expected.

  • Add indexes to support FK lookups/cascades:
CREATE INDEX IF NOT EXISTS preview_domains_project_id_idx ON "preview_domains" ("project_id");
CREATE INDEX IF NOT EXISTS custom_domain_verification_project_id_idx ON "custom_domain_verification" ("project_id");
CREATE INDEX IF NOT EXISTS deployments_project_id_idx ON "deployments" ("project_id");
  • Before re-adding FKs, ensure no orphans (run on DB):
SELECT COUNT(*) FROM preview_domains p LEFT JOIN projects pr ON pr.id=p.project_id WHERE p.project_id IS NOT NULL AND pr.id IS NULL;
SELECT COUNT(*) FROM custom_domain_verification v LEFT JOIN projects pr ON pr.id=v.project_id WHERE pr.id IS NULL;
SELECT COUNT(*) FROM deployments d LEFT JOIN projects pr ON pr.id=d.project_id WHERE pr.id IS NULL;

22-23: Projects.tags: plan for querying and normalization.
If you’ll filter by tags, add a GIN index and normalize tags to lowercase/trimmed.

-- index for tag membership queries
CREATE INDEX IF NOT EXISTS projects_tags_gin_idx ON "projects" USING GIN ("tags");

1-28: Scope: DB migration bundled in a CSB upgrade PR.
Consider splitting schema changes into a dedicated PR to simplify rollout/rollback and review.

apps/backend/supabase/migrations/meta/0017_snapshot.json (2)

294-307: preview_domains.project_id is nullable while FK cascades on delete.
If a preview domain must always belong to a project, consider NOT NULL; otherwise keep nullable but note cascades won’t apply to NULLs.


881-894: deployments FK cascade recorded; add index if heavy usage.
Add deployments.project_id index to support cascades/joins (see SQL comment).

packages/code-provider/package.json (1)

34-35: No peerDependencies found; optional version pinning

  • Verified @codesandbox/sdk@^2.1.0 and @codesandbox/pitcher-client@^1.1.7 have no peerDependencies.
  • Both depend on isomorphic-ws for WebSocket support—no additional browser polyfills needed.
  • Optionally switch to ~2.1.0/~1.1.7 (or exact) to lock minor versions during migration hardening.
packages/constants/src/csb.ts (1)

8-17: Both BLANK and EMPTY_NEXTJS point to the same template ID — confirm intent and dedupe

If intentional, extract a shared constant to avoid drift when this ID changes. Also verify that this ID supports Next.js scaffolding for EMPTY_NEXTJS.

Suggested tweak:

 export const SandboxTemplates: Record<Templates, SandboxTemplate> = {
-    BLANK: {
-        id: 'pt_JQTY6AuyR5UtjDUPkE3Bsm',
+    BLANK: {
+        id: DEFAULT_TEMPLATE_ID,
         port: 3000,
     },
     EMPTY_NEXTJS: {
-        id: 'pt_JQTY6AuyR5UtjDUPkE3Bsm',
+        id: DEFAULT_TEMPLATE_ID,
         port: 3000,
     },
 };
+const DEFAULT_TEMPLATE_ID = 'pt_JQTY6AuyR5UtjDUPkE3Bsm';
packages/code-provider/src/providers/codesandbox/utils/list-files.ts (1)

1-17: Type migration to SandboxClient looks right; add contextual error handling

Wrap readdir with a catch to surface path issues with context (useful during SDK v2 rollout).

Apply:

 export async function listFiles(
     client: SandboxClient,
     { args }: ListFilesInput,
 ): Promise<ListFilesOutput> {
-    const files = await client.fs.readdir(args.path);
+    const files = await client.fs.readdir(args.path).catch((err: unknown) => {
+        const msg = err instanceof Error ? err.message : String(err);
+        throw new Error(`codesandbox.listFiles failed for path "${args.path}": ${msg}`);
+    });
 
     return {
         files: files.map((file) => ({
             name: file.name,
             type: file.type,
             isSymlink: file.isSymlink,
         })),
     };
 }
packages/code-provider/src/providers/codesandbox/utils/write-file.ts (1)

19-22: Type the catch parameter as unknown

Minor TS hygiene; avoids implicit any.

-    } catch (error) {
+    } catch (error: unknown) {
         console.error(`Error writing remote file ${normalizedPath}:`, error);
         return { success: false };
     }
packages/code-provider/src/providers/codesandbox/utils/read-file.ts (1)

31-33: Remove redundant truthiness check on Uint8Array

Uint8Array is always truthy; simplify toString for binaries.

-                toString: () => {
-                    return file.content ? convertToBase64(file.content) : '';
-                },
+                toString: () => convertToBase64(file.content),
packages/code-provider/src/providers/codesandbox/utils/utils.ts (2)

27-29: Drop noisy console.log in library code

Prefer debug-level logging or remove to avoid console noise.

-            console.log('reading image file', filePath);

22-35: Normalize file paths consistently (parity with writeFile)

readRemoteFile should normalize paths just like writeFile to avoid mismatches on platforms/callers.

-import type { SandboxClient } from '@codesandbox/sdk';
+import type { SandboxClient } from '@codesandbox/sdk';
+import { normalizePath } from '@onlook/utility';
@@
 export async function readRemoteFile(
     client: SandboxClient,
     filePath: string,
 ): Promise<SandboxFile | null> {
     try {
+        const normalizedPath = normalizePath(filePath);
-        if (isImageFile(filePath)) {
+        if (isImageFile(normalizedPath)) {
-            const content = await client.fs.readFile(filePath);
-            return getFileFromContent(filePath, content);
+            const content = await client.fs.readFile(normalizedPath);
+            return getFileFromContent(normalizedPath, content);
         } else {
-            const content = await client.fs.readTextFile(filePath);
-            return getFileFromContent(filePath, content);
+            const content = await client.fs.readTextFile(normalizedPath);
+            return getFileFromContent(normalizedPath, content);
         }
     } catch (error) {
-        console.error(`Error reading remote file ${filePath}:`, error);
+        console.error(`Error reading remote file ${filePath}:`, error);
         return null;
     }
 }
packages/code-provider/src/providers/codesandbox/index.ts (3)

160-164: Guard optional await for disconnect

Avoid awaiting a possibly-undefined promise.

-    async destroy(): Promise<void> {
-        await this.client?.disconnect();
+    async destroy(): Promise<void> {
+        if (this.client) {
+            await this.client.disconnect();
+        }
         this._client = null;
         this.sandbox = null;
     }

378-384: Clarify error message when sandbox is not initialized

The current message says "Client not initialized" but the condition checks sandbox.

-        if (!this.sandbox) {
-            throw new Error('Client not initialized');
-        }
+        if (!this.sandbox) {
+            throw new Error('Sandbox not initialized');
+        }

179-193: Consider reusing a single CodeSandbox SDK instance

You instantiate CodeSandbox multiple times (pause/stop/list). Caching one instance reduces overhead and centralizes config.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 106ec88 and fa5068e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • apps/backend/supabase/migrations/0017_small_xavin.sql (1 hunks)
  • apps/backend/supabase/migrations/meta/0017_snapshot.json (1 hunks)
  • apps/backend/supabase/migrations/meta/_journal.json (1 hunks)
  • apps/web/client/src/app/projects/import/local/_context/index.tsx (2 hunks)
  • apps/web/client/src/components/store/editor/sandbox/session.ts (3 hunks)
  • packages/code-provider/package.json (1 hunks)
  • packages/code-provider/src/providers/codesandbox/index.ts (7 hunks)
  • packages/code-provider/src/providers/codesandbox/utils/list-files.ts (1 hunks)
  • packages/code-provider/src/providers/codesandbox/utils/read-file.ts (1 hunks)
  • packages/code-provider/src/providers/codesandbox/utils/utils.ts (2 hunks)
  • packages/code-provider/src/providers/codesandbox/utils/write-file.ts (1 hunks)
  • packages/constants/src/csb.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
packages/code-provider/src/providers/codesandbox/utils/utils.ts (1)
packages/code-provider/src/providers/codesandbox/index.ts (1)
  • client (92-94)
packages/code-provider/src/providers/codesandbox/utils/read-file.ts (1)
packages/code-provider/src/providers/codesandbox/index.ts (2)
  • readFile (257-262)
  • client (92-94)
apps/web/client/src/components/store/editor/sandbox/session.ts (1)
apps/web/client/src/trpc/react.tsx (1)
  • api (23-23)
packages/code-provider/src/providers/codesandbox/utils/list-files.ts (1)
packages/code-provider/src/providers/codesandbox/index.ts (2)
  • listFiles (250-255)
  • client (92-94)
packages/code-provider/src/providers/codesandbox/utils/write-file.ts (1)
packages/code-provider/src/providers/codesandbox/index.ts (2)
  • writeFile (212-217)
  • client (92-94)
packages/code-provider/src/providers/codesandbox/index.ts (1)
packages/code-provider/src/types.ts (2)
  • CreateSessionInput (176-180)
  • CreateSessionOutput (181-181)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Supabase Preview
🔇 Additional comments (11)
apps/backend/supabase/migrations/meta/_journal.json (1)

123-130: Approve migration entry
Verified that 0017_small_xavin.sql and 0017_snapshot.json are present and the journal tag matches.

apps/backend/supabase/migrations/0017_small_xavin.sql (1)

28-28: Index addition LGTM.
Composite index on (invitee_email, project_id) is appropriate for lookup speed.

apps/backend/supabase/migrations/meta/0017_snapshot.json (1)

964-985: New invitations composite index recorded correctly.
Matches migration; no issues.

apps/web/client/src/app/projects/import/local/_context/index.tsx (1)

6-6: Type-only import is correct for bundling
This keeps the SDK type out of the runtime bundle.

apps/web/client/src/components/store/editor/sandbox/session.ts (1)

2-4: Type-only import and grouped provider import look good
This keeps runtime lean and types clear.

packages/code-provider/src/providers/codesandbox/utils/write-file.ts (1)

1-1: SDK v2 client type migration — looks good

Type-only import and parameter change to SandboxClient are consistent with the broader migration.

Also applies to: 6-6

packages/code-provider/src/providers/codesandbox/utils/read-file.ts (1)

1-1: SDK v2 client type migration — looks good

Signature now accepts SandboxClient; matches provider usage.

Also applies to: 7-7

packages/code-provider/src/providers/codesandbox/utils/utils.ts (1)

1-1: SDK v2 client type migration — looks good

Type import + param change align with other utils.

Also applies to: 23-23

packages/code-provider/src/providers/codesandbox/index.ts (3)

5-5: Adopted SDK v2 SandboxClient/SandboxSession — good migration

Imports/types align with upgraded SDK.

Also applies to: 8-8


321-332: Task lookup now awaited and validated — nice hardening

Ensures a clear error when the task is missing.


74-75: Error handling required for missing sessions

  • Wrap all createCodeProviderClient(...).initialize() invocations in try/catch to handle thrown errors when no session is found.
  • Update any direct getSession calls to gracefully handle null returns per the updated signature.

Comment on lines +1029 to +1116
"name": "projects",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "varchar",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"tags": {
"name": "tags",
"type": "varchar[]",
"primaryKey": false,
"notNull": false,
"default": "'{}'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"preview_img_url": {
"name": "preview_img_url",
"type": "varchar",
"primaryKey": false,
"notNull": false
},
"preview_img_path": {
"name": "preview_img_path",
"type": "varchar",
"primaryKey": false,
"notNull": false
},
"preview_img_bucket": {
"name": "preview_img_bucket",
"type": "varchar",
"primaryKey": false,
"notNull": false
},
"updated_preview_img_at": {
"name": "updated_preview_img_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"sandbox_id": {
"name": "sandbox_id",
"type": "varchar",
"primaryKey": false,
"notNull": true
},
"sandbox_url": {
"name": "sandbox_url",
"type": "varchar",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
},
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Projects: tags and updated_preview_img_at additions recorded; verify app usage.
Search code for tag reads/writes and preview image update flows to avoid null-handling bugs.

Run to find references:


🏁 Script executed:

#!/bin/bash
rg -nP --type=ts --type=tsx --type=sql -C2 '\b(tags|updated_preview_img_at)\b'

Length of output: 108


🏁 Script executed:

#!/bin/bash
rg -nP -C2 -g '*.ts' -g '*.tsx' -g '*.sql' '\b(tags|updated_preview_img_at)\b'

Length of output: 25921


Integrate updated_preview_img_at field
Tags support is already wired through DTOs, API routers, and UIs. However, the new updated_preview_img_at column isn’t yet:

  • Map dbProject.updated_preview_img_at into your DTO (e.g. packages/db/src/dto/project/project.ts)
  • Update this timestamp whenever preview_img_url/path/bucket are changed
  • Expose it in API responses and update your Project type (e.g. packages/models/src/project/project.ts) to avoid missing/null values
🤖 Prompt for AI Agents
In apps/backend/supabase/migrations/meta/0017_snapshot.json around lines
1029-1116, the new updated_preview_img_at column is present in the schema but
not wired through the code; update packages/db/src/dto/project/project.ts to map
dbProject.updated_preview_img_at into the Project DTO, change the
service/repository logic that updates
preview_img_url/preview_img_path/preview_img_bucket to set
updated_preview_img_at = now() whenever any of those fields change, include
updated_preview_img_at in API responses (adjust routers/controllers to return
it) and update the Project model/type (e.g.
packages/models/src/project/project.ts) so the field is present and non-nullable
as required to avoid missing/null values.

Comment on lines +143 to 148
// TODO: Make better type inference on server side
return startSandbox({
sandboxId,
userId,
});
}) as unknown as SandboxSession;
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove unsafe unknown cast; align tRPC output with SDK type or validate at runtime

Prefer returning a server-typed SandboxSession (or adapter) instead of as unknown as. If server typing can’t be changed now, add a minimal runtime guard and throw on mismatch.

Example minimal change here:

-                            // TODO: Make better type inference on server side
-                            return startSandbox({
-                                sandboxId,
-                                userId,
-                            }) as unknown as SandboxSession;
+                            // TODO: tighten server return type to SandboxSession
+                            const session = await startSandbox({ sandboxId, userId });
+                            if (!session) throw new Error('Failed to start sandbox session');
+                            return session as SandboxSession;

Optionally, add a lightweight shape check before casting (helper function outside this callback).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// TODO: Make better type inference on server side
return startSandbox({
sandboxId,
userId,
});
}) as unknown as SandboxSession;
},
// TODO: tighten server return type to SandboxSession
const session = await startSandbox({ sandboxId, userId });
if (!session) throw new Error('Failed to start sandbox session');
return session as SandboxSession;
🤖 Prompt for AI Agents
In apps/web/client/src/app/projects/import/local/_context/index.tsx around lines
143 to 148, remove the unsafe "as unknown as SandboxSession" cast and either
align the tRPC procedure return type with the SDK SandboxSession type or add a
minimal runtime shape guard before returning; implement a small helper (outside
the callback) that checks required fields/types (e.g., id, token, expiresAt or
whatever SandboxSession requires) and throw an error if the shape is invalid,
then return the value typed as SandboxSession only after the guard passes so you
avoid unsafe double-casting.

Comment on lines +32 to 34
// TODO: Make better type inference on server side
return api.sandbox.start.mutate({ sandboxId, userId }) as unknown as SandboxSession;
},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid as unknown as SandboxSession; add guard or fix API typing

Wire tRPC api.sandbox.start.mutate to return SandboxSession (server-side type), or validate the shape before casting to prevent subtle runtime failures.

Suggested tweak:

-                            // TODO: Make better type inference on server side
-                            return api.sandbox.start.mutate({ sandboxId, userId }) as unknown as SandboxSession;
+                            // TODO: Make better type inference on server side
+                            const session = await api.sandbox.start.mutate({ sandboxId, userId });
+                            if (!session) throw new Error('Failed to start sandbox session');
+                            return session as SandboxSession;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/web/client/src/components/store/editor/sandbox/session.ts around lines
32 to 34, the code force-casts api.sandbox.start.mutate(...) to SandboxSession
using "as unknown as SandboxSession"; remove this unsafe double-cast and either
(A) update the tRPC server/client types so api.sandbox.start returns the proper
SandboxSession type, or (B) perform a small runtime validation/guard after the
mutate call that checks required SandboxSession fields (ids, timestamps,
expected nested shapes) and throw or handle an error if validation fails, then
return the validated object typed as SandboxSession.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants