Skip to content

fix: non null assertion linter issues#3397

Merged
ogzhanolguncu merged 5 commits intomainfrom
linter-non-null-assertion-fix
Jul 7, 2025
Merged

fix: non null assertion linter issues#3397
ogzhanolguncu merged 5 commits intomainfrom
linter-non-null-assertion-fix

Conversation

@ogzhanolguncu
Copy link
Contributor

@ogzhanolguncu ogzhanolguncu commented Jun 20, 2025

What does this PR do?

This PR fixes non null assertion issues in our codebase.

Fixes # (issue)

If there is not an issue for this, please create one first. This is used to tracking purposes and also helps use understand why this PR exists

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • Enhancement (small improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How should this be tested?

  • Test billings, payments, subscriptions
  • Auth team switch , session refresh

Anything that matters should be tested. I didn't change anything critical, mostly added throw new Error's to check in case those assertions are actually missing.

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read Contributing Guide
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand areas
  • Ran pnpm build
  • Ran pnpm fmt
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Unkey Docs if changes were necessary

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling and validation throughout the dashboard and API, especially for missing environment variables, user IDs, organization IDs, and configuration properties.
    • Enhanced robustness by replacing forced non-null assertions with safer optional chaining and explicit runtime checks, reducing potential runtime errors.
    • Added clearer error messages, logging, and user-facing toasts for missing or invalid data in billing, authentication, integrations, and team management flows.
    • Prevented runtime errors by adding guards before critical operations like unbinding, invitation acceptance, and API deletion.
  • Refactor

    • Refactored code for better readability by extracting repeated property accesses into local variables and restructuring mapping and validation logic.
    • Updated type definitions and prop handling to allow for nullable values where appropriate, improving type safety and clarity.
    • Reformatted object constructions, function signatures, and error throwing for consistency and maintainability.
    • Improved masking logic for API keys and enhanced display of relative time labels.
  • Chores

    • Tightened linter rules to enforce safer code practices, with exceptions for test and example files.
    • Added inline comments to suppress linter warnings for intentional non-null assertions in specific scenarios.
  • Revert

    • Removed deprecated or unused components and utility hooks related to interval selection and search parameter modification.

@changeset-bot
Copy link

changeset-bot bot commented Jun 20, 2025

⚠️ No Changeset found

Latest commit: 930d9b5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Jun 20, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
dashboard ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 9:54am
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
engineering ⬜️ Ignored (Inspect) Visit Preview Jul 4, 2025 9:54am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 20, 2025

📝 Walkthrough

Walkthrough

This change set systematically removes non-null assertion operators (!) across the codebase, replacing them with safer alternatives such as optional chaining, explicit runtime checks, or type refinements. It also introduces improved error handling, validation, and code clarity in multiple modules, with some minor refactoring and deletion of unused components and utilities.

Changes

Files/Paths (Grouped) Change Summary
apps/api/src/integration/keys_updated_at_actually_updates.ts
apps/api/src/integration/sdk/create_key_with_permissions.ts
Replaced non-null assertions with optional chaining in test code; added lint-ignore comments where assertions are safe.
apps/api/src/pkg/db.ts
apps/api/src/pkg/key_migration/handler.ts
apps/api/src/pkg/middleware/metrics.ts
apps/api/src/pkg/ratelimit/client.ts
apps/api/src/pkg/ratelimit/do_client.ts
apps/api/src/pkg/util/retry.ts
Replaced non-null assertions with optional chaining or added lint-ignore comments; improved error handling and code formatting.
apps/api/src/routes/legacy_keys_createKey.ts
apps/api/src/routes/v1_keys_whoami.ts
Added lint-ignore comments for legacy non-null assertions; removed unnecessary lint directive.
apps/dashboard/app/(app)/apis/[apiId]/select.tsx
apps/dashboard/lib/searchparams.tsx
Deleted React component and utility hook for interval select and search param modification.
apps/dashboard/app/(app)/identities/page.tsx
apps/dashboard/app/(app)/layout.tsx
apps/dashboard/app/(app)/settings/team/client.tsx
apps/dashboard/app/(app)/settings/team/invitations.tsx
apps/dashboard/app/(app)/settings/team/members.tsx
Removed non-null assertions on props; used constants for defaults; improved parameter handling.
apps/dashboard/app/(app)/settings/billing/client.tsx
apps/dashboard/app/(app)/settings/billing/page.tsx
Refactored product mapping and error handling; improved formatting and validation in billing logic.
apps/dashboard/app/(app)/settings/vercel/client.tsx
apps/dashboard/app/(app)/settings/vercel/page.tsx
Added defensive checks and improved error handling for user and binding lookups; switched to date-fns for time formatting.
apps/dashboard/app/auth/actions.ts
apps/dashboard/app/auth/join/route.ts
Added explicit environment variable checks and error handling in authentication flows.
apps/dashboard/app/integrations/vercel/callback/client.tsx
apps/dashboard/app/integrations/vercel/callback/exchange-code.tsx
apps/dashboard/app/integrations/vercel/callback/page.tsx
apps/dashboard/app/integrations/vercel/callback/workspace.tsx
Added guards for missing parameters; improved error handling and validation in Vercel integration flows.
apps/dashboard/app/new/keys.tsx
apps/dashboard/app/new/page.tsx
Refined key masking logic; improved query parameter handling and added validation for required fields.
apps/dashboard/components/navbar-popover.tsx Replaced non-null assertions with optional chaining on possibly undefined objects.
apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx
apps/dashboard/components/navigation/sidebar/usage-banner.tsx
Changed prop types to allow nulls; removed non-null assertions; added explicit runtime checks and improved usage calculations.
apps/dashboard/components/navigation/sidebar/team-switcher.tsx Added validation and error handling for session data; removed non-null assertions in dependencies.
apps/dashboard/lib/auth.ts
apps/dashboard/lib/auth/server.ts
apps/dashboard/lib/auth/workos.ts
Removed non-null assertions; added explicit runtime checks and error handling in authentication providers.
apps/dashboard/lib/trpc/routers/api/delete.ts
apps/dashboard/lib/trpc/routers/key/createRootKey.ts
apps/dashboard/lib/trpc/routers/rbac.ts
apps/dashboard/lib/trpc/routers/rbac/upsertPermission.ts
apps/dashboard/lib/trpc/routers/stripe/createSubscription.ts
apps/dashboard/lib/trpc/routers/stripe/updateSubscription.ts
apps/dashboard/lib/trpc/routers/vercel.ts
apps/dashboard/lib/trpc/trpc.ts
Replaced non-null assertions with explicit checks; improved error messages and validation throughout TRPC routers.
apps/dashboard/lib/trpc/routers/authorization/roles/keys/schema-with-helpers.ts Used type predicates to refine role filtering, removing need for non-null assertions.
apps/dashboard/pages/api/v1/github/verify.ts Added explicit orgId checks and improved error handling in user retrieval logic.
apps/dashboard/providers/PostHogProvider.tsx Added lint-ignore comment for non-null assertion; reformatted prop type annotation.
apps/workflows/src/workflows/invoicing.ts Refactored to use local constants for repeated property access; removed unnecessary non-null assertion.
biome.json Set "noNonNullAssertion" rule to "error" globally, with overrides for test/tool files.
internal/clickhouse/src/keys/active_keys.ts
internal/clickhouse/src/logs.ts
internal/clickhouse/src/ratelimits.ts
internal/clickhouse/src/verifications.ts
Added explicit runtime checks for interval units before performing calculations, replacing non-null assertions.
internal/db/drizzle.config.ts Added lint-ignore comment for non-null assertion on env var.
internal/keys/src/util.ts Reformatted object construction; removed non-null assertion on property.
packages/cache/src/examples/encryption.ts
packages/cache/src/examples/namespaces.ts
packages/cache/src/examples/stale-while-revalidate.ts
packages/cache/src/examples/tiered.ts
Added lint-ignore comments for non-null assertions on environment variables; reformatted object literals for clarity.
packages/cache/src/stores/memory.ts Removed non-null assertion when accessing optional config property.
packages/cache/src/tiered.ts Used local variable for cache value; removed direct property assertion.
packages/rbac/src/queries.ts Removed non-null assertion in array push; relied on prior initialization logic.
apps/dashboard/lib/trpc/routers/key/rbac/roles/schema-with-helpers.ts Updated filtering to use type predicates for keys and permissions, removing non-null assertions and improving type safety.

Sequence Diagram(s)

No sequence diagrams generated as the changes are primarily refactoring, error handling, and type safety improvements without significant control flow modifications or new features.

Possibly related PRs

  • unkeyed/unkey#3243: Modifies the onSuccess handler of the changeWorkspace mutation in apps/dashboard/components/navigation/sidebar/team-switcher.tsx, which is also updated in this PR for validation and error handling.
  • unkeyed/unkey#2915: Refactors audit filter UI and data fetching components, related to audit log filtering improvements seen in this PR.
  • unkeyed/unkey#2843: Addresses transaction deadlocks by optimizing workspace audit log bucket ID usage, related to TRPC router improvements in this PR.

Suggested reviewers

  • perkinsjr
  • mcstepp
  • MichaelUnkey
  • chronark

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 697848a and 930d9b5.

📒 Files selected for processing (2)
  • apps/dashboard/lib/trpc/routers/key/rbac/roles/schema-with-helpers.ts (1 hunks)
  • internal/clickhouse/src/verifications.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2825
File: apps/dashboard/app/(app)/logs-v2/hooks/use-bookmarked-filters.ts:0-0
Timestamp: 2025-01-30T20:51:44.359Z
Learning: The user (ogzhanolguncu) prefers to handle refactoring suggestions in separate PRs to maintain focus in the current PR.
Learnt from: mcstepp
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/controls/components/logs-search/index.tsx:7-43
Timestamp: 2025-05-15T16:09:49.243Z
Learning: For type safety issues involving `any` type assertions, the team prefers to address these systematically with linter updates rather than fixing them individually in code reviews.
Learnt from: mcstepp
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/api-id-navbar.tsx:47-50
Timestamp: 2025-05-15T15:57:02.128Z
Learning: When reviewing code for Unkey, prefer using `Boolean()` over the double negation (`!!`) operator for boolean coercion, as their linter rules favor this pattern.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3375
File: apps/dashboard/app/(app)/settings/root-keys/components/table/hooks/use-root-keys-list-query.ts:0-0
Timestamp: 2025-06-25T20:32:10.471Z
Learning: In the Unkey codebase, ogzhanolguncu prefers strict validation with fail-fast error handling. When validation errors occur that shouldn't happen in normal operation (like invalid operators), throwing errors to crash the page is preferred over graceful error handling or console logging.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3297
File: apps/dashboard/lib/trpc/routers/authorization/roles/query.ts:210-323
Timestamp: 2025-06-04T20:13:12.060Z
Learning: The user ogzhanolguncu prefers explicit, duplicated code over abstracted helper functions when it improves readability, even if it means some duplication in filter building functions in the authorization roles query module.
apps/dashboard/lib/trpc/routers/key/rbac/roles/schema-with-helpers.ts (4)
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3324
File: apps/dashboard/app/(app)/authorization/roles/components/table/components/actions/keys-table-action.popover.constants.tsx:17-18
Timestamp: 2025-06-19T11:48:05.070Z
Learning: In the authorization roles refactor, the RoleBasic type uses `roleId` as the property name for the role identifier, not `id`. This is consistent throughout the codebase in apps/dashboard/lib/trpc/routers/authorization/roles/query.ts.
Learnt from: AkshayBandi027
PR: unkeyed/unkey#2215
File: apps/dashboard/app/(app)/@breadcrumb/authorization/roles/[roleId]/page.tsx:28-29
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In `authorization/roles/[roleId]/update-role.tsx`, the tag `role-${role.id}` is revalidated after updating a role to ensure that the caching mechanism is properly handled for roles.
Learnt from: chronark
PR: unkeyed/unkey#2693
File: apps/api/src/routes/v1_keys_updateKey.ts:350-368
Timestamp: 2024-11-29T15:15:47.308Z
Learning: In `apps/api/src/routes/v1_keys_updateKey.ts`, the code intentionally handles `externalId` and `ownerId` separately for clarity. The `ownerId` field will be removed in the future, simplifying the code.
Learnt from: chronark
PR: unkeyed/unkey#2294
File: apps/api/src/pkg/keys/service.ts:268-271
Timestamp: 2024-10-20T07:05:55.471Z
Learning: In `apps/api/src/pkg/keys/service.ts`, `ratelimitAsync` is a table relation, not a column selection. When querying, ensure that table relations are included appropriately, not as columns.
internal/clickhouse/src/verifications.ts (2)
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2810
File: internal/ui/src/components/date-time/components/time-split.tsx:10-14
Timestamp: 2025-01-22T16:51:59.978Z
Learning: The DateTime component in internal/ui/src/components/date-time/components/time-split.tsx already includes sufficient validation through handleChange and handleBlur functions, making additional runtime validation unnecessary.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2918
File: apps/dashboard/app/(app)/apis/_components/hooks/use-query-timeseries.ts:0-0
Timestamp: 2025-02-27T14:08:53.557Z
Learning: The useFetchVerificationTimeseries hook intentionally uses TIMESERIES_DATA_WINDOW * 24 to create a daily interval (24 hours) instead of the standard 1-hour interval used in other hooks.
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Test Go API Local / Test (Shard 5/8)
  • GitHub Check: Test Go API Local / Test (Shard 1/8)
  • GitHub Check: Test Go API Local / Test (Shard 4/8)
  • GitHub Check: Test Go API Local / Test (Shard 7/8)
  • GitHub Check: Test Go API Local / Test (Shard 3/8)
  • GitHub Check: Test Go API Local / Test (Shard 2/8)
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Build / Build
  • GitHub Check: Test Packages / Test ./internal/clickhouse
🔇 Additional comments (5)
internal/clickhouse/src/verifications.ts (1)

312-316: LGTM! Well-implemented runtime validation.

The explicit runtime check properly replaces the non-null assertion with fail-fast error handling. The descriptive error message including the actual invalid value and expected values will help with debugging when an unsupported interval step is encountered.

apps/dashboard/lib/trpc/routers/key/rbac/roles/schema-with-helpers.ts (4)

64-70: Excellent improvement: Type predicate filter ensures safe property access.

This type predicate filter is a much safer alternative to non-null assertions. It explicitly checks for null/undefined nested objects and refines the type accordingly, preventing runtime errors while maintaining type safety.


72-73: Safe property access after type refinement.

The properties can now be accessed safely without non-null assertions since the preceding filter ensures roleKey.key is non-null with the required shape.


79-85: Consistent and safe type predicate pattern for permissions.

The same safe filtering pattern is applied to permissions, ensuring consistency across the codebase and eliminating the need for non-null assertions on permission objects.


87-88: Safe property access maintained for permissions.

Just like with keys, the permission properties can now be accessed safely without non-null assertions after the type predicate filter ensures non-null permission objects.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai 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

Documentation and Community

  • 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.

@ogzhanolguncu ogzhanolguncu marked this pull request as ready for review June 20, 2025 12:39
@github-actions
Copy link
Contributor

github-actions bot commented Jun 20, 2025

Thank you for following the naming conventions for pull request titles! 🙏

Copy link
Contributor

@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: 9

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ca795b and 7b36769.

📒 Files selected for processing (65)
  • apps/api/src/integration/keys_updated_at_actually_updates.ts (3 hunks)
  • apps/api/src/integration/sdk/create_key_with_permissions.ts (2 hunks)
  • apps/api/src/pkg/db.ts (1 hunks)
  • apps/api/src/pkg/key_migration/handler.ts (3 hunks)
  • apps/api/src/pkg/middleware/metrics.ts (1 hunks)
  • apps/api/src/pkg/ratelimit/client.ts (1 hunks)
  • apps/api/src/pkg/ratelimit/do_client.ts (3 hunks)
  • apps/api/src/pkg/util/retry.ts (1 hunks)
  • apps/api/src/routes/legacy_keys_createKey.ts (2 hunks)
  • apps/api/src/routes/v1_keys_whoami.ts (0 hunks)
  • apps/dashboard/app/(app)/apis/[apiId]/select.tsx (0 hunks)
  • apps/dashboard/app/(app)/identities/page.tsx (2 hunks)
  • apps/dashboard/app/(app)/layout.tsx (1 hunks)
  • apps/dashboard/app/(app)/settings/billing/client.tsx (5 hunks)
  • apps/dashboard/app/(app)/settings/billing/page.tsx (2 hunks)
  • apps/dashboard/app/(app)/settings/team/client.tsx (1 hunks)
  • apps/dashboard/app/(app)/settings/team/invitations.tsx (2 hunks)
  • apps/dashboard/app/(app)/settings/team/invite.tsx (2 hunks)
  • apps/dashboard/app/(app)/settings/team/members.tsx (1 hunks)
  • apps/dashboard/app/(app)/settings/vercel/client.tsx (3 hunks)
  • apps/dashboard/app/(app)/settings/vercel/page.tsx (1 hunks)
  • apps/dashboard/app/api/webhooks/stripe/route.ts (2 hunks)
  • apps/dashboard/app/auth/actions.ts (1 hunks)
  • apps/dashboard/app/auth/join/route.ts (1 hunks)
  • apps/dashboard/app/integrations/vercel/callback/client.tsx (1 hunks)
  • apps/dashboard/app/integrations/vercel/callback/exchange-code.tsx (1 hunks)
  • apps/dashboard/app/integrations/vercel/callback/page.tsx (2 hunks)
  • apps/dashboard/app/integrations/vercel/callback/workspace.tsx (1 hunks)
  • apps/dashboard/app/new/keys.tsx (1 hunks)
  • apps/dashboard/app/new/page.tsx (4 hunks)
  • apps/dashboard/components/navbar-popover.tsx (1 hunks)
  • apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (2 hunks)
  • apps/dashboard/components/navigation/sidebar/team-switcher.tsx (2 hunks)
  • apps/dashboard/components/navigation/sidebar/usage-banner.tsx (2 hunks)
  • apps/dashboard/lib/auth.ts (1 hunks)
  • apps/dashboard/lib/auth/server.ts (1 hunks)
  • apps/dashboard/lib/auth/workos.ts (5 hunks)
  • apps/dashboard/lib/searchparams.tsx (0 hunks)
  • apps/dashboard/lib/trpc/routers/api/delete.ts (2 hunks)
  • apps/dashboard/lib/trpc/routers/authorization/roles/keys/schema-with-helpers.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/key/createRootKey.ts (2 hunks)
  • apps/dashboard/lib/trpc/routers/rbac.ts (6 hunks)
  • apps/dashboard/lib/trpc/routers/rbac/upsertPermission.ts (1 hunks)
  • apps/dashboard/lib/trpc/routers/stripe/createSubscription.ts (3 hunks)
  • apps/dashboard/lib/trpc/routers/stripe/updateSubscription.ts (2 hunks)
  • apps/dashboard/lib/trpc/routers/vercel.ts (11 hunks)
  • apps/dashboard/lib/trpc/trpc.ts (3 hunks)
  • apps/dashboard/pages/api/v1/github/verify.ts (3 hunks)
  • apps/dashboard/providers/PostHogProvider.tsx (2 hunks)
  • apps/workflows/src/workflows/invoicing.ts (9 hunks)
  • biome.json (2 hunks)
  • internal/clickhouse/src/keys/active_keys.ts (1 hunks)
  • internal/clickhouse/src/logs.ts (1 hunks)
  • internal/clickhouse/src/ratelimits.ts (1 hunks)
  • internal/clickhouse/src/verifications.ts (1 hunks)
  • internal/db/drizzle.config.ts (1 hunks)
  • internal/keys/src/util.ts (1 hunks)
  • internal/ui/src/components/button.tsx (1 hunks)
  • packages/cache/src/examples/encryption.ts (2 hunks)
  • packages/cache/src/examples/namespaces.ts (2 hunks)
  • packages/cache/src/examples/stale-while-revalidate.ts (1 hunks)
  • packages/cache/src/examples/tiered.ts (1 hunks)
  • packages/cache/src/stores/memory.ts (1 hunks)
  • packages/cache/src/tiered.ts (1 hunks)
  • packages/rbac/src/queries.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • apps/api/src/routes/v1_keys_whoami.ts
  • apps/dashboard/lib/searchparams.tsx
  • apps/dashboard/app/(app)/apis/[apiId]/select.tsx
🔇 Additional comments (101)
biome.json (2)

28-28: LGTM! Enforcing non-null assertion rule globally.

This rule enforcement will improve type safety across the codebase by preventing unsafe non-null assertions.


130-147: Well-designed overrides for the non-null assertion rule.

The overrides appropriately allow non-null assertions in test files, tools, and legacy versioned files where they might be more acceptable or necessary.

apps/api/src/pkg/middleware/metrics.ts (1)

154-154: Good removal of non-null assertion with proper null handling.

Removing the non-null assertion is correct here since key.forWorkspaceId can be null, and the function already handles null values properly with the null coalescing operator at line 163 (return val ?? "").

apps/api/src/integration/sdk/create_key_with_permissions.ts (1)

32-33: LGTM: Appropriate use of lint suppression comment.

The lint suppression comment clearly indicates this non-null assertion is intentionally kept. In test contexts where the setup controls the conditions, this approach is acceptable.

internal/keys/src/util.ts (1)

12-15: LGTM: Safer handling of optional parameter.

Removing the non-null assertion on opts.prefix is correct since it's defined as optional in the function signature. The KeyV1 constructor should handle undefined values appropriately.

apps/dashboard/providers/PostHogProvider.tsx (2)

10-11: LGTM: Appropriate handling of required environment variable.

The lint suppression comment clearly documents that this non-null assertion is intentional. For required environment variables that the application cannot function without, this approach is acceptable.


56-59: LGTM: Improved type annotation formatting.

The multi-line type annotation improves readability without changing functionality.

internal/ui/src/components/button.tsx (1)

345-349: LGTM: Defensive programming with optional chaining.

While the early guard clause if (!props.keyboard || isClickDisabled) already prevents execution when props.keyboard is undefined, using optional chaining provides additional safety and makes the code more defensive against future changes.

apps/api/src/pkg/db.ts (1)

60-60: LGTM: Safer error message access.

Using optional chaining instead of non-null assertion is more defensive. In the current logic, lastError should always be defined at this point due to the retry loop structure, but optional chaining provides additional safety.

packages/cache/src/tiered.ts (1)

52-57: Excellent refactor to improve type safety.

The extraction of res.val to a local variable val and explicit undefined check is a great improvement over the previous non-null assertion pattern. This makes the code more readable and safer while maintaining the same logic flow.

packages/cache/src/stores/memory.ts (1)

88-88: Good consistency improvement.

Removing the non-null assertion is appropriate here since the existence of unstableEvictOnSet is already validated in the outer conditional on line 73. This change improves consistency with the codebase's move away from non-null assertions.

internal/clickhouse/src/logs.ts (1)

280-284: Excellent defensive programming improvement.

The explicit runtime check with a descriptive error message is much better than the previous non-null assertion. This change prevents silent failures and makes debugging easier when an unknown interval is encountered.

packages/rbac/src/queries.ts (1)

39-39: Appropriate removal of unnecessary non-null assertion.

The non-null assertion was redundant here since lines 36-38 explicitly ensure acc[rule] exists as an array. TypeScript can infer the type safety from the explicit initialization, making this change both safe and cleaner.

apps/dashboard/app/(app)/identities/page.tsx (1)

27-27: Good defensive programming with safe fallbacks.

The removal of the non-null assertion combined with the ?? 0 fallback when passing to the Results component is a good pattern. This allows for more flexible internal handling while ensuring downstream components always receive valid numeric values.

Also applies to: 57-57

apps/dashboard/lib/trpc/routers/authorization/roles/keys/schema-with-helpers.ts (1)

45-55: Excellent use of type predicates for improved type safety!

The replacement of non-null assertions with a type predicate function is a great improvement. This approach:

  • Provides compile-time type safety by narrowing the type
  • Makes the null-filtering logic explicit and self-documenting
  • Eliminates the risk of runtime errors from non-null assertions
apps/dashboard/components/navbar-popover.tsx (1)

170-173: Verify the behavior when rowVirtualizer methods return undefined.

While optional chaining is safer than non-null assertions, in this context rowVirtualizer should always be defined when useVirtual is true. The optional chaining could potentially cause undefined behavior:

  • rowVirtualizer?.getTotalSize() could return undefined, leading to height: "undefinedpx"
  • rowVirtualizer?.getVirtualItems() could return undefined, causing the .map() call to fail

Consider adding explicit runtime checks instead:

- height: `${rowVirtualizer?.getTotalSize()}px`,
+ height: `${rowVirtualizer?.getTotalSize() ?? 0}px`,
- {rowVirtualizer?.getVirtualItems().map((virtualRow) => {
+ {(rowVirtualizer?.getVirtualItems() ?? []).map((virtualRow) => {

Or verify that the current approach handles these edge cases properly.

apps/dashboard/lib/auth/server.ts (1)

59-63: Great improvement in error handling and configuration validation.

The explicit runtime check after initialization is much safer than relying on non-null assertions. This approach:

  • Provides clear error messaging when initialization fails
  • Helps identify configuration issues more easily
  • Prevents potential runtime errors from returning null instances
apps/dashboard/app/integrations/vercel/callback/exchange-code.tsx (2)

23-28: Good optimization and safety improvement!

Caching the environment variables and adding explicit validation provides several benefits:

  • Performance: Avoids repeated calls to vercelIntegrationEnv()
  • Safety: Prevents API calls with undefined credentials
  • Debugging: Clear error message helps identify configuration issues

36-37: LGTM - Using cached environment variables.

The use of cached env values is consistent with the validation added above and improves performance.

apps/dashboard/app/new/keys.tsx (1)

84-103: LGTM! Excellent defensive programming improvements.

The explicit null/undefined checks for firstPart, prefix, and suffix remove unsafe assumptions about string splitting behavior. The fallback logic properly handles edge cases while maintaining the masking functionality.

apps/workflows/src/workflows/invoicing.ts (3)

65-68: Good refactoring for clarity and safety.

Extracting stripeCustomerId to a local constant improves readability and removes repeated property access. The explicit null check prevents potential runtime errors.


130-131: Consistent pattern for subscription property access.

Extracting subscription properties (plan, verifications, ratelimits, support) to local constants follows the same pattern as stripeCustomerId and improves code consistency.

Also applies to: 147-148, 172-173, 197-198


301-301: Safe removal of non-null assertion.

Removing the non-null assertion on tier.centsPerUnit aligns with the PR objective. The conditional check on line 292 already ensures tier.centsPerUnit is truthy before this code executes.

apps/dashboard/pages/api/v1/github/verify.ts (2)

118-123: Good defensive programming with early return.

The explicit check for ws.orgId prevents potential runtime errors when calling getUsers. The early return with a 201 status maintains the API contract while handling the edge case gracefully.


233-250: Excellent refactoring for error resilience.

The new implementation using Promise.all with individual try-catch blocks provides better concurrency and graceful error handling. Failed user fetches no longer break the entire operation, and the filtering ensures only valid users are returned.

apps/dashboard/lib/auth/workos.ts (4)

73-74: Good documentation for static property.

The comment warns about implicit external access to the static instance property, which helps prevent accidental modifications.


150-153: Explicit validation improves reliability.

Adding the explicit check for refreshResult.sealedSession with a clear error message prevents potential runtime errors and improves debugging when session refresh fails.


303-303: Comprehensive validation for organization switching.

The enhanced condition now validates all required properties (authenticated, session, and sealedSession) before proceeding, ensuring safe access to these properties.


353-354: Appropriate use of linter ignore comment.

The biome-ignore comment indicates this non-null assertion is intentionally safe, as the orgMap.get() call is guaranteed to find the organization due to the prior Promise.all construction.

apps/dashboard/app/auth/join/route.ts (1)

37-43: Good defensive programming for invitation acceptance.

The explicit check for organizationId prevents attempting to accept invitations or switch organizations when the required ID is missing. The error logging helps with debugging while maintaining the redirect flow.

apps/dashboard/lib/trpc/routers/rbac/upsertPermission.ts (1)

57-58: LGTM! Lint suppression is appropriately used here.

The non-null assertion on ctx.user!.id is likely safe in this TRPC router context, as authentication middleware typically ensures the user exists. However, consider making the comment more descriptive about why this assertion is safe (e.g., "Protected route ensures user exists").

apps/dashboard/app/(app)/layout.tsx (1)

39-39: Good improvement in null safety!

Removing the non-null assertion allows the AppSidebar component to properly handle potentially null quotas, which is safer than forcing a non-null type. This aligns well with the related component updates mentioned in the AI summary.

apps/dashboard/app/(app)/settings/team/invitations.tsx (1)

25-25: LGTM! Cleaner code by trusting the type system.

Removing the non-null assertions on organization.id makes the code cleaner and relies on the TypeScript type system. This should be safe assuming the Organization type properly defines id as a required field.

Let me verify that the Organization type has id as a required field:

#!/bin/bash
# Search for Organization type definition to confirm id is required
ast-grep --pattern 'type Organization = {
  $$$
}'

ast-grep --pattern 'interface Organization {
  $$$
}'

Also applies to: 82-82

apps/api/src/pkg/ratelimit/client.ts (1)

135-136: Lint suppression is justified by the validation logic.

The non-null assertion on res[0].val! is safe here because:

  1. The code checks res.length > 0 before accessing res[0]
  2. Previous validation ensures all results are successful (have .val)

The suppression comment could be more descriptive, but the assertion is sound given the surrounding validation logic.

packages/cache/src/examples/namespaces.ts (2)

26-29: LGTM: Appropriate lint suppressions for environment variables

The lint ignore comments are well-justified for environment variables in example code. The comment "Safe to leave" clearly indicates these are intentional non-null assertions where the developer is expected to provide the required environment variables.


65-69: LGTM: Improved code formatting

The multi-line formatting enhances readability without affecting functionality.

apps/api/src/pkg/util/retry.ts (1)

39-40: LGTM: Justified lint suppression for guaranteed non-null value

The lint ignore comment is appropriate here since the loop structure guarantees that result will be assigned at least once before reaching the return statement. The non-null assertion is safe in this context.

apps/dashboard/app/(app)/settings/team/client.tsx (1)

101-103: LGTM: Safe removal of non-null assertions

The non-null assertions are safely removed since the early return at lines 55-57 ensures that organization is defined when these lines execute. This change improves type safety without introducing runtime risks.

apps/dashboard/app/(app)/settings/team/members.tsx (1)

111-111: LGTM: Safe removal of non-null assertion

The non-null assertion is safely removed since the organization parameter is typed as Organization (non-nullable) in the component props. The TypeScript type system ensures that organization cannot be null when this component is used.

apps/dashboard/lib/auth.ts (1)

56-56: LGTM: Safe removal of non-null assertion with proper error handling

The non-null assertion is safely removed since the getAuth() function guarantees that userId will be present by redirecting to the sign-in page if it's missing (lines 31-33). The inline comment correctly documents this behavior.

packages/cache/src/examples/encryption.ts (2)

27-30: LGTM: Appropriate use of lint suppression for example code.

The biome-ignore comments are suitable for example code where environment variables are expected to be configured. However, consider adding runtime validation if this pattern is used in production code.


39-40: LGTM: Consistent lint suppression approach.

The lint suppression is consistent with the pattern used for other environment variables in this example.

apps/dashboard/app/integrations/vercel/callback/client.tsx (2)

164-167: Excellent safety improvement with clear error messaging.

The guard clause prevents potential runtime errors by validating projectId before proceeding with the mutation. The toast error provides clear feedback to the user.


170-170: Good removal of non-null assertion.

Removing the non-null assertion is safe here since the guard clause above ensures projectId is defined at this point.

apps/dashboard/app/integrations/vercel/callback/page.tsx (1)

113-113: Safe removal of non-null assertion.

The non-null assertion removal is safe since the explicit check above ensures props.searchParams.next exists.

apps/dashboard/lib/trpc/routers/stripe/createSubscription.ts (3)

19-23: Good error handling consistency.

The reformatted error throwing maintains consistency with other error handling patterns in the codebase.


39-44: Excellent validation for critical Stripe data.

This explicit validation prevents runtime errors when creating subscriptions if the Stripe product lacks a default price. The error message is descriptive and includes the product ID for debugging.


79-79: Safe removal of non-null assertion.

The non-null assertion removal is safe here since the validation above ensures product.default_price exists before this line is reached.

apps/api/src/pkg/ratelimit/do_client.ts (2)

67-68: Appropriate lint suppression for safe non-null assertion.

The lint suppression is justified here since the preceding if (res.length > 0) check ensures res[0] exists. The non-null assertion is actually safe in this context.


203-207: Good formatting improvement for readability.

The multi-line JSON object formatting improves code readability without affecting functionality.

Also applies to: 218-222

apps/dashboard/lib/trpc/routers/key/createRootKey.ts (1)

47-48: LGTM: Safe keyAuthId handling implemented correctly.

The extraction of keyAuthId to a local variable followed by explicit null checking is a good improvement over non-null assertions. This pattern prevents runtime errors and improves code readability.

Also applies to: 67-67

apps/api/src/pkg/key_migration/handler.ts (2)

23-27: LGTM: Improved readability for ConsoleLogger instantiation.

The reformatting enhances code readability while maintaining functionality.


38-38: LGTM: Proper defensive programming with nullish coalescing.

Using ?? [] ensures that inArray() always receives an array instead of potentially undefined/null values, preventing runtime errors during database queries.

Also applies to: 58-62

internal/clickhouse/src/ratelimits.ts (1)

114-118: LGTM: Excellent runtime validation for intervalUnit.

The explicit check with a descriptive error message prevents runtime errors and makes debugging easier if an unknown interval step is encountered.

internal/clickhouse/src/keys/active_keys.ts (1)

156-160: LGTM: Consistent runtime validation pattern.

The explicit validation for msPerUnit follows the same robust pattern used in other ClickHouse modules, ensuring consistent error handling across the codebase.

apps/dashboard/app/(app)/settings/vercel/page.tsx (1)

120-148: LGTM: Comprehensive error handling improvement for user fetching.

The refactored user fetching logic demonstrates excellent defensive programming:

  • Filters out falsy IDs before processing
  • Wraps async operations in try-catch blocks for graceful error handling
  • Logs errors appropriately for debugging
  • Filters out failed fetches to prevent null entries
  • Provides better fallback user names

This significantly improves the robustness and error resilience of the user data handling.

apps/dashboard/app/(app)/settings/billing/page.tsx (2)

135-135: Excellent refactoring to use dedicated mapping function.

The extraction of inline mapping logic to the mapProduct function improves code clarity and enables comprehensive validation of Stripe product data.


188-214: Outstanding defensive programming with comprehensive validation.

The mapProduct function implements robust validation at each step:

  • Validates default_price existence before use
  • Ensures price expansion rather than string references
  • Confirms unit_amount is present
  • Safely parses metadata values

This approach significantly improves error detection and prevents runtime failures compared to non-null assertions.

apps/dashboard/app/auth/actions.ts (2)

92-101: Excellent environment variable validation and error handling.

The explicit check for UNKEY_ROOT_KEY with proper error logging and user-friendly error messages significantly improves reliability. The approach maintains security by not exposing sensitive configuration details while providing clear feedback about service availability.


107-107: Good practice using cached environment variable.

Using the pre-validated unkeyRootKey variable eliminates the need for non-null assertions and ensures consistency with the earlier validation logic.

apps/dashboard/components/navigation/sidebar/app-sidebar/index.tsx (2)

32-32: Improved type safety with explicit null handling.

Changing from quotas?: Quotas to quotas: Quotas | null makes the nullable nature explicit and forces proper handling of null cases throughout the component tree.


125-125: Consistent with updated type definition.

Removing the non-null assertion aligns perfectly with the updated type signature that explicitly allows null values.

apps/dashboard/app/integrations/vercel/callback/workspace.tsx (2)

39-42: Excellent early validation with user-friendly fallback.

The explicit check for memberships?.data with error logging and fallback UI prevents potential runtime errors while maintaining a good user experience.


51-66: Comprehensive session handling with robust error recovery.

The enhanced validation and error handling significantly improves reliability:

  • Validates session data completeness before use
  • Wraps cookie operations in try-catch for graceful failure handling
  • Provides clear user feedback through toast notifications
  • Maintains proper error logging for debugging

This approach ensures the workspace switching process fails gracefully rather than throwing unhandled exceptions.

apps/dashboard/lib/trpc/routers/api/delete.ts (2)

45-52: Excellent explicit validation with informative error handling.

The explicit check for keyAuthId prevents potential runtime errors and provides a clear, actionable error message. This is much safer than relying on non-null assertions and helps identify configuration issues early.


81-89: Consistent use of validated variable eliminates assertion risks.

Using the pre-validated keyAuthId variable throughout the transaction eliminates the need for non-null assertions while maintaining the same functional behavior.

apps/dashboard/lib/trpc/routers/rbac.ts (3)

145-145: LGTM! Non-null assertion removal is safe here.

The removal of non-null assertions (!) from ctx.user.id is appropriate since these routes use the requireUser middleware, which should guarantee that ctx.user is defined. The direct access to ctx.user.id is safer than the previous forced assertion.

Also applies to: 225-225, 280-280, 358-358


813-820: Good defensive programming with explicit user validation.

The explicit check for ctx.user?.id with a proper error throw is excellent defensive programming. This ensures the function fails gracefully if somehow a user context is missing, even though the middleware should prevent this scenario.


841-841: Consistent use of validated userId variable.

Using the extracted and validated userId variable maintains consistency with the validation logic above and eliminates any possibility of accessing undefined user data.

apps/api/src/integration/keys_updated_at_actually_updates.ts (2)

19-19: Excellent improvement in test safety with optional chaining.

Replacing non-null assertions with optional chaining (?.) makes the test more robust by gracefully handling cases where database queries might return undefined. This prevents potential test failures due to runtime errors.

Also applies to: 39-40, 54-54


41-43: Appropriate use of intentional non-null assertion.

The retained non-null assertion on createdAtM with the lint ignore comment is reasonable here, as createdAtM should always be present for existing database records in this test scenario.

apps/dashboard/lib/trpc/routers/vercel.ts (1)

32-36: Improved error formatting enhances readability.

The multi-line formatting of TRPCError objects with explicit code and message properties improves code readability and maintainability. This is a good stylistic improvement.

Also applies to: 38-42, 51-55, 57-61

apps/dashboard/app/(app)/settings/vercel/client.tsx (2)

35-35: Good library choice for consistent time formatting.

Replacing the ms library with formatDistanceToNow from date-fns provides more human-readable relative time display and likely aligns better with the project's existing dependencies. The implementation properly handles the conditional display when updatedAtM might be null.

Also applies to: 300-305


380-386: Excellent defensive programming prevents runtime errors.

Adding the explicit check for props.binding before calling the mutation is excellent defensive programming. This prevents potential runtime errors if the binding becomes undefined due to race conditions or state updates, providing a better user experience with a clear error message.

apps/dashboard/components/navigation/sidebar/team-switcher.tsx (3)

57-60: Essential validation prevents invalid session handling.

Adding explicit validation for sessionData.token and sessionData.expiresAt before proceeding is crucial for preventing runtime errors. This ensures the session switching fails gracefully with a clear error message if the backend returns incomplete data.


62-78: Robust error handling with try-catch wrapper.

Wrapping the session cookie setting and cache invalidation operations in a try-catch block provides excellent error resilience. The specific error messages help with debugging, and the graceful fallback maintains a good user experience even when operations fail.


97-97: Safe dependency array without non-null assertion.

Removing the non-null assertion from the useMemo dependency array is the correct approach. The function already handles the case where userMemberships might be undefined or empty, making the assertion unnecessary and potentially unsafe.

apps/dashboard/lib/trpc/routers/stripe/updateSubscription.ts (5)

20-24: LGTM! Improved error formatting for consistency.

The multiline error structure improves readability and follows consistent formatting patterns.


72-75: Excellent safety improvement by removing non-null assertion.

The previous code used a non-null assertion on i.plan.product!, which could cause runtime errors if the product field was null or undefined. The new implementation safely handles this case with optional chaining and explicit null checks.


84-89: Good addition of explicit validation for subscription item ID.

This validation prevents potential runtime errors when calling the Stripe API with an undefined item ID, providing a clear error message for debugging.


91-96: Essential validation for product default price.

This check prevents runtime errors when calling toString() on a potentially undefined default_price field, ensuring the Stripe API call receives valid data.


98-99: Safe usage after proper validation.

The code now safely uses item.id and newProduct.default_price after explicit validation checks, eliminating the need for non-null assertions.

apps/dashboard/components/navigation/sidebar/usage-banner.tsx (3)

11-11: Good type update to handle null quotas.

Changing the prop type to Quotas | null properly reflects the actual data structure and prevents type mismatches.


21-21: Excellent addition of robust validation and error handling.

The optional chaining prevents runtime errors when accessing requestsPerMonth, and the comprehensive validation checks provide helpful debugging information while preventing the component from rendering with invalid data.

Also applies to: 23-31


33-34: Good refactoring for improved readability.

Extracting the percentage calculation and shouldUpgrade logic into variables makes the code more readable and maintainable.

apps/dashboard/lib/trpc/trpc.ts (3)

39-39: Safe replacement of non-null assertion with optional chaining.

Using ctx.user?.id instead of ctx.user!.id prevents runtime errors if the user context is unexpectedly undefined.


115-116: Improved safety in rate limiting middleware.

Extracting userId with optional chaining and checking both ratelimit and userId before proceeding prevents potential runtime errors and makes the logic more explicit.

Also applies to: 119-119


158-160: Consistent safety improvements in LLM access middleware.

The same pattern of safe user ID extraction and explicit checks ensures the middleware handles undefined user contexts gracefully.

apps/dashboard/app/(app)/settings/billing/client.tsx (2)

163-172: Excellent addition of validation for currentProductId.

This validation prevents the subscription update from proceeding with undefined currentProductId, providing clear error logging and user feedback. This is a critical safety improvement that aligns perfectly with the PR objectives.


2-2: Good formatting improvements for consistency.

The changes to import structure, return object formatting, mutation call formatting, and type annotations improve code readability and maintain consistent styling throughout the file.

Also applies to: 82-87, 173-176, 193-195, 321-324

apps/dashboard/app/new/page.tsx (3)

29-29: Good refactoring to extract search parameters.

Extracting apiId and workspaceId to local constants improves readability and reduces repeated property access throughout the function.

Also applies to: 66-66


40-43: Critical validation addition for keyAuthId.

This validation prevents runtime errors by ensuring api.keyAuthId exists before passing it to the Keys component. The error logging and 404 response provide appropriate handling for this edge case.


61-61: Safe usage after proper validation.

Now that api.keyAuthId is validated above, it can be safely used without non-null assertions, eliminating potential runtime errors.

apps/dashboard/app/(app)/settings/team/invite.tsx (4)

56-58: LGTM! Improved code formatting.

The multiline formatting improves readability without changing functionality.


68-68: Excellent replacement of non-null assertion with optional chaining.

This change aligns perfectly with the PR objective of removing risky non-null assertions. The optional chaining approach is much safer and prevents potential runtime errors.


73-78: Outstanding defensive programming with explicit validation.

The explicit check for user?.orgId with comprehensive error handling is a significant improvement over the previous non-null assertion approach. The error logging and user-friendly toast notification provide excellent developer and user experience.


79-88: Robust error handling with try-catch wrapper.

The try-catch block properly handles potential mutation failures and provides consistent error reporting. This is a substantial improvement in error resilience compared to the previous implementation.

apps/dashboard/app/api/webhooks/stripe/route.ts (4)

18-21: Excellent explicit validation for Stripe environment configuration.

The detailed error message clearly explains what's missing and helps with debugging configuration issues. This is a significant improvement over potential runtime failures from missing environment variables.


23-28: Outstanding environment variable validation with clear error messaging.

The explicit check for STRIPE_SECRET_KEY with a descriptive error message is exemplary defensive programming. This prevents potential runtime errors and provides clear guidance for fixing configuration issues.


30-30: Safe usage of validated environment variable.

Using the validated stripeSecretKey variable instead of direct environment access is the perfect complement to the validation logic above.


86-122: Exceptional comprehensive error handling and validation.

This refactoring demonstrates excellent defensive programming with:

  • Try-catch wrapper for the entire operation
  • Explicit validation of all required subscription data fields
  • Concurrent API calls for better performance (Promise.all)
  • Comprehensive validation of price and customer data
  • Proper error logging and HTTP response handling
  • Safe handling of union types (string vs object references)

The currency formatting and Slack alert integration are also well-implemented. This is a substantial improvement in robustness compared to the previous implementation.

@mcstepp mcstepp self-assigned this Jun 25, 2025
Copy link
Collaborator

@mcstepp mcstepp left a comment

Choose a reason for hiding this comment

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

👍

just had a nitpick-y question, but nothing blocking

@vercel vercel bot temporarily deployed to Preview – dashboard July 3, 2025 09:36 Inactive
@ogzhanolguncu ogzhanolguncu requested a review from mcstepp July 3, 2025 11:51
Copy link
Contributor

@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: 1

♻️ Duplicate comments (1)
apps/dashboard/app/integrations/vercel/callback/page.tsx (1)

32-34: Good type safety improvement, but UI enhancement still needed.

The explicit check for props.searchParams.next properly prevents runtime errors by removing the non-null assertion. However, the fallback UI could still be improved as mentioned in the previous review.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0c9ecb and 697848a.

📒 Files selected for processing (4)
  • apps/dashboard/app/(app)/settings/vercel/page.tsx (1 hunks)
  • apps/dashboard/app/integrations/vercel/callback/page.tsx (2 hunks)
  • apps/dashboard/app/new/keys.tsx (1 hunks)
  • apps/dashboard/lib/trpc/routers/authorization/roles/keys/schema-with-helpers.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#2825
File: apps/dashboard/app/(app)/logs-v2/hooks/use-bookmarked-filters.ts:0-0
Timestamp: 2025-01-30T20:51:44.359Z
Learning: The user (ogzhanolguncu) prefers to handle refactoring suggestions in separate PRs to maintain focus in the current PR.
Learnt from: mcstepp
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/components/controls/components/logs-search/index.tsx:7-43
Timestamp: 2025-05-15T16:09:49.243Z
Learning: For type safety issues involving `any` type assertions, the team prefers to address these systematically with linter updates rather than fixing them individually in code reviews.
Learnt from: mcstepp
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/api-id-navbar.tsx:47-50
Timestamp: 2025-05-15T15:57:02.128Z
Learning: When reviewing code for Unkey, prefer using `Boolean()` over the double negation (`!!`) operator for boolean coercion, as their linter rules favor this pattern.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3375
File: apps/dashboard/app/(app)/settings/root-keys/components/table/hooks/use-root-keys-list-query.ts:0-0
Timestamp: 2025-06-25T20:32:10.471Z
Learning: In the Unkey codebase, ogzhanolguncu prefers strict validation with fail-fast error handling. When validation errors occur that shouldn't happen in normal operation (like invalid operators), throwing errors to crash the page is preferred over graceful error handling or console logging.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3297
File: apps/dashboard/lib/trpc/routers/authorization/roles/query.ts:210-323
Timestamp: 2025-06-04T20:13:12.060Z
Learning: The user ogzhanolguncu prefers explicit, duplicated code over abstracted helper functions when it improves readability, even if it means some duplication in filter building functions in the authorization roles query module.
apps/dashboard/app/integrations/vercel/callback/page.tsx (14)
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3242
File: apps/dashboard/app/(app)/apis/[apiId]/_overview/components/table/components/override-indicator.tsx:50-65
Timestamp: 2025-05-15T16:26:08.666Z
Learning: In the Unkey dashboard, Next.js router (router.push) should be used for client-side navigation instead of window.location.href to preserve client state and enable smoother transitions between pages.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3311
File: apps/dashboard/components/logs/llm-search/components/search-input.tsx:14-14
Timestamp: 2025-06-10T14:21:42.413Z
Learning: In Next.js applications, importing backend modules into frontend components causes bundling issues and can expose server-side code to the client bundle. For simple constants like limits, it's acceptable to duplicate the value rather than compromise the frontend/backend architectural separation.
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/search.tsx:41-57
Timestamp: 2024-10-23T16:19:42.049Z
Learning: For the `FilterableCommand` component in `apps/www/components/glossary/search.tsx`, adding error handling and loading states to the results list is not necessary.
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/search.tsx:16-20
Timestamp: 2024-10-23T16:21:47.395Z
Learning: For the `FilterableCommand` component in `apps/www/components/glossary/search.tsx`, refactoring type definitions into an interface is not necessary at this time.
Learnt from: p6l-richard
PR: unkeyed/unkey#2085
File: apps/www/components/glossary/terms-stepper-mobile.tsx:16-20
Timestamp: 2024-10-23T16:25:33.113Z
Learning: In the `apps/www/components/glossary/terms-stepper-mobile.tsx` file, avoid suggesting to extract the term navigation logic into a custom hook, as the user prefers to keep the component straightforward.
Learnt from: Srayash
PR: unkeyed/unkey#2568
File: apps/dashboard/app/auth/sign-up/oauth-signup.tsx:25-25
Timestamp: 2024-10-25T23:53:41.716Z
Learning: In the React component `OAuthSignUp` (`apps/dashboard/app/auth/sign-up/oauth-signup.tsx`), adding a `useEffect` cleanup function to reset the `isLoading` state causes a "something went wrong" popup to appear before redirecting when a user clicks on signup.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3401
File: apps/dashboard/app/(app)/logs/filters.query-params.ts:10-0
Timestamp: 2025-06-24T13:29:10.129Z
Learning: The `buildQueryParams` function in `apps/dashboard/app/(app)/logs/filters.query-params.ts` calls `useFilters()` hook inside it, but this is valid because the function is only called from within other React hooks, maintaining the Rules of Hooks compliance.
Learnt from: chronark
PR: unkeyed/unkey#2143
File: apps/dashboard/app/(app)/logs/components/log-details/components/log-footer.tsx:58-61
Timestamp: 2024-12-03T14:21:19.543Z
Learning: For the "Outcome" field in the `LogFooter` component (`apps/dashboard/app/(app)/logs/components/log-details/components/log-footer.tsx`), default to "N/A" instead of "VALID" when handling null values to avoid confusing customers.
Learnt from: chronark
PR: unkeyed/unkey#2180
File: apps/dashboard/lib/constants/workspace-navigations.tsx:85-88
Timestamp: 2024-10-04T20:47:34.791Z
Learning: In navigation code (e.g., `apps/dashboard/lib/constants/workspace-navigations.tsx`), prefer using `segments.at(0)` over `segments[0]` to handle cases when the `segments` array might be empty.
Learnt from: chronark
PR: unkeyed/unkey#2180
File: apps/dashboard/lib/constants/workspace-navigations.tsx:85-88
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In navigation code (e.g., `apps/dashboard/lib/constants/workspace-navigations.tsx`), prefer using `segments.at(0)` over `segments[0]` to handle cases when the `segments` array might be empty.
Learnt from: MichaelUnkey
PR: unkeyed/unkey#2810
File: internal/ui/src/components/date-time/components/time-split.tsx:10-14
Timestamp: 2025-01-22T16:51:59.978Z
Learning: The DateTime component in internal/ui/src/components/date-time/components/time-split.tsx already includes sufficient validation through handleChange and handleBlur functions, making additional runtime validation unnecessary.
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3156
File: apps/dashboard/app/(app)/apis/[apiId]/_components/create-key/index.tsx:112-0
Timestamp: 2025-04-22T11:49:06.167Z
Learning: In the CreateKeyDialog component of Unkey, section navigation is designed to always allow progression even if validation fails, as visual indicators display the validation state of each section.
Learnt from: unrenamed
PR: unkeyed/unkey#2652
File: apps/www/components/particles.tsx:88-90
Timestamp: 2024-11-08T11:44:42.947Z
Learning: In React TypeScript components, if a function memoized with `useCallback` is not called elsewhere in the component, and a `useEffect` is used to invoke it, do not suggest removing the `useEffect` as it is necessary to execute the function.
Learnt from: chronark
PR: unkeyed/unkey#2146
File: apps/dashboard/app/(app)/apis/[apiId]/settings/default-prefix.tsx:74-75
Timestamp: 2024-10-04T17:27:09.821Z
Learning: In `apps/dashboard/app/(app)/apis/[apiId]/settings/default-prefix.tsx`, the hidden `<input>` elements for `workspaceId` and `keyAuthId` work correctly without being registered with React Hook Form.
apps/dashboard/app/(app)/settings/vercel/page.tsx (3)
Learnt from: chronark
PR: unkeyed/unkey#2693
File: apps/api/src/routes/v1_keys_updateKey.ts:350-368
Timestamp: 2024-11-29T15:15:47.308Z
Learning: In `apps/api/src/routes/v1_keys_updateKey.ts`, the code intentionally handles `externalId` and `ownerId` separately for clarity. The `ownerId` field will be removed in the future, simplifying the code.
Learnt from: AkshayBandi027
PR: unkeyed/unkey#2215
File: apps/dashboard/app/(app)/@breadcrumb/authorization/roles/[roleId]/page.tsx:28-29
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In `authorization/roles/[roleId]/update-role.tsx`, the tag `role-${role.id}` is revalidated after updating a role to ensure that the caching mechanism is properly handled for roles.
Learnt from: chronark
PR: unkeyed/unkey#2143
File: apps/dashboard/app/(app)/logs/components/log-details/components/log-footer.tsx:58-61
Timestamp: 2024-12-03T14:21:19.543Z
Learning: For the "Outcome" field in the `LogFooter` component (`apps/dashboard/app/(app)/logs/components/log-details/components/log-footer.tsx`), default to "N/A" instead of "VALID" when handling null values to avoid confusing customers.
apps/dashboard/lib/trpc/routers/authorization/roles/keys/schema-with-helpers.ts (5)
Learnt from: ogzhanolguncu
PR: unkeyed/unkey#3324
File: apps/dashboard/app/(app)/authorization/roles/components/table/components/actions/keys-table-action.popover.constants.tsx:17-18
Timestamp: 2025-06-19T11:48:05.070Z
Learning: In the authorization roles refactor, the RoleBasic type uses `roleId` as the property name for the role identifier, not `id`. This is consistent throughout the codebase in apps/dashboard/lib/trpc/routers/authorization/roles/query.ts.
Learnt from: AkshayBandi027
PR: unkeyed/unkey#2215
File: apps/dashboard/app/(app)/@breadcrumb/authorization/roles/[roleId]/page.tsx:28-29
Timestamp: 2024-10-08T15:33:04.290Z
Learning: In `authorization/roles/[roleId]/update-role.tsx`, the tag `role-${role.id}` is revalidated after updating a role to ensure that the caching mechanism is properly handled for roles.
Learnt from: chronark
PR: unkeyed/unkey#2693
File: apps/api/src/routes/v1_keys_updateKey.ts:350-368
Timestamp: 2024-11-29T15:15:47.308Z
Learning: In `apps/api/src/routes/v1_keys_updateKey.ts`, the code intentionally handles `externalId` and `ownerId` separately for clarity. The `ownerId` field will be removed in the future, simplifying the code.
Learnt from: chronark
PR: unkeyed/unkey#2294
File: apps/api/src/pkg/keys/service.ts:268-271
Timestamp: 2024-10-20T07:05:55.471Z
Learning: In `apps/api/src/pkg/keys/service.ts`, `ratelimitAsync` is a table relation, not a column selection. When querying, ensure that table relations are included appropriately, not as columns.
Learnt from: Flo4604
PR: unkeyed/unkey#3421
File: go/apps/api/openapi/openapi.yaml:196-200
Timestamp: 2025-07-03T05:58:10.669Z
Learning: In the Unkey codebase, OpenAPI 3.1 is used, which allows sibling keys (such as `description`) alongside `$ref` in schema objects. Do not flag this as an error in future reviews.
apps/dashboard/app/new/keys.tsx (2)
Learnt from: chronark
PR: unkeyed/unkey#2825
File: apps/dashboard/app/(app)/logs/components/table/logs-table.tsx:100-118
Timestamp: 2025-01-31T13:50:45.004Z
Learning: Sensitive data in logs is masked at the API layer (apps/api/src/pkg/middleware/metrics.ts) before being written to Clickhouse. This includes redacting API keys, plaintext values, and authorization headers using regex replacements.
Learnt from: chronark
PR: unkeyed/unkey#2693
File: apps/api/src/routes/v1_keys_updateKey.ts:350-368
Timestamp: 2024-11-29T15:15:47.308Z
Learning: In `apps/api/src/routes/v1_keys_updateKey.ts`, the code intentionally handles `externalId` and `ownerId` separately for clarity. The `ownerId` field will be removed in the future, simplifying the code.
🧬 Code Graph Analysis (1)
apps/dashboard/app/(app)/settings/vercel/page.tsx (1)
apps/dashboard/lib/auth/server.ts (1)
  • auth (67-67)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Build / Build
  • GitHub Check: Test API / API Test Local
  • GitHub Check: Test Packages / Test ./packages/nextjs
  • GitHub Check: Test Packages / Test ./packages/api
  • GitHub Check: Test Packages / Test ./packages/cache
  • GitHub Check: Test Packages / Test ./internal/clickhouse
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/dashboard/app/integrations/vercel/callback/page.tsx (1)

112-112: Excellent removal of non-null assertion.

The removal of the ! operator is now safe thanks to the explicit check added above. This change aligns perfectly with the PR objectives of eliminating non-null assertions in favor of safer validation patterns.

apps/dashboard/app/new/keys.tsx (1)

80-103: LGTM! Excellent improvement to code safety.

The refactoring of the maskKey function successfully addresses non-null assertion issues by:

  1. Explicit null checks: Adding if (!firstPart) and if (!prefix || !suffix) prevents runtime errors from undefined array elements
  2. Defensive programming: The function now gracefully handles edge cases like empty strings or malformed keys
  3. Maintained behavior: The masking logic remains the same for valid inputs while being more robust

The changes align perfectly with the PR objectives of improving code safety without changing functionality.

apps/dashboard/app/(app)/settings/vercel/page.tsx (1)

119-147: Excellent defensive programming and error handling improvements!

The refactored user fetching logic effectively addresses the non-null assertion issues by:

  1. Deduplicating and filtering: Using Set and filter(Boolean) prevents unnecessary API calls for duplicate or falsy IDs
  2. Robust error handling: The try-catch wrapper gracefully handles both missing users and API failures
  3. Type safety: The final filter ensures only valid user objects are processed
  4. User experience: Fallback to "Unknown User" provides clear feedback when user data is unavailable

This approach aligns well with the PR's goal of removing unsafe non-null assertions while maintaining functionality and improving code reliability.

@vercel vercel bot temporarily deployed to Preview – dashboard July 3, 2025 11:54 Inactive
@vercel vercel bot temporarily deployed to Preview – engineering July 3, 2025 11:54 Inactive
@ogzhanolguncu
Copy link
Contributor Author

@mcstepp this is good to go

Copy link
Collaborator

mcstepp commented Jul 3, 2025

cool cool, let me get some food in me and I'll take this up again

Copy link
Contributor Author

🫡 🫡

Copy link
Collaborator

@mcstepp mcstepp left a comment

Choose a reason for hiding this comment

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

I'll allow the generic for lint bypass in the examples, but thrown errors need to actually have a useful message

@ogzhanolguncu ogzhanolguncu requested a review from mcstepp July 4, 2025 09:53
@vercel vercel bot temporarily deployed to Preview – dashboard July 4, 2025 09:54 Inactive
Copy link
Collaborator

@mcstepp mcstepp left a comment

Choose a reason for hiding this comment

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

👍

@ogzhanolguncu ogzhanolguncu added this pull request to the merge queue Jul 7, 2025
Merged via the queue into main with commit ff168c6 Jul 7, 2025
32 of 38 checks passed
@ogzhanolguncu ogzhanolguncu deleted the linter-non-null-assertion-fix branch July 7, 2025 15:47
@coderabbitai coderabbitai bot mentioned this pull request Nov 12, 2025
18 tasks
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