chore(webapp): upgrade @conform-to to v1#4044
Conversation
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe pull request upgrades 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
6a023d4 to
971ffea
Compare
e5d7cff to
f37daf8
Compare
@trigger.dev/build
trigger.dev
@trigger.dev/core
@trigger.dev/python
@trigger.dev/react-hooks
@trigger.dev/redis-worker
@trigger.dev/rsc
@trigger.dev/schema-to-json
@trigger.dev/sdk
commit: |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx (2)
142-157: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReturn blocked purchase errors in the same Conform shape the modal consumes.
PurchaseBranchesModalonly forwards fetcher payloads with astatusfield intolastResult(Lines 625-627) and only rendersamount.errors/form.errors(Lines 714-717). The plain{ ok: false, error }responses here are therefore invisible in the UI, so “plan unavailable” and “managed billing” failures become silent no-ops for the user.Possible fix
- if (purchaseBlockReason === "plan_unavailable") { - return json( - { ok: false, error: "Unable to verify billing status. Please try again." } as const, - { status: 503 } - ); - } - if (purchaseBlockReason === "managed_billing") { - return json({ ok: false, error: "Contact us to request more branches." } as const, { - status: 403, - }); - } - const submission = parseWithZod(formData, { schema: PurchaseSchema }); if (submission.status !== "success") { return json(submission.reply()); } + + if (purchaseBlockReason === "plan_unavailable") { + return json( + submission.reply({ + formErrors: ["Unable to verify billing status. Please try again."], + }), + { status: 503 } + ); + } + if (purchaseBlockReason === "managed_billing") { + return json( + submission.reply({ + formErrors: ["Contact us to request more branches."], + }), + { status: 403 } + ); + }
706-711: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winSuppress Conform’s injected default value here.
InputNumberStepperis controlled viavalue={amountValue}, sogetInputProps(amount, { type: "number", value: false })should be used to avoid Conform adding adefaultValuealongside the controlled props.Source: Learnings
🧹 Nitpick comments (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a subpath export for
tryCatchhere.This route is under
apps/webapp, so importingtryCatchfrom the@trigger.dev/coreroot regresses the repo’s package-boundary rule. Please switch this to the appropriate subpath export used elsewhere in webapp. As per coding guidelines,apps/webapp/**/*.{ts,tsx}should “Use subpath exports from@trigger.dev/corepackage instead of importing from the root@trigger.dev/corepath”.Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 39b5f328-d5fb-47ba-a21d-decdcfecff07
📒 Files selected for processing (25)
.server-changes/conform-v1.mdapps/webapp/app/components/Feedback.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsxapps/webapp/app/components/errors/ConfigureErrorAlerts.tsxapps/webapp/app/components/runs/v3/ReplayRunDialog.tsxapps/webapp/app/components/schedules/PurchaseSchedulesModal.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.concurrency/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors.$fingerprint/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.$scheduleParam/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.general/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.integrations/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings._index/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.team/route.tsx
✅ Files skipped from review due to trivial changes (1)
- .server-changes/conform-v1.md
🚧 Files skipped from review as they are similar to previous changes (19)
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.$scheduleParam/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors.$fingerprint/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections.new/route.tsx
- apps/webapp/app/components/Feedback.tsx
- apps/webapp/app/components/errors/ConfigureErrorAlerts.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.integrations/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
- apps/webapp/app/components/schedules/PurchaseSchedulesModal.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.concurrency/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.general/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts.new/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings._index/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables.new/route.tsx
- apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.team/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (38)
- GitHub Check: internal / 🧪 Unit Tests: Internal (4, 12)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 10)
- GitHub Check: internal / 🧪 Unit Tests: Internal (12, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (2, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (11, 12)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 10)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 10)
- GitHub Check: internal / 🧪 Unit Tests: Internal (10, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (3, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (8, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (9, 12)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 10)
- GitHub Check: internal / 🧪 Unit Tests: Internal (7, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (1, 12)
- GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 10)
- GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
- GitHub Check: internal / 🧪 Unit Tests: Internal (5, 12)
- GitHub Check: internal / 🧪 Unit Tests: Internal (6, 12)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: sdk-compat / Deno Runtime
- GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
- GitHub Check: sdk-compat / Bun Runtime
- GitHub Check: sdk-compat / Cloudflare Workers
- GitHub Check: packages / 🧪 Unit Tests: Packages (1, 3)
- GitHub Check: packages / 🧪 Unit Tests: Packages (2, 3)
- GitHub Check: packages / 🧪 Unit Tests: Packages (3, 3)
- GitHub Check: typecheck / typecheck
- GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Build and publish previews
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use zod for validation in packages/core and apps/webapp
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use function declarations instead of default exports
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
apps/webapp/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
apps/webapp/**/*.{ts,tsx}: Access environment variables through theenvexport ofenv.server.tsinstead of directly accessingprocess.env
Use subpath exports from@trigger.dev/corepackage instead of importing from the root@trigger.dev/corepathUse named constants for sentinel/placeholder values (e.g.
const UNSET_VALUE = '__unset__') instead of raw string literals scattered across comparisons
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
apps/webapp/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)
Only use
useCallback/useMemofor context provider values, expensive derived data that is a dependency elsewhere, or stable refs required by a dependency array. Don't wrap ordinary event handlers or trivial computations
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}: Usepnpm run typecheckfor changes in apps (apps/*) and internal packages (internal-packages/*), and never usebuildto verify those changes.
Use Vitest for tests, and never mock anything; use testcontainers instead.
Prefer static imports over dynamicimport(), and only use dynamic imports for unresolved circular dependencies, genuine code-splitting needs, or conditional runtime loading.
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs,md,mdx}
📄 CodeRabbit inference engine (CLAUDE.md)
Always import from
@trigger.dev/sdkwhen writing Trigger.dev tasks; never use@trigger.dev/sdk/v3or deprecatedclient.defineJob.
Files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
🧠 Learnings (17)
📚 Learning: 2026-02-03T18:27:40.429Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:40.429Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (e.g., Edit with PencilSquareIcon) in the TableCellMenu are intentionally icon-only with no text labels as a compact UI pattern. This is a deliberate design choice for this route; preserve the icon-only behavior for consistency in this file.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-05-18T08:21:27.694Z
Learnt from: d-cs
Repo: triggerdotdev/trigger.dev PR: 3632
File: apps/webapp/sentry.server.ts:4-21
Timestamp: 2026-05-18T08:21:27.694Z
Learning: When handling Prisma error P1001 ("Can't reach database server") in TypeScript, don’t assume a single error shape. Prisma can surface P1001 via two different error classes/fields: `PrismaClientKnownRequestError` exposes it as `err.code === "P1001"` (common during mid-query connection drops), while `PrismaClientInitializationError` exposes it as `err.errorCode === "P1001"` (common on client startup failure). Therefore, predicates should use `err.code === "P1001" || err.errorCode === "P1001"`. Do not flag `err.code === "P1001"` as “unreachable/never matches,” as it is expected in production.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-05-18T08:21:27.694Z
Learnt from: d-cs
Repo: triggerdotdev/trigger.dev PR: 3632
File: apps/webapp/sentry.server.ts:4-21
Timestamp: 2026-05-18T08:21:27.694Z
Learning: When handling Prisma errors for P1001 ("Can't reach database server"), do not assume it only appears under a single property name. Prisma may surface P1001 via either `PrismaClientKnownRequestError` (`err.code === "P1001"`, e.g., mid-query connection drops) or `PrismaClientInitializationError` (`err.errorCode === "P1001"`, e.g., client startup connection failure). To reliably detect the condition, check `err.code === "P1001" || err.errorCode === "P1001"`, and avoid review rules that would incorrectly flag `err.code === "P1001"` as unreachable/never-matching.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-13T19:53:13.759Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3937
File: packages/trigger-sdk/skills/realtime-and-frontend/SKILL.md:258-260
Timestamp: 2026-06-13T19:53:13.759Z
Learning: When reviewing code that uses `trigger.dev/react-hooks`’s `useRealtimeRun`, preserve the call signature where the first argument is the full realtime handle object (not `handle.id`). This is intentional to maintain type-safety and is consistent with the official docs; do not suggest changing the first argument from the handle object to `handle.id`.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-17T17:13:49.929Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3948
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx:48-62
Timestamp: 2026-06-17T17:13:49.929Z
Learning: In triggerdotdev/trigger.dev, within `dashboardLoader`/`dashboardAction` (or similar context resolver code) whenever you resolve an organization ID from an organization slug for RBAC/enterprise authorization scope, always read from the primary Prisma client (`prisma`), not `$replica`. Using `$replica` can hit replica-lag and cause the RBAC lookup/authorization to run without the correct org scope (bypassing intended role enforcement). Implement the slug→org lookup with `prisma.organization.findFirst(...)` (or equivalent primary-client query) and add an inline comment documenting why the primary client is required (replica lag could lead to unscoped RBAC checks).
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-23T13:04:21.413Z
Learnt from: carderne
Repo: triggerdotdev/trigger.dev PR: 4023
File: apps/webapp/app/services/upsertBranch.server.ts:14-18
Timestamp: 2026-06-23T13:04:21.413Z
Learning: In TypeScript, it’s valid to `import { type X }` and then use `typeof X` in a type-only position, e.g. `type Alias = z.infer<typeof X>`. The `type` modifier suppresses the runtime import, but the type checker still has the full exported type so `z.infer<typeof X>` can resolve correctly. In code reviews, don’t flag this as a TypeScript compile error as long as `typeof X` is used in a type context (e.g., with `z.infer`, `type` aliases, generics), not as a runtime value.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-04-02T19:18:26.255Z
Learnt from: samejr
Repo: triggerdotdev/trigger.dev PR: 3319
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions/route.tsx:179-189
Timestamp: 2026-04-02T19:18:26.255Z
Learning: In this repo’s route components that render the Inspector `ResizablePanelGroup` panels, it’s acceptable to pass `collapsed={!isShowingInspector}` together with a no-op `onCollapseChange={() => {}}` when panel visibility is intentionally controlled only by route parameters (e.g., `*Param` search/route params) rather than user drag/collapse interactions. Do not flag an empty/no-op `onCollapseChange` as “missing wiring” in these cases; only flag it when collapse state is expected to change based on user interaction.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
📚 Learning: 2026-05-12T21:04:00.184Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3542
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.sessions._index/route.tsx:40-42
Timestamp: 2026-05-12T21:04:00.184Z
Learning: In triggerdotdev/trigger.dev route loader implementations (Remix `route.tsx` files under `apps/webapp/app/routes/**`), follow the existing convention for missing/unauthorized environment lookups: when `findEnvironmentBySlug` (or the equivalent env resolver) returns a falsy value, handle it by throwing `new Error("Environment not found")` rather than returning a `404` `Response` (i.e., do not flag this as “missing 404 response”). Changing the error-to-404 convention is a cross-cutting refactor and should be left out of individual PRs unless the PR explicitly addresses that broader migration.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
📚 Learning: 2026-05-08T21:00:20.973Z
Learnt from: samejr
Repo: triggerdotdev/trigger.dev PR: 3538
File: apps/webapp/app/components/primitives/Resizable.tsx:60-78
Timestamp: 2026-05-08T21:00:20.973Z
Learning: In the triggerdotdev/trigger.dev codebase, treat Zod as a boundary validation tool (API handlers, request/response validation, and storage/DB read/write validation), not as inline render-time validation inside React components/primitive UI code. For render-time guards, prefer small manual type-narrowing checks (e.g., a short predicate like ~10–20 lines) over importing Zod into UI primitives, to avoid per-render schema-parse overhead and unnecessary abstraction. Use the manual guard approach unless you truly need schema validation at a boundary; only then introduce Zod.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-25T18:21:55.847Z
Learnt from: carderne
Repo: triggerdotdev/trigger.dev PR: 4039
File: apps/webapp/app/routes/invite-resend.tsx:0-0
Timestamp: 2026-06-25T18:21:55.847Z
Learning: In the triggerdotdev/trigger.dev Zod 4 migration, avoid importing from the root package `conform-to/zod` in webapp code. It can resolve to the Zod 3 build and may crash at module load under Zod 4. When reviewing TypeScript/TSX files in `apps/webapp`, prefer importing from the Zod 4 subpath `conform-to/zod/v4` for Zod 4-compatible schemas/types.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-05-12T21:04:05.815Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3542
File: apps/webapp/app/components/sessions/v1/SessionStatus.tsx:1-3
Timestamp: 2026-05-12T21:04:05.815Z
Learning: In this Remix + TypeScript codebase, do not flag a server/client boundary violation when a file imports only types from a module matching `*.server`.
Specifically, it’s safe to import types using `import type { Foo } from "*.server"` or `import { type Foo } from "*.server"` because TypeScript erases type-only imports at compile time and they emit no JavaScript, so they won’t cross the Remix server/client bundle boundary.
Only raise the boundary concern for value imports (e.g., `import { Foo }` without `type`, or `import Foo`), since those produce JavaScript output.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-25T18:21:51.905Z
Learnt from: carderne
Repo: triggerdotdev/trigger.dev PR: 4039
File: apps/webapp/app/routes/invite-revoke.tsx:0-0
Timestamp: 2026-06-25T18:21:51.905Z
Learning: During the Zod v4 migration in the triggerdotdev/trigger.dev webapp, ensure any imports from `conform-to/zod` use the Zod-4 subpath: `conform-to/zod/v4` (e.g., `import { parseWithZod } from "conform-to/zod/v4"`). Do not import from the package root `conform-to/zod`, because it is the Zod 3 implementation and may load Zod-3-only symbols (e.g., `ZodBranded`, `ZodEffects`), which can throw at module load (notably with `zod4.4.3`). This should be enforced across `apps/webapp/**/*` where helpers like `parseWithZod` and `conformZodMessage` are used.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-06-25T18:21:54.729Z
Learnt from: carderne
Repo: triggerdotdev/trigger.dev PR: 4039
File: apps/webapp/app/routes/confirm-basic-details.tsx:0-0
Timestamp: 2026-06-25T18:21:54.729Z
Learning: For Remix + TypeScript files that use Conform v1 (conform-to/react) and its getInputProps helper, when you intend to suppress the helper-provided default value for non-checkbox/non-radio inputs (e.g., hidden inputs managed via an explicit value prop), use the Conform v1 option key `value: false`. Do not recommend `defaultValue: false` here, because `defaultValue` is not a valid option key for these input types in Conform v1 typings.
Applied to files:
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
📚 Learning: 2026-04-16T14:21:15.229Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3368
File: apps/webapp/app/components/logs/LogsTaskFilter.tsx:135-163
Timestamp: 2026-04-16T14:21:15.229Z
Learning: When rendering lists of task registry items in apps/webapp (e.g., <SelectItem /> rows) and using `key={item.slug}`, do not flag it as potentially non-unique. In trigger.dev’s `TaskIdentifier` table, the DB constraint `@unique([runtimeEnvironmentId, slug])` guarantees `slug` is unique within a given runtime environment, so `item.slug` is safe as the React key as long as the list is derived from that registry/constraint (and not from a legacy query that could produce duplicate slugs).
Applied to files:
apps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx
🔇 Additional comments (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx (1)
90-92: 🔒 Security & PrivacyVerify the auth-scope org lookup stays on primary Prisma.
These
dashboardLoader/dashboardActioncontext resolvers feed RBAC scope fromresolveOrgIdFromSlug(...), but the provided file does not show whether that helper reads via primaryprismaor a replica. Please confirm it uses the primary client and consider an inline comment here documenting the replica-lag risk, since a stale slug→org lookup can leave authorization unscoped. Based on learnings, org-slug resolution insidedashboardLoader/dashboardActionmust use primaryprismafor RBAC scope because replica lag can bypass intended role enforcement.Also applies to: 205-207
Source: Learnings
apps/webapp/app/components/billing/BillingLimitConfigSection.tsx (1)
123-127: 🎯 Functional CorrectnessNo issue here.
CheckboxWithLabelsyncs its internal checked state fromdefaultChecked, so this checkbox followscancelInProgressRunsupdates.> Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx (2)
142-157: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReturn blocked purchase errors in the same Conform shape the modal consumes.
PurchaseBranchesModalonly forwards fetcher payloads with astatusfield intolastResult(Lines 625-627) and only rendersamount.errors/form.errors(Lines 714-717). The plain{ ok: false, error }responses here are therefore invisible in the UI, so “plan unavailable” and “managed billing” failures become silent no-ops for the user.Possible fix
- if (purchaseBlockReason === "plan_unavailable") { - return json( - { ok: false, error: "Unable to verify billing status. Please try again." } as const, - { status: 503 } - ); - } - if (purchaseBlockReason === "managed_billing") { - return json({ ok: false, error: "Contact us to request more branches." } as const, { - status: 403, - }); - } - const submission = parseWithZod(formData, { schema: PurchaseSchema }); if (submission.status !== "success") { return json(submission.reply()); } + + if (purchaseBlockReason === "plan_unavailable") { + return json( + submission.reply({ + formErrors: ["Unable to verify billing status. Please try again."], + }), + { status: 503 } + ); + } + if (purchaseBlockReason === "managed_billing") { + return json( + submission.reply({ + formErrors: ["Contact us to request more branches."], + }), + { status: 403 } + ); + }
706-711: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winSuppress Conform’s injected default value here.
InputNumberStepperis controlled viavalue={amountValue}, sogetInputProps(amount, { type: "number", value: false })should be used to avoid Conform adding adefaultValuealongside the controlled props.Source: Learnings
🧹 Nitpick comments (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx (1)
4-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a subpath export for
tryCatchhere.This route is under
apps/webapp, so importingtryCatchfrom the@trigger.dev/coreroot regresses the repo’s package-boundary rule. Please switch this to the appropriate subpath export used elsewhere in webapp. As per coding guidelines,apps/webapp/**/*.{ts,tsx}should “Use subpath exports from@trigger.dev/corepackage instead of importing from the root@trigger.dev/corepath”.Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 39b5f328-d5fb-47ba-a21d-decdcfecff07
📒 Files selected for processing (25)
.server-changes/conform-v1.mdapps/webapp/app/components/Feedback.tsxapps/webapp/app/components/billing/BillingAlertsSection.tsxapps/webapp/app/components/billing/BillingLimitConfigSection.tsxapps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsxapps/webapp/app/components/errors/ConfigureErrorAlerts.tsxapps/webapp/app/components/runs/v3/ReplayRunDialog.tsxapps/webapp/app/components/schedules/PurchaseSchedulesModal.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.concurrency/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors.$fingerprint/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.$scheduleParam/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.general/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.integrations/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings._index/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections.new/route.tsxapps/webapp/app/routes/_app.orgs.$organizationSlug.settings.team/route.tsx
✅ Files skipped from review due to trivial changes (1)
- .server-changes/conform-v1.md
🚧 Files skipped from review as they are similar to previous changes (19)
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.$scheduleParam/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.errors.$fingerprint/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.invite/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.private-connections.new/route.tsx
- apps/webapp/app/components/Feedback.tsx
- apps/webapp/app/components/errors/ConfigureErrorAlerts.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.integrations/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx
- apps/webapp/app/components/schedules/PurchaseSchedulesModal.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.concurrency/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings.general/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts.new/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings._index/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables.new/route.tsx
- apps/webapp/app/components/runs/v3/ReplayRunDialog.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.team/route.tsx
- apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.test.tasks.$taskParam/route.tsx
📜 Review details
🔇 Additional comments (2)
apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx (1)
90-92: 🔒 Security & PrivacyVerify the auth-scope org lookup stays on primary Prisma.
These
dashboardLoader/dashboardActioncontext resolvers feed RBAC scope fromresolveOrgIdFromSlug(...), but the provided file does not show whether that helper reads via primaryprismaor a replica. Please confirm it uses the primary client and consider an inline comment here documenting the replica-lag risk, since a stale slug→org lookup can leave authorization unscoped. Based on learnings, org-slug resolution insidedashboardLoader/dashboardActionmust use primaryprismafor RBAC scope because replica lag can bypass intended role enforcement.Also applies to: 205-207
Source: Learnings
apps/webapp/app/components/billing/BillingLimitConfigSection.tsx (1)
123-127: 🎯 Functional CorrectnessNo issue here.
CheckboxWithLabelsyncs its internal checked state fromdefaultChecked, so this checkbox followscancelInProgressRunsupdates.> Likely an incorrect or invalid review comment.
🛑 Comments failed to post (2)
apps/webapp/app/components/billing/BillingAlertsSection.tsx (1)
171-190: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail file='apps/webapp/app/components/billing/BillingAlertsSection.tsx' echo '--- outline ---' ast-grep outline "$file" --view expanded || true echo '--- relevant lines around form setup ---' sed -n '150,230p' "$file" echo '--- relevant lines around render of email fields ---' sed -n '320,390p' "$file" echo '--- search for form reset / keying / reinit ---' rg -n 'reset|reinit|reinitialize|key=' "$file"Repository: triggerdotdev/trigger.dev
Length of output: 6629
🌐 Web query:
Conform useForm defaultValue change rerender field list reset insert placeholder rows💡 Result:
In React Hook Form, resetting a form containing a useFieldArray after changing defaultValues involves careful management of form state to ensure field lists update and placeholders or new rows render correctly. To correctly reset a field array with new default values, you should invoke the reset method provided by the useForm hook [1][2]. When you call reset with a new object, React Hook Form updates the internal form state, which triggers a re-render of the field array [2]. Key considerations for this process include: 1. Use Reset for Default Value Changes: The reset API is the recommended way to update the form's default values [1][3]. When using useFieldArray, calling reset({ fieldArrayName: newValues }) ensures the library re-initializes the field array with the new data [2]. This process effectively replaces the current field list and ensures that any mapped components (such as rows with inputs or placeholders) reflect the new state [2]. 2. Handling Controlled Components: If you are using Controller components, it is essential to ensure that defaultValues are either provided at the form level in useForm or passed explicitly to the reset call [1][2]. Failing to provide consistent default values can lead to stale data remaining in the inputs after a reset, particularly with field arrays [4]. 3. Managing Rerenders and Field Lists: Invoking reset will cause a full re-render of the form state [2]. If you notice performance issues or unnecessary re-renders in larger forms, verify that your field array components are properly memoized and that the field array names (e.g., test.${index}.firstName) remain stable [5][6]. 4. Avoiding Manual Manipulation: Avoid trying to mutate the defaultValues object directly, as this can lead to unpredictable behavior where the form state and the UI get out of sync [4][7]. Instead, treat the form state as immutable and rely on the reset method to apply updates [3][2]. If you are inserting placeholder rows dynamically, you can use the append or prepend methods from useFieldArray to add items [5]. If you need to wipe existing data and start fresh with a specific set of rows, reset is the appropriate tool, as it clears the existing subscriptions and re-registers inputs based on the new array provided [2]. If specific inputs are failing to clear, verify that you are not encountering design limitations related to shouldUnregister, which can sometimes interfere with how fields are re-registered during a reset [7].
Citations:
- 1: https://www.react-hook-form.com/api/useform/reset
- 2: https://react-hook-form.com/docs/useform/reset
- 3: https://react-hook-form.com/docs/useform
- 4: react-hook-form/react-hook-form#1267
- 5: https://react-hook-form.com/docs/usefieldarray
- 6: react-hook-form/react-hook-form#12198
- 7: react-hook-form/react-hook-form#8758
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- search for useForm + reset/key patterns in webapp ---' rg -n 'useForm<|getFormProps\(form\)|form\.reset\(|useForm\(' apps/webapp -g '*.{ts,tsx}' | sed -n '1,200p' echo '--- search for conform package references ---' rg -n '`@conform-to/react`|`@conform-to/zod`|parseWithZod' apps/webapp -g '*.{ts,tsx}' | sed -n '1,200p'Repository: triggerdotdev/trigger.dev
Length of output: 36882
🌐 Web query:
Conform getFieldList useForm field array defaultValue reset insert remove documentation💡 Result:
In React Hook Form, the useFieldArray hook is the standard tool for managing dynamic lists of form fields [1][2]. There is no official function called getFieldList; if you need to access field states, the getFieldState method from the useForm hook is the appropriate API [3]. Key Concepts and APIs: 1. useFieldArray: This hook accepts a control object (from useForm) and a name (the path to the array in your form values) [1][4]. It returns a fields array (containing your data plus a unique id for each item) and mutation methods [1][4]. 2. Array Mutation Methods: - append: Adds one or multiple items to the end of the array [4][2]. - insert: Inserts one or multiple items at a specific index [4][2]. - remove: Removes an item at a specific index, or all items if no index is provided [1][4]. - prepend, swap, move, update, and replace are also available for comprehensive array manipulation [4][2]. 3. Default Values and Resetting: - Initial values are set via the defaultValues property in useForm [5][6]. - The reset method from useForm can be used to update or reset the entire form state, including field arrays [6][7]. When resetting a form with a field array, it is recommended to provide the full structure of the default values to ensure all fields are correctly synchronized [6][7]. - Note: Be cautious when using append or insert with empty objects if default values are defined; React Hook Form treats undefined values as a fallback to your configured defaultValues [8]. 4. Accessing State: - Use getFieldState(name) to retrieve the state (isDirty, isTouched, invalid, error) of a specific field [3]. For implementation, always use the item.id generated by useFieldArray as the React key for your field components to prevent re-render issues [4][9]. Top results: [1], [4], [5], [6]
Citations:
- 1: https://react-hook-form.com/docs/usefieldarray
- 2: https://deepwiki.com/react-hook-form/react-hook-form/5-usefieldarray-hook
- 3: https://www.react-hook-form.com/api/useform/getfieldstate
- 4: https://www.react-hook-form.com/api/usefieldarray/
- 5: https://www.react-hook-form.com/api/useform
- 6: https://www.react-hook-form.com/api/useform/reset
- 7: https://react-hook-form.com/docs/useform/reset
- 8: react-hook-form/react-hook-form#7685
- 9: https://github.com/react-hook-form/react-hook-form/blob/master/src/useFieldArray.ts
🏁 Script executed:
#!/bin/bash set -euo pipefail file='apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.alerts.new/route.tsx' sed -n '220,270p' "$file"Repository: triggerdotdev/trigger.dev
Length of output: 1640
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- BillingAlertsSection props and submit flow ---' sed -n '1,140p' apps/webapp/app/components/billing/BillingAlertsSection.tsx echo sed -n '230,430p' apps/webapp/app/components/billing/BillingAlertsSection.tsx echo '--- who renders BillingAlertsSection ---' rg -n 'BillingAlertsSection' apps/webapp -g '*.{ts,tsx}' echo '--- billing alerts route action that changes saved emails ---' sed -n '200,280p' apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsxRepository: triggerdotdev/trigger.dev
Length of output: 12170
🏁 Script executed:
#!/bin/bash set -euo pipefail echo '--- billing components with reset or prop-driven reinit ---' rg -n 'form\.reset\(|defaultValue:|useEffect\(\(\) => \{|useEffect\([^)]*\[.*saved|alertsResetRequested' apps/webapp/app/components/billing -g '*.{ts,tsx}' echo '--- BillingLimitConfigSection relevant slice ---' sed -n '140,230p' apps/webapp/app/components/billing/BillingLimitConfigSection.tsx echo '--- BillingLimitRecoveryPanel relevant slice ---' sed -n '60,170p' apps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsxRepository: triggerdotdev/trigger.dev
Length of output: 9456
🏁 Script executed:
#!/bin/bash set -euo pipefail file='apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx' echo '--- usage of BillingAlertsSection ---' rg -n 'BillingAlertsSection|alertsResetRequested|alerts=' "$file" echo '--- surrounding render block ---' sed -n '520,590p' "$file" echo '--- action/loader slices around billing alerts save ---' sed -n '200,260p' "$file" sed -n '300,360p' "$file"Repository: triggerdotdev/trigger.dev
Length of output: 6511
🌐 Web query:
@conform-to/react useForm defaultValue change field list reset getFieldList Conform💡 Result:
In the Conform library for React, changing the defaultValue of the useForm hook does not automatically reset existing field lists because Conform maintains its internal state independent of external changes to props [1]. To update the form and reset field lists effectively when defaultValue changes, you must ensure that Conform recognizes the update or remounts the components [1]. Key methods to handle this include: 1. Changing the form id or key: You can pass a unique id or key to the useForm hook [2][3]. When this value changes, Conform will automatically reset the form to its initial state, which is the most reliable way to handle a full reset when dependencies like defaultValue update [2][3]. 2. Using the reset intent: You can trigger a reset programmatically using the reset intent provided by Conform [4]. This can be done via a button or by calling form.reset [4][5]. If you need to reset a specific field list, you can pass the name of that field to the reset intent [4]. 3. React 19/Next.js 15 Considerations: In newer versions of React, form elements may automatically reset after server actions, which can conflict with Conform's state management [6][5][7]. If your form is unexpectedly resetting, you may need to prevent the native browser reset event using an event listener [6]: useEffect( => { const handleReset = (event: Event) => { if (event.target === document.forms.namedItem(form.id)) { event.preventDefault; } }; document.addEventListener('reset', handleReset, true); return => document.removeEventListener('reset', handleReset, true); }, [form.id]); To access and manage list fields, use the getFieldList method on the field metadata [8][9]. This returns an array of field objects that you can map over [8]. Each object contains metadata (like key, name, and initialValue) that should be used to correctly bind the input fields to Conform [8][4]. If you find that the list itself is not re-rendering after an update, explicitly using the key property provided by each item in getFieldList (e.g., key={item.key}) is essential for React to correctly remount the updated inputs [3][1].
Citations:
- 1: edmundhung/conform#129
- 2: https://conform.guide/api/react/useForm
- 3: https://conform.guide/api/react/future/useForm
- 4: https://conform.guide/intent-button
- 5: edmundhung/conform#606
- 6: edmundhung/conform#681
- 7: edmundhung/conform#923
- 8: https://conform.guide/complex-structures
- 9: https://conform.guide/api/react/future/useField
Reset the Conform email list when
savedEmailschanges.useFormkeeps the existing field list until the form is reset or remounted, so updating onlyemailValuesleavesemails.getFieldList()at the old length. After removing an address and saving, the UI can keep rendering stale placeholder rows. Reset the form/list on saved-email changes, or key the form by the saved email set.apps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx (1)
99-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n== file list ==\n' git ls-files 'apps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx' \ 'apps/webapp/app/**' | sed -n '1,120p' printf '\n== locate related billing action/route files ==\n' fd -a 'billing.*(route|action)|BillingLimitRecoveryPanel' apps/webapp/app printf '\n== outline target component ==\n' ast-grep outline apps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx --view expanded printf '\n== read target component slice ==\n' sed -n '1,280p' apps/webapp/app/components/billing/BillingLimitRecoveryPanel.tsx printf '\n== search for intent handling ==\n' rg -n '"billing-limit-resolve"|"billing-limit"|"billing-alerts"|intent' apps/webapp/app -g '!**/*.map' printf '\n== search for useNavigation / navigation.state in nearby billing files ==\n' rg -n 'useNavigation\(|navigation\.state|formData\?\.get\("intent"\)' apps/webapp/app/components apps/webapp/app -g '*Billing*' -g '*billing*'Repository: triggerdotdev/trigger.dev
Length of output: 33798
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n== billing-limits route outline ==\n' ast-grep outline apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx --view expanded printf '\n== route slices around action handling ==\n' sed -n '200,540p' apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx printf '\n== billing-limits page composition ==\n' sed -n '1,260p' apps/webapp/app/components/billing/BillingLimitConfigSection.tsx printf '\n---\n' sed -n '1,280p' apps/webapp/app/components/billing/BillingAlertsSection.tsxRepository: triggerdotdev/trigger.dev
Length of output: 248
🏁 Script executed:
#!/bin/bash set -euo pipefail route='apps/webapp/app/routes/_app.orgs.$organizationSlug.settings.billing-limits/route.tsx' config='apps/webapp/app/components/billing/BillingLimitConfigSection.tsx' alerts='apps/webapp/app/components/billing/BillingAlertsSection.tsx' printf '\n== billing-limits route outline ==\n' ast-grep outline "$route" --view expanded printf '\n== route slices around action handling ==\n' sed -n '200,540p' "$route" printf '\n== billing-limits config section ==\n' sed -n '1,280p' "$config" printf '\n== billing-alerts section ==\n' sed -n '1,320p' "$alerts"Repository: triggerdotdev/trigger.dev
Length of output: 34859
Scope
isSubmittingto the resolve form intent.
useNavigation()is shared across the billing-limits route, so other submits on this page can disable this button and swap its label.Suggested fix
- const isSubmitting = navigation.state === "submitting"; + const isSubmitting = + navigation.state === "submitting" && + navigation.formData?.get("intent") === "billing-limit-resolve";📝 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.const navigation = useNavigation(); const isSubmitting = navigation.state === "submitting" && navigation.formData?.get("intent") === "billing-limit-resolve";
Migrate the dashboard form layer from @conform-to 0.9 to the 1.x API. conform 1.x peer-depends on zod ^3.21 || ^4, so it runs on the current zod 3 and unblocks the zod 4 upgrade (conform 0.9 cannot bundle against zod 4, which removed ZodNativeEnum, ZodEffects, and ZodPipeline).
Address CodeRabbit feedback on the conform 1.x migration: use defaultValue (not value) on hidden inputs so they stay uncontrolled, return the env-var project-lookup failure as a form-level error, join multi-message field errors when rendering, and clone alerts.emails before using it as mutable field-list state.
The schedules and branches add-on purchase modals detected conform responses with "intent" in fetcher.data, but conform v1's submission.reply() returns a status field, not intent, so lastResult was always undefined and server-side errors never rendered. Switch the guard to "status" in fetcher.data, matching the rest of the migration.
Resolves conform v1 type errors surfaced once the @conform-to v1 upgrade was rebased onto main's newer billing-limits / dev-branches code: - billing config/recovery panels: FormMetadata has no `.ref` in v1; use a local form ref for the manual input-event dispatch - billing alerts: pass the schema generic to useForm so array fields infer string[] defaults instead of string - test task form: drop redundant explicit type="hidden" (getInputProps sets it), move the region Select `key` after the spread, add the missing getInputProps options arg, and use getFormProps for the delete form - branches purchase modal: render field.errors (v1) instead of the removed .error / .initialError
f37daf8 to
e762338
Compare
Summary
Upgrades the dashboard form layer from
@conform-to0.9 to 1.x. No behaviour change is intended; this is the conform API migration only.conform 1.x peer-depends on
zod^3.21 || ^4, so it runs on the current zod 3 and is a prerequisite for upgrading the repo to zod 4: conform 0.9 importsZodNativeEnum,ZodEffects, andZodPipeline, all removed in zod 4, so the webapp cannot build against zod 4 until conform is on 1.x. Landing this first (on zod 3) keeps the zod 4 PR focused on zod alone.Testing
Did a bunch of local smoke tests and E2E playwright tests, several rounds of different reviewers, all clean.