Skip to content

chore: Sourcebot REST api surface #290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 3, 2025
Merged

chore: Sourcebot REST api surface #290

merged 5 commits into from
May 3, 2025

Conversation

brendan-kellam
Copy link
Contributor

@brendan-kellam brendan-kellam commented May 3, 2025

This PR updates the api surface for /search, and /repos to use our own schema instead of directly returning the zoekt's schema. The new schemas are very close, with the following minor differences:

  • Uses camelCase instead of PascalCase
  • fileName matches are separated from other chunk matches

Some additional things we can do in the future to make the api easier to work with for client:

Summary by CodeRabbit

  • New Features

    • Introduced a new search API integration, including robust schema validation and type definitions for search requests, responses, and repository data.
    • Added new modules for fetching file sources and listing repositories with improved data structures.
  • Refactor

    • Migrated search-related logic and data types to feature-specific modules, improving code organization and maintainability.
    • Updated property naming conventions throughout the search and repository features for consistency and clarity.
  • Bug Fixes

    • Improved memoization and dependency tracking in search suggestion components, ensuring more accurate and up-to-date suggestions.
  • Chores

    • Updated linting configuration and scripts for better development workflow.
    • Added ESLint comments to suppress unused variable warnings in constants.

@brendan-kellam brendan-kellam requested a review from msukkari May 3, 2025 06:58
Copy link

coderabbitai bot commented May 3, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This change reorganizes and modularizes the codebase for search-related functionality in the web package. It removes the previous monolithic implementations of search APIs, types, and schemas from the lib directory, replacing them with feature-scoped modules under features/search. The update introduces new API modules (searchApi, fileSourceApi, listReposApi), Zod schemas, and TypeScript types for search requests and responses. All imports and usages throughout the app are updated to reference these new modules and the new data structures, which use consistent camelCase naming. The change also updates the ESLint configuration and package scripts, and makes minor dependency array and text adjustments in several components.

Changes

File(s) Change Summary
src/features/search/searchApi.ts, fileSourceApi.ts, listReposApi.ts, schemas.ts, types.ts, zoektSchema.ts Added new modular implementations for search, file source, and repository listing APIs; introduced Zod schemas and TypeScript types for search-related data structures, all under the features/search directory.
src/app/api/(server)/search/route.ts, source/route.ts, repos/route.ts Updated imports to use new feature-scoped API modules (searchApi, fileSourceApi, listReposApi) and schemas from features/search.
src/app/api/(client)/client.ts Updated import paths for search, file source, and repository listing types and schemas to reference features/search modules.
src/app/[domain]/browse/[...path]/page.ts Changed imports and data access to use new feature-specific APIs and updated response shapes (e.g., camelCase property names).
src/app/[domain]/components/fileHeader.tsx, searchBar/useSuggestionsData.ts, search/components/filterPanel/index.tsx, search/components/searchResultsPanel/fileMatch.tsx, etc. Updated type imports to use new features/search/types module and refactored all property accesses to match new camelCase naming conventions.
src/app/[domain]/search/page.tsx Refactored imports, variable names, and response handling to use new search API, types, and camelCase property names; updated query parameter from maxMatchDisplayCount to matches.
src/app/[domain]/search/components/codePreviewPanel/index.tsx, codePreview.tsx, searchResultsPanel/index.tsx, etc. Updated types and property names for file and match data to align with new schema (camelCase, nested structure); removed or adjusted filtering logic as needed.
src/lib/types.ts, src/lib/schemas.ts, src/lib/server/searchService.ts Removed all search-related types, schemas, and the monolithic search service implementation from the lib directory. Updated or removed enums and type aliases as needed.
src/lib/extensions/searchResultHighlightExtension.ts, src/lib/utils.ts Updated type imports and property accesses to use new types and property names from features/search/types.
src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx, useSuggestionModeAndQuery.ts Added missing dependencies to useMemo hooks for correctness; no logic changes.
src/app/[domain]/connections/quickActions.tsx Escaped apostrophe in JSX string for proper rendering.
src/app/[domain]/connections/[id]/page.tsx, search/components/filterPanel/filter.tsx Removed unused import statements.
src/features/entitlements/constants.ts Added ESLint disable comments for unused variables.
src/app/.eslintrc.json, package.json Updated ESLint config to remove react-hooks preset; modified lint script to skip environment validation.

Sequence Diagram(s)

sequenceDiagram
    participant UI
    participant SearchAPI
    participant Zoekt
    participant DB

    UI->>SearchAPI: search({ query, matches, ... }, orgId)
    SearchAPI->>SearchAPI: transformZoektQuery(query)
    alt context: prefix
        SearchAPI->>DB: fetch context repositories
        DB-->>SearchAPI: repo list or error
        SearchAPI->>SearchAPI: build reposet: query
    end
    SearchAPI->>Zoekt: POST /api/search with transformed query and org header
    Zoekt-->>SearchAPI: JSON search response
    SearchAPI->>SearchAPI: validate & transform response
    SearchAPI-->>UI: SearchResponse or ServiceError
Loading
sequenceDiagram
    participant UI
    participant FileSourceAPI
    participant SearchAPI

    UI->>FileSourceAPI: getFileSource({ fileName, repository, branch }, orgId)
    FileSourceAPI->>SearchAPI: search(query for file, matches=1, whole=true, orgId)
    SearchAPI-->>FileSourceAPI: SearchResponse or ServiceError
    alt file found
        FileSourceAPI-->>UI: { content, language }
    else file not found
        FileSourceAPI-->>UI: fileNotFound error
    end
Loading
sequenceDiagram
    participant UI
    participant ListReposAPI
    participant Zoekt

    UI->>ListReposAPI: listRepositories(orgId)
    ListReposAPI->>Zoekt: POST /api/list with org header
    Zoekt-->>ListReposAPI: JSON list response
    ListReposAPI->>ListReposAPI: validate & transform response
    ListReposAPI-->>UI: ListRepositoriesResponse or ServiceError
Loading

Possibly related PRs

  • sourcebot-dev/sourcebot#273: Introduces the "search contexts" feature, which depends on and extends the search infrastructure refactored in this PR.

Suggested reviewers

  • msukkari

Poem

In the warren, code hops anew,
Search and schemas split in two.
Types and APIs, now neat and bright,
CamelCase fields in morning light.
Old monoliths have hopped away—
Modular bunnies here to stay!
🐇✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ae96bd5 and 177a182.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • packages/web/package.json (2 hunks)
  • packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts (5 hunks)
  • packages/web/src/features/search/types.ts (1 hunks)
✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

@brendan-kellam brendan-kellam changed the title chore: Sourcebot REST api surface formalization chore: Sourcebot REST api surface spec May 3, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (1)
packages/web/src/app/[domain]/search/components/filterPanel/index.tsx (1)

173-176: ⚠️ Potential issue

Potential runtime crash when repository/language is undefined.

match[propName] is assumed to be a non-empty string, but neither the type system nor the incoming JSON guarantees this.
If a file object is missing language (fairly common in search APIs) or repository, key.length will throw.

-        .map((match) => match[propName])
-        .filter((key) => key.length > 0)
+        .map((match) => match[propName] ?? "")
+        .filter((key): key is string => key.length > 0)

This keeps the pipeline safe while still filtering out empty strings.
Consider tightening the SearchResultFile type so the compiler can help catch this earlier.

🧹 Nitpick comments (9)
packages/web/src/app/[domain]/connections/quickActions.tsx (1)

405-407: Prefer literal apostrophe for readability and compatibility
The apostrophe in JSX text nodes doesn’t require escaping, and using &apos; may reduce readability and can be unsupported in some HTML parsers. Switching back to a literal ' (or using the numeric entity &#39;) is sufficient and more compatible.

Suggested diff:

- <span>Username to use for authentication. This is only required if you&apos;re using an App Password (stored in <Code>token</Code>) for authentication.</span>
+ <span>Username to use for authentication. This is only required if you're using an App Password (stored in <Code>token</Code>) for authentication.</span>
packages/web/src/app/[domain]/components/fileHeader.tsx (1)

1-1: Use a type-only import for Repository
Since Repository is only used as a TypeScript type here, switch to a type-only import to avoid including unneeded runtime code in the bundle:

-import { Repository } from "@/features/search/types";
+import type { Repository } from "@/features/search/types";
packages/web/src/app/[domain]/search/page.tsx (1)

43-46: Guard against invalid or negative matches values.

parseInt can yield NaN or negative numbers (e.g., matches=-5).
Down-stream logic – particularly the Zoekt API – expects a positive integer.

-const _matches = parseInt(useNonEmptyQueryParam(SearchQueryParams.matches) ?? `${DEFAULT_MATCH_COUNT}`);
-const matches = isNaN(_matches) ? DEFAULT_MATCH_COUNT : _matches;
+const rawMatches = parseInt(
+  useNonEmptyQueryParam(SearchQueryParams.matches) ?? `${DEFAULT_MATCH_COUNT}`,
+  10,
+);
+const matches = !rawMatches || rawMatches <= 0 ? DEFAULT_MATCH_COUNT : rawMatches;
packages/web/src/features/search/searchApi.ts (1)

125-128: Header object can be a constant; current re-assignment is redundant.

The temporary let header followed by immediate overwrite adds noise and defeats const safety.

-let header: Record<string, string> = {};
-header = {
-    "X-Tenant-ID": orgId.toString()
-};
+const header = {
+  "X-Tenant-ID": orgId.toString(),
+};
packages/web/src/features/search/zoektSchema.ts (1)

20-41: Consider wrapping stats in a Zod object
Right now zoektSearchResponseStats is a plain object of Zod validators and is spread into another z.object. For consistency and reusability, you may define it as a z.object(...) itself:

-export const zoektSearchResponseStats = {
+export const zoektSearchResponseStats = z.object({
     ContentBytesLoaded: z.number(),
     IndexBytesLoaded: z.number(),
     …  
     FlushReason: z.number(),
-}
+});

This lets you refer to the stats schema directly (e.g. zoektSearchResponseStats.parse(...)).

packages/web/src/features/search/schemas.ts (4)

3-10: Location schema is clear and typed
locationSchema captures byte offset and human-readable coordinates. Consider adding .int().nonnegative() if you want to enforce integer, non-negative constraints.

-export const locationSchema = z.object({
+export const locationSchema = z.object({
     byteOffset: z.number(),
     lineNumber: z.number(),
     column: z.number(),
 });

to

export const locationSchema = z.object({
  byteOffset: z.number().int().nonnegative(),
  lineNumber: z.number().int().min(1),
  column: z.number().int().min(1),
});

22-31: Refine request schema
searchRequestSchema works, but you may want to ensure matches and contextLines are integers with sensible bounds:

.matches: z.number().int().min(1),
.contextLines: z.number().int().min(0).optional(),

This will catch invalid floats or negatives early.


33-81: Extract nested schemas for readability
The large searchResponseSchema is correct but could be easier to maintain if you factored out the file and chunk schemas:

const fileNameSchema = z.object({ text: z.string(), matchRanges: z.array(rangeSchema) });
const chunkSchema = z.object({});

export const searchResponseSchema = z.object({
  zoektStats: ,
  files: z.array(z.object({
    fileName: fileNameSchema,
    chunks: z.array(chunkSchema),})),});

This reduces inline nesting and improves discoverability.


83-90: Repository schema is fine
repositorySchema covers basic repository metadata. Consider adding .nullable() for branches if empty lists should be allowed.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0119510 and ae96bd5.

📒 Files selected for processing (34)
  • packages/web/.eslintrc.json (0 hunks)
  • packages/web/package.json (1 hunks)
  • packages/web/src/app/[domain]/browse/[...path]/page.tsx (3 hunks)
  • packages/web/src/app/[domain]/components/fileHeader.tsx (1 hunks)
  • packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx (1 hunks)
  • packages/web/src/app/[domain]/components/searchBar/useSuggestionModeAndQuery.ts (1 hunks)
  • packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts (5 hunks)
  • packages/web/src/app/[domain]/connections/[id]/page.tsx (0 hunks)
  • packages/web/src/app/[domain]/connections/quickActions.tsx (1 hunks)
  • packages/web/src/app/[domain]/search/components/codePreviewPanel/codePreview.tsx (3 hunks)
  • packages/web/src/app/[domain]/search/components/codePreviewPanel/index.tsx (5 hunks)
  • packages/web/src/app/[domain]/search/components/filterPanel/filter.tsx (0 hunks)
  • packages/web/src/app/[domain]/search/components/filterPanel/index.tsx (6 hunks)
  • packages/web/src/app/[domain]/search/components/searchResultsPanel/codePreview.tsx (3 hunks)
  • packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatch.tsx (3 hunks)
  • packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatchContainer.tsx (4 hunks)
  • packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx (2 hunks)
  • packages/web/src/app/[domain]/search/page.tsx (7 hunks)
  • packages/web/src/app/api/(client)/client.ts (1 hunks)
  • packages/web/src/app/api/(server)/repos/route.ts (1 hunks)
  • packages/web/src/app/api/(server)/search/route.ts (1 hunks)
  • packages/web/src/app/api/(server)/source/route.ts (1 hunks)
  • packages/web/src/features/entitlements/constants.ts (2 hunks)
  • packages/web/src/features/search/fileSourceApi.ts (1 hunks)
  • packages/web/src/features/search/listReposApi.ts (1 hunks)
  • packages/web/src/features/search/schemas.ts (1 hunks)
  • packages/web/src/features/search/searchApi.ts (1 hunks)
  • packages/web/src/features/search/types.ts (1 hunks)
  • packages/web/src/features/search/zoektSchema.ts (1 hunks)
  • packages/web/src/lib/extensions/searchResultHighlightExtension.ts (2 hunks)
  • packages/web/src/lib/schemas.ts (0 hunks)
  • packages/web/src/lib/server/searchService.ts (0 hunks)
  • packages/web/src/lib/types.ts (1 hunks)
  • packages/web/src/lib/utils.ts (2 hunks)
💤 Files with no reviewable changes (5)
  • packages/web/src/app/[domain]/connections/[id]/page.tsx
  • packages/web/src/app/[domain]/search/components/filterPanel/filter.tsx
  • packages/web/.eslintrc.json
  • packages/web/src/lib/server/searchService.ts
  • packages/web/src/lib/schemas.ts
🧰 Additional context used
🧬 Code Graph Analysis (8)
packages/web/src/lib/extensions/searchResultHighlightExtension.ts (1)
packages/web/src/features/search/types.ts (1)
  • SearchResultRange (15-15)
packages/web/src/features/search/listReposApi.ts (4)
packages/web/src/features/search/types.ts (1)
  • ListRepositoriesResponse (21-21)
packages/web/src/lib/serviceError.ts (2)
  • ServiceError (11-11)
  • invalidZoektResponse (48-65)
packages/web/src/features/search/zoektClient.ts (1)
  • zoektFetch (11-34)
packages/web/src/features/search/zoektSchema.ts (1)
  • zoektListRepositoriesResponseSchema (123-132)
packages/web/src/app/[domain]/search/components/codePreviewPanel/codePreview.tsx (1)
packages/web/src/features/search/types.ts (1)
  • SearchResultChunk (18-18)
packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx (1)
packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatchContainer.tsx (1)
  • MAX_MATCHES_TO_PREVIEW (10-10)
packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatch.tsx (2)
packages/web/src/features/search/types.ts (1)
  • SearchResultChunk (18-18)
packages/web/src/lib/utils.ts (1)
  • base64Decode (191-194)
packages/web/src/lib/types.ts (1)
packages/web/src/lib/schemas.ts (2)
  • getVersionResponseSchema (67-69)
  • repositoryQuerySchema (15-29)
packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts (2)
packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx (1)
  • Suggestion (22-27)
packages/web/src/lib/utils.ts (1)
  • isServiceError (182-188)
packages/web/src/features/search/types.ts (1)
packages/web/src/features/search/schemas.ts (8)
  • searchRequestSchema (22-31)
  • searchResponseSchema (33-81)
  • rangeSchema (12-15)
  • locationSchema (3-10)
  • symbolSchema (17-20)
  • listRepositoriesResponseSchema (91-93)
  • fileSourceRequestSchema (95-99)
  • fileSourceResponseSchema (101-104)
🪛 Biome (1.9.4)
packages/web/src/app/[domain]/search/page.tsx

[error] 104-104: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts

[error] 8-8: Do not shadow the global "Symbol" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (78)
packages/web/src/features/entitlements/constants.ts (2)

2-3: ESLint disable for unused planLabels is appropriate
Since planLabels is only leveraged at compile time for its Plan type and not referenced at runtime, suppressing the no-unused-vars rule here is reasonable.


11-12: ESLint disable for unused entitlements is appropriate
Likewise, entitlements is used solely in a type context (Entitlement) and not at runtime, so the lint suppression is justified.

packages/web/src/app/api/(server)/repos/route.ts (1)

3-3: Import path updated for listRepositories
The refactored import from @/features/search/listReposApi aligns with the new feature‐scoped API module. Verify the function signature remains compatible with this route’s usage.

packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx (1)

278-278: Verify stability of refineModeSuggestions
Adding refineModeSuggestions to the useMemo dependency array ensures recomputation when it changes. Please confirm that useRefineModeSuggestions returns a stable (memoized) array; otherwise, each render will trigger the memoized block, negating performance benefits.

packages/web/src/app/api/(server)/search/route.ts (2)

3-3: Import path updated for search
Switching to the feature‐scoped @/features/search/searchApi is consistent with the refactoring and improves modularity.


8-9: Schema and type imports updated
The searchRequestSchema and SearchRequest are now correctly imported from @/features/search/schemas and @/features/search/types, maintaining consistency and type safety in the new structure.

packages/web/src/app/api/(server)/source/route.ts (1)

3-3: Import path updates align with the new feature module structure.

The imports have been correctly updated to reference the new paths under the features/search directory, aligning with the broader refactoring effort to modularize search-related functionality.

Also applies to: 8-9

packages/web/src/app/[domain]/components/searchBar/useSuggestionModeAndQuery.ts (1)

72-72: Fixed dependency array to properly react to suggestionModeMappings changes.

Adding suggestionModeMappings to the dependency array ensures that the memoized values are recalculated when the mappings change, preventing stale data issues in the suggestion mode logic.

packages/web/src/lib/extensions/searchResultHighlightExtension.ts (2)

3-3: Updated import path to use new feature module structure.

The import for SearchResultRange has been correctly updated to reference the new path under features/search/types.


11-13: Property naming convention standardized to camelCase.

The property names have been correctly updated from PascalCase to camelCase (Startstart, Endend, LineNumberlineNumber, Columncolumn, ByteOffsetbyteOffset), ensuring consistency with the new conventions established in this refactoring.

Also applies to: 31-31

packages/web/src/lib/utils.ts (2)

9-10: Imports updated to match new feature module structure.

The import for Repository has been correctly updated to the new path under features/search/types, while keeping RepositoryQuery from the existing location. This aligns with the separation of search-specific types into the dedicated feature module.


52-60: Property naming convention standardized to camelCase.

Property accesses on the repo parameter have been updated from PascalCase to camelCase:

  • RawConfigrawConfig
  • URLurl

This ensures consistency with the new camelCase naming conventions established in this refactoring.

packages/web/src/app/[domain]/search/components/searchResultsPanel/codePreview.tsx (2)

5-5: Import path updated to feature-scoped location.

The import path has been updated from the general @/lib/types to the feature-specific @/features/search/types. This aligns with the broader refactoring to improve code organization through feature-scoped modules.


46-47: Property naming convention changed from PascalCase to camelCase.

All property references were updated from PascalCase (e.g., Start.ByteOffset, LineNumber) to camelCase (e.g., start.byteOffset, lineNumber). This change maintains consistent naming conventions across the codebase and aligns with TypeScript best practices.

Also applies to: 48-51, 62-68

packages/web/src/app/[domain]/browse/[...path]/page.tsx (3)

4-5: Imports updated to use dedicated API modules.

Import paths have been updated to use dedicated API modules (fileSourceApi and listReposApi) from the feature-specific directory, improving code organization and modularity.


61-61: Updated repository object access pattern.

The repository access pattern has been updated to use the new camelCase properties (repos and name) instead of the previous PascalCase properties (List.Repos and Repository.Name). This maintains consistency with the new API response structure.


85-85: Updated repo prop to match new data structure.

The repo prop passed to the FileHeader component now uses the direct repository object instead of accessing a nested Repository property, aligning with the new flattened data structure.

packages/web/src/app/[domain]/search/components/codePreviewPanel/codePreview.tsx (3)

6-6: Updated type import to feature-scoped location.

Import updated from the general @/lib/types to the feature-specific @/features/search/types, aligning with the broader refactoring effort.


25-25: Type definition updated to match new data structure.

The type for matches was changed from SearchResultFileMatch[] to SearchResultChunk[] to align with the new chunk-based data structure defined in @/features/search/types.


87-87: Property access updated to camelCase naming convention.

Access to match ranges has been updated from match.Ranges to match.matchRanges, following the camelCase naming convention adopted throughout the codebase.

packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx (2)

3-3: Types import path updated to feature-scoped location.

Import path updated from @/lib/types to @/features/search/types for Repository and SearchResultFile types, improving code organization through feature-scoped modules.


44-46: Simplified match filtering logic.

The code has been simplified to directly slice the fileMatch.chunks array instead of using a more complex filtering approach. This makes the code more maintainable and easier to understand while aligning with the new data structure.

packages/web/src/app/api/(client)/client.ts (1)

3-18: Import refactoring looks good

The refactoring of imports to use the new feature-based organization is clean and consistent. Moving search-related types and schemas from /lib to /features/search follows good modularization practices and makes the codebase more maintainable.

packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatch.tsx (5)

5-5: Import path update looks good

The import path has been updated to use the new feature-scoped module structure.


10-10: Prop type updated correctly

The match prop type has been updated to use the new SearchResultChunk type.


20-22: Property access updated to camelCase

The property access has been correctly updated from match.Content to match.content following the new camelCase naming convention.


25-25: Property access updated to camelCase

The property access has been correctly updated from match.Ranges to match.matchRanges following the new camelCase naming convention.


43-45: Property accesses updated to camelCase

The property accesses have been correctly updated following the new camelCase naming convention:

  • file.Language to file.language
  • match.Ranges to match.matchRanges
  • match.ContentStart.LineNumber to match.contentStart.lineNumber
packages/web/src/features/search/listReposApi.ts (2)

1-5: Imports look correct

The imports are appropriate for this module, bringing in the necessary error handling utilities, types, and API client.


7-44: Implementation of listRepositories looks good

The function properly:

  1. Constructs the request with appropriate parameters and headers
  2. Handles error responses from the API
  3. Transforms the response to match the expected schema
  4. Uses type safety with the satisfies keyword

The transformation logic in the parser is clean and handles optional fields appropriately.

packages/web/src/features/search/fileSourceApi.ts (3)

1-6: Imports look correct

The imports are appropriate for this module, bringing in necessary utilities like escapeStringRegexp for query safety.


7-9: Good TODO comment

The TODO comment provides valuable context about a better way to implement file content fetching in the future. This will be important for supporting permalinks to specific revisions.


10-42: Implementation of getFileSource looks good

The function:

  1. Properly escapes user inputs using escapeStringRegexp to prevent query injection
  2. Handles optional branch parameter correctly
  3. Properly handles and forwards service errors
  4. Returns appropriate errors for file not found cases
  5. Uses type safety with the satisfies keyword

This is a robust implementation that follows security best practices.

packages/web/src/lib/types.ts (3)

2-2: Import path updated to align with code reorganization.

The import statement has been simplified to only include schemas that remain in this file, following the migration of search-related schemas to features/search/schemas.ts.


11-11: Parameter renaming for improved consistency.

The maxMatchDisplayCount parameter was renamed to matches, making the API more concise while maintaining its semantic meaning.


14-15: Type definitions reorganized.

Types now have a more logical layout in the file with TenancyMode and RepositoryQuery moved to the bottom, improving code organization.

packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatchContainer.tsx (8)

8-8: Import path updated to use feature-scoped types.

The import for Repository and SearchResultFile types has been updated to use the new feature-scoped path, aligning with the code reorganization.


35-35: Property access updated to use camelCase.

Updated from ChunkMatches.length to chunks.length to match the new camelCase naming convention for API responses.


39-40: Property access paths updated to use camelCase.

File sorting logic now uses camelCase property paths (chunks, contentStart.lineNumber) consistent with the new API response schema.


51-56: FileName highlight range logic updated.

Logic for determining the file name highlight range now uses the camelCase property paths (fileName.matchRanges, start.column, end.column), consistent with the schema changes.


60-60: Dependency array updated.

Updated the dependency array to use the new property path file.fileName.matchRanges to ensure proper memoization.


68-68: Property access updated to use camelCase.

Updated from MatchRanges.length to matchRanges.length to match the new camelCase naming convention.


75-75: Branch-related property accesses updated.

The null check for file.branches and its usage in the memoized value calculation have been updated to use camelCase.

Also applies to: 79-80


104-105: Repository and fileName properties updated.

Updated from file.Repository to file.repository and from file.FileName to file.fileName.text to match the new camelCase schema.

packages/web/src/app/[domain]/search/components/codePreviewPanel/index.tsx (8)

7-7: Import path updated to use feature-scoped types.

The import path for SearchResultFile has been updated to use the new feature-scoped directory structure.


29-29: Query key updated to use camelCase properties.

The query key array now uses the camelCase property names (fileName, repository, branches) consistent with the new API response schema.


37-37: Branch extraction logic updated.

Branch extraction from fileMatch now uses the camelCase property name branches consistent with the schema changes.


40-42: File source fetching parameters updated.

Parameters passed to the fetchFileSource function now use camelCase property paths (fileName.text, repository), consistent with the API schema changes.


46-46: Repository URL template access updated.

Access to the repository URL template now uses the camelCase property repository instead of Repository.


59-59: Path substitution updated.

Path substitution in URL generation now uses the camelCase property path fileName.text instead of FileName.

Also applies to: 72-72


81-85: Return object properties updated.

The object returned from the query function now uses camelCase property paths (fileName.text, chunks, language) consistent with the schema changes.


102-102: CodePreview component prop updated.

The repoName prop passed to the CodePreview component now uses the camelCase property repository instead of Repository.

packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts (8)

43-46: Repository data access pattern updated.

The data access pattern for repository suggestions has been updated to use camelCase property name instead of the previous PascalCase property, aligning with the new API response schema.


56-57: Search query parameters updated.

The search query parameters now use matches (previously maxMatchDisplayCount) and include contextLines: 1, aligning with the updated API parameters.


64-66: File data access pattern updated.

The data extraction for file suggestions now uses camelCase property paths (fileName.text) consistent with the schema changes.


76-77: Symbol search query parameters updated.

Similar to file search, the symbol search query parameters have been updated to use matches and contextLines: 1.


84-84: Symbol extraction logic updated.

The logic to extract symbols from search results has been updated to navigate the new nested structure (files → chunks → symbols) with camelCase property names.


90-90: Symbol map key creation updated.

The symbol map key creation now uses camelCase properties (kind, symbol) consistent with the schema changes.


92-92: Symbol value access updated.

The value property in the symbol suggestions now uses the camelCase property symbol instead of the previous PascalCase version.


162-162: getSymbolIcon function updated.

The switch statement in the getSymbolIcon function now uses the camelCase property kind instead of the previous PascalCase version.

packages/web/src/features/search/searchApi.ts (1)

143-166: Clarify units for zoektStats.duration.

Result.Duration is in nanoseconds, whereas consumers (e.g., telemetry, UI) often expect milliseconds.
Consider normalising here to avoid unit confusion downstream:

-        zoektStats: {
-            duration: Result.Duration,
+        zoektStats: {
+            durationMs: Math.round(Result.Duration / 1_000_000),

and adjust the SearchResponse type accordingly.

packages/web/src/features/search/zoektSchema.ts (9)

2-2: Import Zod correctly
The import of z from “zod” is appropriate and minimal.


5-12: Validate location schema keys
zoektLocationSchema correctly mirrors the Go API’s Location fields with appropriate types and comments.


14-17: Range schema is accurate
zoektRangeSchema cleanly composes two zoektLocationSchema objects for Start and End.


43-48: Symbol schema matches API
zoektSymbolSchema correctly defines Sym, Kind, Parent, and ParentKind. Good alignment with the Zoekt API.


51-75: Search response schema structure
zoektSearchResponseSchema accurately models the nested Result object, including files and their matches. The use of optional fields and .nullable() is appropriate for API variability.


78-87: Repository stats schema is correct
zoektRepoStatsSchema covers all numeric metrics returned by Zoekt. Types match expected integers.


90-99: Index metadata schema
zoektIndexMetadataSchema correctly types versioning and metadata fields. The LanguageMap record is well defined.


103-121: Repository schema completeness
zoektRepositorySchema includes all required fields for repository metadata. Use of .nullable() and .optional() aligns with fields that can be absent.


123-132: List repositories response schema
zoektListRepositoriesResponseSchema correctly nests Repos and Stats under List. Matches the Go API’s listing endpoint.

packages/web/src/features/search/schemas.ts (6)

1-2: Minimal Zod import
Importing only z is clean and follows usual patterns.


12-15: Range schema usage is appropriate
rangeSchema cleanly composes two locationSchema entries.


17-20: Symbol schema is minimal
symbolSchema covers the basic identity of symbols. If you need parent/child hierarchies, you could extend this later.


91-94: List repositories response
listRepositoriesResponseSchema is concise and matches the API response.


95-99: File source request schema
fileSourceRequestSchema is straightforward and correctly typed.


101-104: File source response schema
fileSourceResponseSchema cleanly returns source and language.

packages/web/src/features/search/types.ts (2)

1-11: Import of schemas and Zod
Imports are correctly scoped to ./schemas. Good separation of concerns.


13-25: Types correctly inferred from schemas
All other types—SearchRequest, SearchResponse, SearchResultRange, SearchResultLocation, SearchResultFile, SearchResultChunk, ListRepositoriesResponse, Repository, FileSourceRequest, and FileSourceResponse—are cleanly inferred and will update automatically with schema changes.

@brendan-kellam brendan-kellam changed the title chore: Sourcebot REST api surface spec chore: Sourcebot REST api surface May 3, 2025
msukkari
msukkari previously approved these changes May 3, 2025
@brendan-kellam brendan-kellam merged commit eb10d59 into main May 3, 2025
4 of 5 checks passed
@brendan-kellam brendan-kellam deleted the bkellam/api_shim branch May 3, 2025 18:34
@coderabbitai coderabbitai bot mentioned this pull request May 6, 2025
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