| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Caution Review failedThe pull request is closed. WalkthroughThis 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
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
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
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
Possibly related PRs
Suggested reviewers
Poem
📜 Recent review details Configuration used: CodeRabbit UI Reviewing files that changed from the base of the PR and between ae96bd5 and 177a182. ⛔ Files ignored due to path filters (1)
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 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (.coderabbit.yaml)
Documentation and Community
|
Sorry, something went wrong.
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (1)packages/web/src/app/[domain]/search/components/filterPanel/index.tsx (1)🧹 Nitpick comments (9)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.
packages/web/src/app/[domain]/connections/quickActions.tsx (1)📜 Review detailspackages/web/src/app/[domain]/components/fileHeader.tsx (1)405-407: Prefer literal apostrophe for readability and compatibility
The apostrophe in JSX text nodes doesn’t require escaping, and using ' may reduce readability and can be unsupported in some HTML parsers. Switching back to a literal ' (or using the numeric entity ') is sufficient and more compatible.Suggested diff:
- <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> + <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]/search/page.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/features/search/searchApi.ts (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/zoektSchema.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/schemas.ts (4)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(...)).
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.
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Reviewing files that changed from the base of the PR and between 0119510 and ae96bd5.
📒 Files selected for processing (34)packages/web/src/features/search/types.ts (1)packages/web/src/features/search/listReposApi.ts (4)
- SearchResultRange (15-15)
packages/web/src/features/search/types.ts (1)packages/web/src/app/[domain]/search/components/codePreviewPanel/codePreview.tsx (1)packages/web/src/lib/serviceError.ts (2)
- ListRepositoriesResponse (21-21)
packages/web/src/features/search/zoektClient.ts (1)
- ServiceError (11-11)
- invalidZoektResponse (48-65)
packages/web/src/features/search/zoektSchema.ts (1)
- zoektFetch (11-34)
- zoektListRepositoriesResponseSchema (123-132)
packages/web/src/features/search/types.ts (1)packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx (1)
- SearchResultChunk (18-18)
packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatchContainer.tsx (1)packages/web/src/app/[domain]/search/components/searchResultsPanel/fileMatch.tsx (2)
- MAX_MATCHES_TO_PREVIEW (10-10)
packages/web/src/features/search/types.ts (1)packages/web/src/lib/types.ts (1)packages/web/src/lib/utils.ts (1)
- SearchResultChunk (18-18)
- base64Decode (191-194)
packages/web/src/lib/schemas.ts (2)packages/web/src/app/[domain]/components/searchBar/useSuggestionsData.ts (2)
- getVersionResponseSchema (67-69)
- repositoryQuerySchema (15-29)
packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx (1)packages/web/src/features/search/types.ts (1)packages/web/src/lib/utils.ts (1)
- Suggestion (22-27)
- isServiceError (182-188)
packages/web/src/features/search/schemas.ts (8)🪛 Biome (1.9.4) packages/web/src/app/[domain]/search/page.tsx
- searchRequestSchema (22-31)
- searchResponseSchema (33-81)
- rangeSchema (12-15)
- locationSchema (3-10)
- symbolSchema (17-20)
- listRepositoriesResponseSchema (91-93)
- fileSourceRequestSchema (95-99)
- fileSourceResponseSchema (101-104)
[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)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
packages/web/src/app/api/(server)/repos/route.ts (1)
Likewise, entitlements is used solely in a type context (Entitlement) and not at runtime, so the lint suppression is justified.3-3: Import path updated for listRepositories
packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.tsx (1)
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.278-278: Verify stability of refineModeSuggestions
packages/web/src/app/api/(server)/search/route.ts (2)
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.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
packages/web/src/app/api/(server)/source/route.ts (1)
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.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 (Start → start, End → end, LineNumber → lineNumber, Column → column, ByteOffset → byteOffset), 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:
- RawConfig → rawConfig
- URL → url
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:
packages/web/src/features/search/listReposApi.ts (2)
- file.Language to file.language
- match.Ranges to match.matchRanges
- match.ContentStart.LineNumber to match.contentStart.lineNumber
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:
- Constructs the request with appropriate parameters and headers
- Handles error responses from the API
- Transforms the response to match the expected schema
- 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:
- Properly escapes user inputs using escapeStringRegexp to prevent query injection
- Handles optional branch parameter correctly
- Properly handles and forwards service errors
- Returns appropriate errors for file not found cases
- 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
packages/web/src/features/search/schemas.ts (6)
zoektListRepositoriesResponseSchema correctly nests Repos and Stats under List. Matches the Go API’s listing endpoint.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
packages/web/src/features/search/types.ts (2)
fileSourceResponseSchema cleanly returns source and language.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.
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
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:
Some additional things we can do in the future to make the api easier to work with for client:
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores