Skip to content

Fix search ticker metadata#73

Open
keshav-005 wants to merge 3 commits intoOpen-Dev-Society:mainfrom
keshav-005:fix-55-search-ticker-metadata
Open

Fix search ticker metadata#73
keshav-005 wants to merge 3 commits intoOpen-Dev-Society:mainfrom
keshav-005:fix-55-search-ticker-metadata

Conversation

@keshav-005
Copy link
Copy Markdown

@keshav-005 keshav-005 commented Apr 22, 2026

Summary

  • stop treating Finnhub's display symbol as the exchange label in search results
  • normalize the search subtitle so symbol, exchange, and type render cleanly without misleading duplicates

Test plan

  • npx eslint lib/actions/finnhub.actions.ts components/SearchCommand.tsx
  • manually reviewed the search mapping to confirm exchange labels now come from profile data or symbol suffix fallback instead of displaySymbol

Fixes #55

Summary by CodeRabbit

  • Bug Fixes

    • Stock metadata now omits empty fields and extra separators when exchange or type are missing.
    • Search debounce behavior improved so results update more reliably as you type.
  • Refactor

    • Exchange labeling for stocks enhanced, producing clearer and more accurate exchange info in search results.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 22, 2026

@keshav-005 is attempting to deploy a commit to the ravixalgorithm's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

📝 Walkthrough

Walkthrough

Refactors Finnhub integration with concrete TypeScript DTOs and a centralized getExchangeLabel; tightens searchStocks to use typed candidates and explicit __exchange; updates SearchCommand.tsx debounced effect dependency and stock metadata rendering to omit empty segments.

Changes

Cohort / File(s) Summary
UI Display Refinements
components/SearchCommand.tsx
Added debouncedSearch to the effect dependency array; removed unused map index; render stock metadata by joining only truthy fields to avoid blank/undefined separators.
API Integration & Type Safety
lib/actions/finnhub.actions.ts
Added internal DTO types (FinnhubQuote, FinnhubCompanyProfile, SearchStockCandidate), FINNHUB_EXCHANGE_SUFFIXES, and getExchangeLabel(); replaced any with fetchJSON<...> generics; use typed results and explicit __exchange assignment in searchStocks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped through types both neat and bright,
Joined only truthy fields in the pale moonlight,
Exchanges lined up, no blanks in sight,
Debounced footsteps pacing just right,
A tiny rabbit cheers the tidy byte.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix search ticker metadata' directly addresses the main changes: correcting how search result metadata (symbol, exchange, type) is normalized and sourced.
Linked Issues check ✅ Passed The PR successfully addresses issue #55 by normalizing search result metadata and fixing exchange label sourcing to prevent misleading ticker information.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing search ticker metadata: adding typed DTOs, centralizing exchange resolution logic, and cleaning up metadata rendering without extra separators.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/actions/finnhub.actions.ts`:
- Around line 44-53: The getExchangeLabel function currently uses the last
symbol segment after a '.' as a fallback which mislabels share-class tickers
(e.g., BRK.B) as exchange "B"; update getExchangeLabel to only accept suffix
fallbacks when the suffix matches a known exchange allowlist (e.g., TO, L, HK,
T, SS, SZ, AX, PA, etc.) or when suffix length >= 2, otherwise return 'US';
change references in getExchangeLabel (the symbol.split('.') logic and returned
suffix) to validate the suffix against that allowlist/length rule before
returning it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 997004d2-a3b5-40f2-bf2a-5edc247d1921

📥 Commits

Reviewing files that changed from the base of the PR and between fe59884 and 6bc464a.

📒 Files selected for processing (2)
  • components/SearchCommand.tsx
  • lib/actions/finnhub.actions.ts

Comment thread lib/actions/finnhub.actions.ts
@keshav-005
Copy link
Copy Markdown
Author

Good catch, I tightened the fallback so only known exchange suffixes or longer market suffixes are used, which avoids mislabeling share-class tickers like BRK.B as an exchange.

Copy link
Copy Markdown
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

🧹 Nitpick comments (1)
lib/actions/finnhub.actions.ts (1)

59-67: Allowlist is effectively bypassed by the suffix.length >= 2 fallback.

Any symbol whose last .-segment is 2+ characters will be treated as an exchange label, regardless of whether it's a real Finnhub exchange suffix. That weakens the allowlist you just added — e.g. a ticker like FOO.BAR would render BAR as the exchange. Since the allowlist already enumerates the known Finnhub suffixes, consider dropping the length-based escape hatch and defaulting to 'US' when the suffix isn't in FINNHUB_EXCHANGE_SUFFIXES.

Proposed fix
-    if (FINNHUB_EXCHANGE_SUFFIXES.has(suffix) || suffix.length >= 2) {
-        return suffix;
-    }
-
-    return 'US';
+    return FINNHUB_EXCHANGE_SUFFIXES.has(suffix) ? suffix : 'US';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/actions/finnhub.actions.ts` around lines 59 - 67, The allowlist is being
bypassed by the fallback condition "suffix.length >= 2"; update the logic in the
function that examines the parsed suffix (the code using the suffix variable and
FINNHUB_EXCHANGE_SUFFIXES) to remove the "suffix.length >= 2" branch and instead
only accept suffixes that exist in FINNHUB_EXCHANGE_SUFFIXES, returning 'US' for
any suffix not present; ensure the function still returns 'US' when suffix is
falsy and when it's not in FINNHUB_EXCHANGE_SUFFIXES.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/actions/finnhub.actions.ts`:
- Around line 51-54: The guard in getExchangeLabel uses exchange?.trim() but
returns the raw exchange, which can include whitespace; update getExchangeLabel
to return exchange.trim() (not the untrimmed exchange) when the guard passes so
the label is consistent and free of leading/trailing whitespace, leaving the
fallback return (e.g., symbol) unchanged.

---

Nitpick comments:
In `@lib/actions/finnhub.actions.ts`:
- Around line 59-67: The allowlist is being bypassed by the fallback condition
"suffix.length >= 2"; update the logic in the function that examines the parsed
suffix (the code using the suffix variable and FINNHUB_EXCHANGE_SUFFIXES) to
remove the "suffix.length >= 2" branch and instead only accept suffixes that
exist in FINNHUB_EXCHANGE_SUFFIXES, returning 'US' for any suffix not present;
ensure the function still returns 'US' when suffix is falsy and when it's not in
FINNHUB_EXCHANGE_SUFFIXES.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f258abb8-e147-41e3-9937-9f06a44650b6

📥 Commits

Reviewing files that changed from the base of the PR and between 6bc464a and 2c193bf.

📒 Files selected for processing (1)
  • lib/actions/finnhub.actions.ts

Comment thread lib/actions/finnhub.actions.ts
@keshav-005
Copy link
Copy Markdown
Author

Updated again: the helper now returns a trimmed explicit exchange value and only falls back to suffixes from the allowlist, defaulting to US otherwise.

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
lib/actions/finnhub.actions.ts (1)

25-27: Minor: __exchange as a structural field on FinnhubSearchResult is a bit leaky.

Using a __-prefixed property to smuggle profile-derived exchange data through the candidate shape works, but it mixes Finnhub's wire type with an internal enrichment field and relies on convention to keep it out of downstream consumers. A cleaner alternative is a discriminated wrapper instead of extending the DTO:

Optional refactor
-type SearchStockCandidate = FinnhubSearchResult & {
-    __exchange?: string;
-};
+type SearchStockCandidate = {
+    raw: FinnhubSearchResult;
+    exchange?: string;
+};

…and adjust the two producers and the final .map accordingly. Not a blocker — current code is correct given __exchange is optional and only read in one place.

Also applies to: 229-238

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/actions/finnhub.actions.ts` around lines 25 - 27, Replace the leaky
__exchange structural field and the SearchStockCandidate alias by introducing a
discriminated wrapper (e.g., a StockCandidate wrapper that contains the original
FinnhubSearchResult DTO as a property plus an optional exchange field) and
update all producers that create SearchStockCandidate and the consumer that
reads __exchange (the final .map) to use the new wrapper shape instead of
extending FinnhubSearchResult; keep the exchange optional and only read it from
the wrapper when enriching results to preserve downstream DTO purity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lib/actions/finnhub.actions.ts`:
- Around line 25-27: Replace the leaky __exchange structural field and the
SearchStockCandidate alias by introducing a discriminated wrapper (e.g., a
StockCandidate wrapper that contains the original FinnhubSearchResult DTO as a
property plus an optional exchange field) and update all producers that create
SearchStockCandidate and the consumer that reads __exchange (the final .map) to
use the new wrapper shape instead of extending FinnhubSearchResult; keep the
exchange optional and only read it from the wrapper when enriching results to
preserve downstream DTO purity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 220d641a-de28-4407-b895-6f9ad6fd4ad3

📥 Commits

Reviewing files that changed from the base of the PR and between 2c193bf and 80454b9.

📒 Files selected for processing (1)
  • lib/actions/finnhub.actions.ts

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.

Some tick data fetching error

1 participant