Skip to content

Conversation

teresper-eth
Copy link
Collaborator

@teresper-eth teresper-eth commented Sep 20, 2025

This PR fixes the type issue by adding an interface to the API key response

Summary by CodeRabbit

  • Refactor
    • Standardized GET /api-keys response for improved consistency and safety: API keys are masked in listings, createdAt is consistently formatted, and total usage is included when available. Status values are unchanged. These adjustments improve reliability without altering endpoint paths or request parameters, and are backward-compatible for typical clients consuming this endpoint.

Copy link
Contributor

coderabbitai bot commented Sep 20, 2025

Walkthrough

Refactors GET /api-keys response construction to use a locally defined typed interface. The handler now maps records into ApiKeyResponse objects, masking keys, formatting createdAt, and conditionally including totalUsed while preserving status. No exported signatures or routes changed.

Changes

Cohort / File(s) Summary of Changes
Typed response mapping for API keys
src/routes/apiKeys.ts
Replaced inline object mapping with explicitly typed ApiKeyResponse[]; added key masking, createdAt formatting, and conditional inclusion of totalUsed; preserved status; no public API signature changes.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant R as GET /api-keys Route
    participant D as Data Source
    participant M as Mapper (ApiKeyResponse)

    C->>R: HTTP GET /api-keys
    R->>D: Fetch API key records
    D-->>R: Key records
    R->>M: Transform records (mask key, format createdAt, add totalUsed?)
    M-->>R: ApiKeyResponse[]
    R-->>C: 200 OK with typed array
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I nibble on keys in a tidy row,
Masked little carrots with dates that glow.
Types in a basket, all lined just right,
Totals peek out when they’re in sight.
Hop, map, hop—response takes flight! 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Refactor API key response mapping to use TypeScript interfaces" succinctly and accurately captures the primary change in the changeset — migrating the /api-keys response mapping to a typed ApiKeyResponse via a local interface to fix a type issue. It is specific to the main developer intent, avoids noise, and is clear enough for a teammate scanning history to understand the primary change. The title does not overclaim and aligns with the file-level summary showing the typed transformation.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/key-types

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 0

🧹 Nitpick comments (3)
src/routes/apiKeys.ts (3)

190-197: Hoist ApiKeyResponse (or derive from TypeBox) instead of defining inside the handler.

Avoid per-request type redefinition. Either move the type to module scope or derive it from the response schema via TypeBox to prevent drift.

Top-level addition (preferred with TypeBox):

import { Static, Type } from "@sinclair/typebox";

// Extract once near the schema
export const ApiKeyItem = Type.Object({
  id: Type.String(),
  key: Type.String(),
  createdAt: Type.String(), // consider { format: 'date-time' }
  totalUsed: Type.Optional(Type.Number()),
  status: Type.String(),
});
export type ApiKeyResponse = Static<typeof ApiKeyItem>;

Then remove the in-function interface:

-      interface ApiKeyResponse {
-        id: string;
-        key: string;
-        createdAt: string;
-        totalUsed?: number;
-        status: string;
-      }
+      // ApiKeyResponse is defined at module scope

198-215: Trim redundant inline types; simplify mapping with destructuring.

Leverage inference (or Prisma types) and keep nullish handling concise.

-      const apiKeys: ApiKeyResponse[] = user.apiKeys.map((key: {
-        id: string;
-        key: string;
-        createdAt: Date;
-        totalUsed?: number;
-        status: string;
-      }): ApiKeyResponse => {
-        const apiKeyObj: ApiKeyResponse = {
-          id: key.id,
-          key: maskApiKey(key.key),
-          createdAt: key.createdAt.toISOString(),
-          status: key.status,
-        };
-        if (key.totalUsed !== undefined) {
-          apiKeyObj.totalUsed = key.totalUsed;
-        }
-        return apiKeyObj;
-      });
+      const apiKeys: ApiKeyResponse[] = user.apiKeys.map(
+        ({ id, key: hashedKey, createdAt, totalUsed, status }) => ({
+          id,
+          key: maskApiKey(hashedKey),
+          createdAt: createdAt.toISOString(),
+          ...(totalUsed != null ? { totalUsed } : {}),
+          status,
+        })
+      );

207-209: Masked value is derived from the hash, not the plaintext key — confirm UX or store a display suffix.

Since only the hash is stored, maskApiKey(key.key) exposes the last 8 chars of the hash, which won’t match the user’s plaintext key suffix and can confuse identification. Consider persisting a non-sensitive display suffix (e.g., last 6–8 chars of the plaintext) at creation time and using that here; fall back to the hash suffix if absent. Optionally rename the response field to maskedKey in a future version.

Suggested changes (conceptual):

  • On create (outside this hunk):
const displaySuffix = newApiKey.slice(-8);
await prisma.apiKey.create({ data: { /* ... */, key: hashedKey, displaySuffix } });
  • In GET mapping:
-          key: maskApiKey(hashedKey),
+          key: key.displaySuffix
+            ? `****************${key.displaySuffix}`
+            : maskApiKey(hashedKey),

Would you like a small migration + code patch to add displaySuffix?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 973a909 and 55c595e.

📒 Files selected for processing (1)
  • src/routes/apiKeys.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/routes/apiKeys.ts (1)
src/utils/generateApiKey.ts (1)
  • maskApiKey (40-47)

@metanodreamer metanodreamer merged commit 6f24424 into main Sep 20, 2025
1 check passed
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