diff options
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/api/client.test.ts | 30 | ||||
| -rw-r--r-- | src/client/api/client.ts | 15 | ||||
| -rw-r--r-- | src/client/api/index.ts | 4 | ||||
| -rw-r--r-- | src/client/api/types.ts | 11 | ||||
| -rw-r--r-- | src/client/stores/auth.tsx | 3 |
5 files changed, 45 insertions, 18 deletions
diff --git a/src/client/api/client.test.ts b/src/client/api/client.test.ts index 5489547..27c3a0a 100644 --- a/src/client/api/client.test.ts +++ b/src/client/api/client.test.ts @@ -13,8 +13,10 @@ import { import { ApiClient, ApiClientError, + type LoginResponse, localStorageTokenStorage, type TokenStorage, + type User, } from "./client"; function createMockTokenStorage(): TokenStorage & { @@ -209,3 +211,31 @@ describe("localStorageTokenStorage", () => { expect(localStorageTokenStorage.getTokens()).toBeNull(); }); }); + +describe("InferResponseType types", () => { + it("LoginResponse has expected properties", () => { + // This test verifies the inferred types have the correct structure + // The type assertions will fail at compile time if the types are wrong + const mockResponse: LoginResponse = { + accessToken: "access-token", + refreshToken: "refresh-token", + user: { id: "123", username: "testuser" }, + }; + + expect(mockResponse.accessToken).toBe("access-token"); + expect(mockResponse.refreshToken).toBe("refresh-token"); + expect(mockResponse.user.id).toBe("123"); + expect(mockResponse.user.username).toBe("testuser"); + }); + + it("User type is correctly derived from LoginResponse", () => { + // Verify User type has expected structure + const user: User = { + id: "user-1", + username: "testuser", + }; + + expect(user.id).toBe("user-1"); + expect(user.username).toBe("testuser"); + }); +}); diff --git a/src/client/api/client.ts b/src/client/api/client.ts index 7741942..7607eb6 100644 --- a/src/client/api/client.ts +++ b/src/client/api/client.ts @@ -1,6 +1,13 @@ -import { hc } from "hono/client"; +import { hc, type InferResponseType } from "hono/client"; import type { AppType } from "../../server/index.js"; -import type { ApiError, AuthResponse, Tokens } from "./types"; +import type { ApiError, Tokens } from "./types"; + +// Create a temporary client just for type inference +const _rpc = hc<AppType>(""); + +// Infer response types from server definitions +export type LoginResponse = InferResponseType<typeof _rpc.api.auth.login.$post>; +export type User = LoginResponse["user"]; export class ApiClientError extends Error { constructor( @@ -120,12 +127,12 @@ export class ApiClient { } } - async login(username: string, password: string): Promise<AuthResponse> { + async login(username: string, password: string): Promise<LoginResponse> { const res = await this.rpc.api.auth.login.$post({ json: { username, password }, }); - const data = await this.handleResponse<AuthResponse>(res); + const data = await this.handleResponse<LoginResponse>(res); this.tokenStorage.setTokens({ accessToken: data.accessToken, diff --git a/src/client/api/index.ts b/src/client/api/index.ts index fb26b70..63d0a40 100644 --- a/src/client/api/index.ts +++ b/src/client/api/index.ts @@ -3,7 +3,9 @@ export { ApiClientError, type ApiClientOptions, apiClient, + type LoginResponse, localStorageTokenStorage, type TokenStorage, + type User, } from "./client"; -export type { ApiError, AuthResponse, Tokens, User } from "./types"; +export type { ApiError, Tokens } from "./types"; diff --git a/src/client/api/types.ts b/src/client/api/types.ts index eaf69eb..70918fe 100644 --- a/src/client/api/types.ts +++ b/src/client/api/types.ts @@ -1,14 +1,3 @@ -export interface User { - id: string; - username: string; -} - -export interface AuthResponse { - accessToken: string; - refreshToken: string; - user: User; -} - export interface ApiError { error: { message: string; diff --git a/src/client/stores/auth.tsx b/src/client/stores/auth.tsx index 58e9d40..b34717b 100644 --- a/src/client/stores/auth.tsx +++ b/src/client/stores/auth.tsx @@ -7,8 +7,7 @@ import { useMemo, useState, } from "react"; -import { ApiClientError, apiClient } from "../api/client"; -import type { User } from "../api/types"; +import { ApiClientError, apiClient, type User } from "../api/client"; export interface AuthState { user: User | null; |
