feat(api): generate TypeScript API client from OpenAPI specification
Create type-safe TypeScript API client automatically generated from the OpenAPI specification. Includes generated schema types and documented client wrapper for type-safe backend communication. Ref: T008 (specs/001-modbus-relay-control)
This commit is contained in:
61
src/api/README.md
Normal file
61
src/api/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# API Client
|
||||
|
||||
This directory contains the auto-generated TypeScript API client for the STA backend.
|
||||
|
||||
## Files
|
||||
|
||||
- `schema.ts` - Auto-generated OpenAPI type definitions (do not edit manually)
|
||||
- `client.ts` - API client instance with type-safe methods
|
||||
|
||||
## Regenerating the Client
|
||||
|
||||
To regenerate the TypeScript client after backend API changes:
|
||||
|
||||
1. Start the backend server:
|
||||
```bash
|
||||
cargo run
|
||||
```
|
||||
|
||||
2. Download the OpenAPI spec:
|
||||
```bash
|
||||
curl http://localhost:3100/specs > openapi.yaml
|
||||
```
|
||||
|
||||
3. Generate TypeScript types:
|
||||
```bash
|
||||
pnpm exec openapi-typescript openapi.yaml -o src/api/schema.ts
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
```typescript
|
||||
import { apiClient } from '@/api/client';
|
||||
|
||||
// GET request
|
||||
const { data, error } = await apiClient.GET('/api/health');
|
||||
if (error) {
|
||||
console.error('Health check failed:', error);
|
||||
} else {
|
||||
console.log('Server is healthy');
|
||||
}
|
||||
|
||||
// GET request with response data
|
||||
const { data: meta, error: metaError } = await apiClient.GET('/api/meta');
|
||||
if (metaError) {
|
||||
console.error('Failed to get metadata:', metaError);
|
||||
} else {
|
||||
console.log('App name:', meta.name);
|
||||
console.log('App version:', meta.version);
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The API base URL can be configured via the `VITE_API_BASE_URL` environment variable.
|
||||
Create a `.env` file in the project root:
|
||||
|
||||
```env
|
||||
VITE_API_BASE_URL=http://localhost:3100
|
||||
```
|
||||
|
||||
For production builds, set the environment variable to point to your deployed backend.
|
||||
31
src/api/client.ts
Normal file
31
src/api/client.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* API client for the STA backend.
|
||||
*
|
||||
* This client is generated from the OpenAPI specification and provides
|
||||
* type-safe access to all backend endpoints.
|
||||
*
|
||||
* Usage:
|
||||
* ```typescript
|
||||
* import { apiClient } from '@/api/client';
|
||||
*
|
||||
* const { data, error } = await apiClient.GET('/api/health');
|
||||
* ```
|
||||
*/
|
||||
|
||||
import createClient from 'openapi-fetch';
|
||||
import type { paths } from './schema';
|
||||
|
||||
// Get the API base URL from environment variables or default to localhost
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3100';
|
||||
|
||||
/**
|
||||
* Typed API client instance.
|
||||
*
|
||||
* All requests are type-checked against the OpenAPI schema.
|
||||
*/
|
||||
export const apiClient = createClient<paths>({ baseUrl: API_BASE_URL });
|
||||
|
||||
/**
|
||||
* Re-export the types for convenience
|
||||
*/
|
||||
export type { paths, components } from './schema';
|
||||
106
src/api/schema.ts
Normal file
106
src/api/schema.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* This file was auto-generated by openapi-typescript.
|
||||
* Do not make direct changes to the file.
|
||||
*/
|
||||
|
||||
export interface paths {
|
||||
"/api/health": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Success */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Too Many Requests - rate limit exceeded */
|
||||
429: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/meta": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Success */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json; charset=utf-8": components["schemas"]["Meta"];
|
||||
};
|
||||
};
|
||||
/** @description Too Many Requests - rate limit exceeded */
|
||||
429: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
schemas: {
|
||||
/** Meta */
|
||||
Meta: {
|
||||
version: string;
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
requestBodies: never;
|
||||
headers: never;
|
||||
pathItems: never;
|
||||
}
|
||||
export type $defs = Record<string, never>;
|
||||
export type operations = Record<string, never>;
|
||||
Reference in New Issue
Block a user