refactor: remove api-types.ts compatibility layer

- Migrated all 29 files from api-types.ts to use reflector-api.d.ts directly
- Removed $SourceKind manual enum in favor of OpenAPI-generated types
- Fixed unrelated Spinner component TypeScript error in AuthWrapper.tsx
- All imports now use: import type { components } from "path/to/reflector-api"
- Deleted api-types.ts file completely
This commit is contained in:
2025-08-29 16:35:33 -06:00
parent 8c525e09e8
commit 7ddae5ddd5
35 changed files with 96 additions and 77 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -19,7 +19,7 @@ export default function AuthWrapper({
justifyContent="center" justifyContent="center"
h="calc(100vh - 80px)" // Account for header height h="calc(100vh - 80px)" // Account for header height
> >
<Spinner size="xl" color="blue.500" thickness="4px" /> <Spinner size="xl" color="blue.500" />
</Flex> </Flex>
); );
} }

View File

@@ -1,7 +1,10 @@
import React from "react"; import React from "react";
import { Box, Stack, Link, Heading } from "@chakra-ui/react"; import { Box, Stack, Link, Heading } from "@chakra-ui/react";
import NextLink from "next/link"; import NextLink from "next/link";
import { Room, SourceKind } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type Room = components["schemas"]["Room"];
type SourceKind = components["schemas"]["SourceKind"];
interface FilterSidebarProps { interface FilterSidebarProps {
rooms: Room[]; rooms: Room[];

View File

@@ -18,7 +18,10 @@ import {
highlightMatches, highlightMatches,
generateTextFragment, generateTextFragment,
} from "../../../lib/textHighlight"; } from "../../../lib/textHighlight";
import { SearchResult, SourceKind } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type SearchResult = components["schemas"]["SearchResult"];
type SourceKind = components["schemas"]["SourceKind"];
interface TranscriptCardsProps { interface TranscriptCardsProps {
results: SearchResult[]; results: SearchResult[];

View File

@@ -20,12 +20,11 @@ import {
} from "nuqs"; } from "nuqs";
import { LuX } from "react-icons/lu"; import { LuX } from "react-icons/lu";
import useSessionUser from "../../lib/useSessionUser"; import useSessionUser from "../../lib/useSessionUser";
import { import type { components } from "../../reflector-api";
Room,
SourceKind, type Room = components["schemas"]["Room"];
SearchResult, type SourceKind = components["schemas"]["SourceKind"];
$SourceKind, type SearchResult = components["schemas"]["SearchResult"];
} from "../../lib/api-types";
import { import {
useRoomsList, useRoomsList,
useTranscriptsSearch, useTranscriptsSearch,
@@ -204,7 +203,7 @@ export default function TranscriptBrowser() {
const [urlSourceKind, setUrlSourceKind] = useQueryState( const [urlSourceKind, setUrlSourceKind] = useQueryState(
"source", "source",
parseAsStringLiteral($SourceKind.values).withOptions({ parseAsStringLiteral(["room", "live", "file"] as const).withOptions({
shallow: false, shallow: false,
}), }),
); );

View File

@@ -12,7 +12,9 @@ import {
HStack, HStack,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { LuLink } from "react-icons/lu"; import { LuLink } from "react-icons/lu";
import { Room } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type Room = components["schemas"]["Room"];
import { RoomActionsMenu } from "./RoomActionsMenu"; import { RoomActionsMenu } from "./RoomActionsMenu";
interface RoomCardsProps { interface RoomCardsProps {

View File

@@ -1,5 +1,7 @@
import { Box, Heading, Text, VStack } from "@chakra-ui/react"; import { Box, Heading, Text, VStack } from "@chakra-ui/react";
import { Room } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type Room = components["schemas"]["Room"];
import { RoomTable } from "./RoomTable"; import { RoomTable } from "./RoomTable";
import { RoomCards } from "./RoomCards"; import { RoomCards } from "./RoomCards";

View File

@@ -9,7 +9,9 @@ import {
Spinner, Spinner,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { LuLink } from "react-icons/lu"; import { LuLink } from "react-icons/lu";
import { Room } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type Room = components["schemas"]["Room"];
import { RoomActionsMenu } from "./RoomActionsMenu"; import { RoomActionsMenu } from "./RoomActionsMenu";
interface RoomTableProps { interface RoomTableProps {

View File

@@ -16,7 +16,7 @@ import {
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import useRoomList from "./useRoomList"; import useRoomList from "./useRoomList";
import { Room } from "../../lib/api-types"; import type { components } from "../../reflector-api";
import { import {
useRoomCreate, useRoomCreate,
useRoomUpdate, useRoomUpdate,
@@ -27,6 +27,8 @@ import {
import { RoomList } from "./_components/RoomList"; import { RoomList } from "./_components/RoomList";
import { PaginationPage } from "../browse/_components/Pagination"; import { PaginationPage } from "../browse/_components/Pagination";
type Room = components["schemas"]["Room"];
interface SelectOption { interface SelectOption {
label: string; label: string;
value: string; value: string;

View File

@@ -1,5 +1,7 @@
import { useRoomsList } from "../../lib/api-hooks"; import { useRoomsList } from "../../lib/api-hooks";
import { Page_Room_ } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type Page_Room_ = components["schemas"]["Page_Room_"];
import { PaginationPage } from "../browse/_components/Pagination"; import { PaginationPage } from "../browse/_components/Pagination";
type RoomList = { type RoomList = {

View File

@@ -6,7 +6,8 @@ import TopicPlayer from "./topicPlayer";
import useParticipants from "../../useParticipants"; import useParticipants from "../../useParticipants";
import useTopicWithWords from "../../useTopicWithWords"; import useTopicWithWords from "../../useTopicWithWords";
import ParticipantList from "./participantList"; import ParticipantList from "./participantList";
import { GetTranscriptTopic } from "../../../../lib/api-types"; import type { components } from "../../../../reflector-api";
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
import { SelectedText, selectedTextIsTimeSlice } from "./types"; import { SelectedText, selectedTextIsTimeSlice } from "./types";
import { useTranscriptUpdate } from "../../../../lib/api-hooks"; import { useTranscriptUpdate } from "../../../../lib/api-hooks";
import useTranscript from "../../useTranscript"; import useTranscript from "../../useTranscript";

View File

@@ -1,7 +1,8 @@
import { faArrowTurnDown } from "@fortawesome/free-solid-svg-icons"; import { faArrowTurnDown } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ChangeEvent, useEffect, useRef, useState } from "react"; import { ChangeEvent, useEffect, useRef, useState } from "react";
import { Participant } from "../../../../lib/api-types"; import type { components } from "../../../../reflector-api";
type Participant = components["schemas"]["Participant"];
import { import {
useTranscriptSpeakerAssign, useTranscriptSpeakerAssign,
useTranscriptSpeakerMerge, useTranscriptSpeakerMerge,

View File

@@ -1,6 +1,7 @@
import useTopics from "../../useTopics"; import useTopics from "../../useTopics";
import { Dispatch, SetStateAction, useEffect } from "react"; import { Dispatch, SetStateAction, useEffect } from "react";
import { GetTranscriptTopic } from "../../../../lib/api-types"; import type { components } from "../../../../reflector-api";
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
import { import {
BoxProps, BoxProps,
Box, Box,

View File

@@ -2,7 +2,9 @@ import { useEffect, useRef, useState } from "react";
import React from "react"; import React from "react";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import "../../../styles/markdown.css"; import "../../../styles/markdown.css";
import { GetTranscript, GetTranscriptTopic } from "../../../lib/api-types"; import type { components } from "../../../reflector-api";
type GetTranscript = components["schemas"]["GetTranscript"];
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
import { useTranscriptUpdate } from "../../../lib/api-hooks"; import { useTranscriptUpdate } from "../../../lib/api-hooks";
import { import {
Flex, Flex,

View File

@@ -1,6 +1,9 @@
import { CreateTranscript, GetTranscript } from "../../lib/api-types"; import type { components } from "../../reflector-api";
import { useTranscriptCreate } from "../../lib/api-hooks"; import { useTranscriptCreate } from "../../lib/api-hooks";
type CreateTranscript = components["schemas"]["CreateTranscript"];
type GetTranscript = components["schemas"]["GetTranscript"];
type UseCreateTranscript = { type UseCreateTranscript = {
transcript: GetTranscript | null; transcript: GetTranscript | null;
loading: boolean; loading: boolean;

View File

@@ -5,7 +5,9 @@ import RegionsPlugin from "wavesurfer.js/dist/plugins/regions.esm.js";
import { formatTime, formatTimeMs } from "../../lib/time"; import { formatTime, formatTimeMs } from "../../lib/time";
import { Topic } from "./webSocketTypes"; import { Topic } from "./webSocketTypes";
import { AudioWaveform } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type AudioWaveform = components["schemas"]["AudioWaveform"];
import { waveSurferStyles } from "../../styles/recorder"; import { waveSurferStyles } from "../../styles/recorder";
import { Box, Flex, IconButton } from "@chakra-ui/react"; import { Box, Flex, IconButton } from "@chakra-ui/react";
import { LuPause, LuPlay } from "react-icons/lu"; import { LuPause, LuPlay } from "react-icons/lu";

View File

@@ -2,11 +2,10 @@ import { useEffect, useState } from "react";
import { featureEnabled } from "../../domainContext"; import { featureEnabled } from "../../domainContext";
import { ShareMode, toShareMode } from "../../lib/shareMode"; import { ShareMode, toShareMode } from "../../lib/shareMode";
import { import type { components } from "../../reflector-api";
GetTranscript, type GetTranscript = components["schemas"]["GetTranscript"];
GetTranscriptTopic, type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
UpdateTranscript, type UpdateTranscript = components["schemas"]["UpdateTranscript"];
} from "../../lib/api-types";
import { import {
Box, Box,
Flex, Flex,

View File

@@ -1,5 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { GetTranscript, GetTranscriptTopic } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type GetTranscript = components["schemas"]["GetTranscript"];
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
import { Button, BoxProps, Box } from "@chakra-ui/react"; import { Button, BoxProps, Box } from "@chakra-ui/react";
type ShareCopyProps = { type ShareCopyProps = {

View File

@@ -1,6 +1,9 @@
import { useState, useEffect, useMemo } from "react"; import { useState, useEffect, useMemo } from "react";
import { featureEnabled } from "../../domainContext"; import { featureEnabled } from "../../domainContext";
import { GetTranscript, GetTranscriptTopic } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type GetTranscript = components["schemas"]["GetTranscript"];
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
import { import {
BoxProps, BoxProps,
Button, Button,

View File

@@ -1,5 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { UpdateTranscript } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type UpdateTranscript = components["schemas"]["UpdateTranscript"];
import { useTranscriptUpdate } from "../../lib/api-hooks"; import { useTranscriptUpdate } from "../../lib/api-hooks";
import { Heading, IconButton, Input, Flex, Spacer } from "@chakra-ui/react"; import { Heading, IconButton, Input, Flex, Spacer } from "@chakra-ui/react";
import { LuPen } from "react-icons/lu"; import { LuPen } from "react-icons/lu";

View File

@@ -1,4 +1,5 @@
import { Participant } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type Participant = components["schemas"]["Participant"];
import { useTranscriptParticipants } from "../../lib/api-hooks"; import { useTranscriptParticipants } from "../../lib/api-hooks";
type ErrorParticipants = { type ErrorParticipants = {

View File

@@ -1,5 +1,7 @@
// Wrapper for backward compatibility // Wrapper for backward compatibility
import { SearchResult, SourceKind } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type SearchResult = components["schemas"]["SearchResult"];
type SourceKind = components["schemas"]["SourceKind"];
import { useTranscriptsSearch } from "../../lib/api-hooks"; import { useTranscriptsSearch } from "../../lib/api-hooks";
import { import {
PaginationPage, PaginationPage,

View File

@@ -1,6 +1,9 @@
import { GetTranscriptTopicWithWordsPerSpeaker } from "../../lib/api-types"; import type { components } from "../../reflector-api";
import { useTranscriptTopicsWithWordsPerSpeaker } from "../../lib/api-hooks"; import { useTranscriptTopicsWithWordsPerSpeaker } from "../../lib/api-hooks";
type GetTranscriptTopicWithWordsPerSpeaker =
components["schemas"]["GetTranscriptTopicWithWordsPerSpeaker"];
type ErrorTopicWithWords = { type ErrorTopicWithWords = {
error: Error; error: Error;
loading: false; loading: false;

View File

@@ -1,5 +1,7 @@
import { useTranscriptTopics } from "../../lib/api-hooks"; import { useTranscriptTopics } from "../../lib/api-hooks";
import { GetTranscriptTopic } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
type TranscriptTopics = { type TranscriptTopics = {
topics: GetTranscriptTopic[] | null; topics: GetTranscriptTopic[] | null;

View File

@@ -1,6 +1,8 @@
import { GetTranscript } from "../../lib/api-types"; import type { components } from "../../reflector-api";
import { useTranscriptGet } from "../../lib/api-hooks"; import { useTranscriptGet } from "../../lib/api-hooks";
type GetTranscript = components["schemas"]["GetTranscript"];
type ErrorTranscript = { type ErrorTranscript = {
error: Error; error: Error;
loading: false; loading: false;

View File

@@ -1,6 +1,8 @@
import { AudioWaveform } from "../../lib/api-types"; import type { components } from "../../reflector-api";
import { useTranscriptWaveform } from "../../lib/api-hooks"; import { useTranscriptWaveform } from "../../lib/api-hooks";
type AudioWaveform = components["schemas"]["AudioWaveform"];
type AudioWaveFormResponse = { type AudioWaveFormResponse = {
waveform: AudioWaveform | null; waveform: AudioWaveform | null;
loading: boolean; loading: boolean;

View File

@@ -2,7 +2,8 @@ import { useEffect, useState } from "react";
import Peer from "simple-peer"; import Peer from "simple-peer";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import { useTranscriptWebRTC } from "../../lib/api-hooks"; import { useTranscriptWebRTC } from "../../lib/api-hooks";
import { RtcOffer } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type RtcOffer = components["schemas"]["RtcOffer"];
const useWebRTC = ( const useWebRTC = (
stream: MediaStream | null, stream: MediaStream | null,

View File

@@ -2,7 +2,10 @@ import { useContext, useEffect, useState } from "react";
import { Topic, FinalSummary, Status } from "./webSocketTypes"; import { Topic, FinalSummary, Status } from "./webSocketTypes";
import { useError } from "../../(errors)/errorContext"; import { useError } from "../../(errors)/errorContext";
import { DomainContext } from "../../domainContext"; import { DomainContext } from "../../domainContext";
import { AudioWaveform, GetTranscriptSegmentTopic } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type AudioWaveform = components["schemas"]["AudioWaveform"];
type GetTranscriptSegmentTopic =
components["schemas"]["GetTranscriptSegmentTopic"];
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { $api } from "../../lib/apiClient"; import { $api } from "../../lib/apiClient";

View File

@@ -1,4 +1,6 @@
import { GetTranscriptTopic } from "../../lib/api-types"; import type { components } from "../../reflector-api";
type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
export type Topic = GetTranscriptTopic; export type Topic = GetTranscriptTopic;

View File

@@ -24,7 +24,9 @@ import { notFound } from "next/navigation";
import useSessionStatus from "../lib/useSessionStatus"; import useSessionStatus from "../lib/useSessionStatus";
import { useRecordingConsent } from "../recordingConsentContext"; import { useRecordingConsent } from "../recordingConsentContext";
import { useMeetingAudioConsent } from "../lib/api-hooks"; import { useMeetingAudioConsent } from "../lib/api-hooks";
import { Meeting } from "../lib/api-types"; import type { components } from "../reflector-api";
type Meeting = components["schemas"]["Meeting"];
import { FaBars } from "react-icons/fa6"; import { FaBars } from "react-icons/fa6";
export type RoomDetails = { export type RoomDetails = {

View File

@@ -1,7 +1,9 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useError } from "../(errors)/errorContext"; import { useError } from "../(errors)/errorContext";
import { Meeting } from "../lib/api-types"; import type { components } from "../reflector-api";
import { shouldShowError } from "../lib/errorUtils"; import { shouldShowError } from "../lib/errorUtils";
type Meeting = components["schemas"]["Meeting"];
import { useRoomsCreateMeeting } from "../lib/api-hooks"; import { useRoomsCreateMeeting } from "../lib/api-hooks";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";

View File

@@ -4,13 +4,10 @@ import { useEffect } from "react";
import { configureApiAuth } from "./apiClient"; import { configureApiAuth } from "./apiClient";
import useSessionAccessToken from "./useSessionAccessToken"; import useSessionAccessToken from "./useSessionAccessToken";
// Note: Base URL is now configured directly in apiClient.tsx
export function ApiAuthProvider({ children }: { children: React.ReactNode }) { export function ApiAuthProvider({ children }: { children: React.ReactNode }) {
const { accessToken } = useSessionAccessToken(); const { accessToken } = useSessionAccessToken();
useEffect(() => { useEffect(() => {
// Configure authentication
configureApiAuth(accessToken); configureApiAuth(accessToken);
}, [accessToken]); }, [accessToken]);

View File

@@ -1,27 +0,0 @@
// Re-export types from generated OpenAPI schema for backward compatibility
import type { components } from "../reflector-api";
// Export types with their original names
export type Room = components["schemas"]["Room"];
export type Meeting = components["schemas"]["Meeting"];
export type SourceKind = components["schemas"]["SourceKind"];
export type SearchResult = components["schemas"]["SearchResult"];
export type GetTranscript = components["schemas"]["GetTranscript"];
export type GetTranscriptTopic = components["schemas"]["GetTranscriptTopic"];
export type UpdateTranscript = components["schemas"]["UpdateTranscript"];
export type AudioWaveform = components["schemas"]["AudioWaveform"];
export type Participant = components["schemas"]["Participant"];
export type CreateTranscript = components["schemas"]["CreateTranscript"];
export type RtcOffer = components["schemas"]["RtcOffer"];
export type GetTranscriptSegmentTopic =
components["schemas"]["GetTranscriptSegmentTopic"];
export type Page_Room_ = components["schemas"]["Page_Room_"];
export type GetTranscriptTopicWithWordsPerSpeaker =
components["schemas"]["GetTranscriptTopicWithWordsPerSpeaker"];
export type GetTranscriptMinimal =
components["schemas"]["GetTranscriptMinimal"];
// Export any enums or constants that were in the old API
export const $SourceKind = {
values: ["room", "live", "file"] as const,
} as const;

View File

@@ -16,23 +16,21 @@ export const client = createClient<paths>({
baseUrl: "http://127.0.0.1:1250", baseUrl: "http://127.0.0.1:1250",
}); });
// Create the React Query client wrapper
export const $api = createFetchClient<paths>(client); export const $api = createFetchClient<paths>(client);
// Store the current auth token and ready state
let currentAuthToken: string | null | undefined = null; let currentAuthToken: string | null | undefined = null;
let authConfigured = false; let authConfigured = false;
// Export function to check if auth is ready
export const isAuthConfigured = () => authConfigured; export const isAuthConfigured = () => authConfigured;
// Set up authentication middleware once
client.use({ client.use({
onRequest({ request }) { onRequest({ request }) {
if (currentAuthToken) { if (currentAuthToken) {
request.headers.set("Authorization", `Bearer ${currentAuthToken}`); request.headers.set("Authorization", `Bearer ${currentAuthToken}`);
} }
// Only set Content-Type if not already set (FormData will set its own boundary) // XXX Only set Content-Type if not already set (FormData will set its own boundary)
// This is a work around for uploading file, we're passing a formdata
// but the content type was still application/json
if ( if (
!request.headers.has("Content-Type") && !request.headers.has("Content-Type") &&
!(request.body instanceof FormData) !(request.body instanceof FormData)
@@ -43,13 +41,11 @@ client.use({
}, },
}); });
// Configure authentication by updating the token
export const configureApiAuth = (token: string | null | undefined) => { export const configureApiAuth = (token: string | null | undefined) => {
currentAuthToken = token; currentAuthToken = token;
authConfigured = true; authConfigured = true;
}; };
// Export typed hooks for convenience
export const useApiQuery = $api.useQuery; export const useApiQuery = $api.useQuery;
export const useApiMutation = $api.useMutation; export const useApiMutation = $api.useMutation;
export const useApiSuspenseQuery = $api.useSuspenseQuery; export const useApiSuspenseQuery = $api.useSuspenseQuery;