@danstackme/apity v0.5.7
Apity
A type-safe API client generator for React applications with runtime validation.
Features
- 🔒 Type-safe API endpoints with TypeScript
- 📄 Define your API schema with Zod
- 🔄 Static type generation for path and query parameters
- 🎯 Runtime validation with Zod
- ⚡️ React Query integration
- 🔄 Import from OpenAPI/Swagger specifications
Installation
npm install @danstackme/apityQuick Start
- Define your API endpoints:
// src/endpoints.ts
import { createApi, createApiEndpoint } from "@danstackme/apity";
import { z } from "zod";
// Define your Zod schemas
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
const UsersResponseSchema = z.array(UserSchema);
const CreateUserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
const QuerySchema = z.object({
limit: z.number(),
offset: z.number().optional(),
});
// Define your endpoints
const getUsersEndpoint = createApiEndpoint({
method: "GET",
response: UsersResponseSchema,
query: QuerySchema,
});
const createUserEndpoint = createApiEndpoint({
method: "POST",
response: UserSchema,
body: CreateUserSchema,
});
const getUserEndpoint = createApiEndpoint({
method: "GET",
response: UserSchema,
});
const updateUserEndpoint = createApiEndpoint({
method: "PUT",
response: UserSchema,
body: CreateUserSchema,
});
const deleteUserEndpoint = createApiEndpoint({
method: "DELETE",
response: z.void(),
});
// Export your endpoints
export const fetchEndpoints = {
"/users": [getUsersEndpoint],
"/users/[id]": [getUserEndpoint],
} as const;
export const mutateEndpoints = {
"/users": [createUserEndpoint],
"/users/[id]": [updateUserEndpoint, deleteUserEndpoint],
} as const;
// Create and export the API instance
export const api = createApi({
baseUrl: "https://api.example.com",
fetchEndpoints,
mutateEndpoints,
});- Set up the type definitions in your application (typically in App.tsx):
// src/App.tsx
import { ApiProvider } from "@danstackme/apity";
import { api, fetchEndpoints, mutateEndpoints } from "./endpoints";
// Register your endpoints for type safety
declare module "@danstackme/apity" {
interface Register {
fetchEndpoints: typeof fetchEndpoints;
mutateEndpoints: typeof mutateEndpoints;
}
}
function App() {
return (
<ApiProvider api={api}>
<YourApp />
</ApiProvider>
);
}- Use the hooks in your components:
// src/components/UserList.tsx
import { useFetch, useMutate } from "@danstackme/apity";
export function UserList() {
// Fetch users with required query parameters
const { data: users, isLoading } = useFetch({
path: "/users",
query: {
limit: 10,
offset: 0,
},
});
// Set up a mutation with path parameters
const { mutate: createUser, isPending: isCreating } = useMutate({
path: "/users/[id]",
method: "PUT",
params: { id: 1 },
});
// Another mutation example
const { mutate: deleteUser } = useMutate({
path: "/users/[id]",
method: "DELETE",
params: { id: 1 },
});
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Users</h1>
{/* Create user form */}
<form
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
createUser({
name: formData.get("name") as string,
email: formData.get("email") as string,
});
}}
>
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<button type="submit" disabled={isCreating}>
{isCreating ? "Creating..." : "Create User"}
</button>
</form>
{/* User list */}
<div>
{users?.map((user) => (
<div key={user.id}>
<h3>{user.name}</h3>
<p>{user.email}</p>
<button onClick={() => deleteUser({ params: { id: user.id } })}>
Delete
</button>
</div>
))}
</div>
</div>
);
}Advanced Usage
Adding Middleware
You can add middleware for authentication, error handling, and more:
export const api = createApi({
baseUrl: "https://api.example.com",
fetchEndpoints,
mutateEndpoints,
middleware: {
before: (config) => {
// Add authentication header
config.headers = {
...config.headers,
Authorization: `Bearer ${localStorage.getItem("token")}`,
};
return config;
},
onError: (error) => {
// Handle unauthorized errors
if (error.response?.status === 401) {
window.location.href = "/login";
}
return Promise.reject(error);
},
},
});Path Parameters
For dynamic routes, use square brackets in the path and provide params:
const { data: user } = useFetch({
path: "/users/[id]",
params: { id: "123" },
});OpenAPI/Swagger Import
You can automatically generate type-safe endpoints from your OpenAPI/Swagger specification using the built-in CLI tool:
npx @danstackme/apity <path-to-spec> --outDir <out-directory>The --outDir defaults to /src
The tool supports both JSON and YAML specifications and will:
- Automatically convert Swagger 2.0 to OpenAPI 3.0
- Generate type-safe endpoints with Zod validation
- Create path and query parameter types
- Set up proper request/response validation
For example, given an OpenAPI spec like:
openapi: 3.0.0
paths:
/users:
get:
parameters:
- name: limit
in: query
schema:
type: integer
responses:
200:
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/User"
post:
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/CreateUser"
responses:
200:
content:
application/json:
schema:
$ref: "#/components/schemas/User"It will generate a fully typed endpoints.ts file with proper Zod validation schemas that you can immediately use in your application.
License
MIT
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago