Skip to content

Commit 42d66fd

Browse files
authored
Merge pull request #9 from zerodays/feat/replace-zodios-with-orval
Replace zodios with orval
2 parents 66d08dc + 96be48d commit 42d66fd

25 files changed

Lines changed: 837 additions & 363 deletions

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@ jobs:
4646
- name: Install Dependencies
4747
run: yarn install --frozen-lockfile
4848
- name: Run Prettier through format
49-
run: yarn format-check
49+
run: yarn format:check

.prettierignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.md

Lines changed: 25 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Welcome to `react-native-template` 👋, the go-to template for building mobile
1313
- [Nativewind Integration](#3-nativewind-integration)
1414
- [Full Localization Support](#4-full-localization-support)
1515
- [Typed Expo Router Setup](#5-typed-expo-router-setup)
16-
- [Zodius API Client Setup](#6-zodius-api-client-setup)
16+
- [Orval API Client Setup](#6-orval-api-client-setup)
1717
- [Custom Utility Hooks](#7-custom-utility-hooks)
1818
- [Zustand State Management](#8-zustand-state-management)
1919
- [CI/CD Workflow Configuration](#9-cicd-workflow-configuration)
@@ -30,7 +30,6 @@ Welcome to `react-native-template` 👋, the go-to template for building mobile
3030
- [Loading](#loading)
3131
- [FormTextInput](#formtextinput)
3232
- [ValidationError](#validationerror)
33-
- [Toaster](#toaster)
3433
7. [Using the Template Effectively](#using-the-template-effectively)
3534
- [Recommended Folder Structure](#recommended-folder-structure)
3635
- [Development Decision Flow Chart](#development-decision-flow-chart)
@@ -186,30 +185,39 @@ export default Routes;
186185
// router.push(Routes.artists.artist('1').songs.song('2'));
187186
```
188187

189-
<a name="6-zodius-api-client-setup"></a>
188+
<a name="6-orval-api-client-setup"></a>
190189

191-
### 6. Zodius API Client Setup 📡
190+
### 6. Orval API Client Setup 📡
192191

193-
A pre-configured Zodius API client with Tenstack Query for managing API calls. The `./api` folder includes a fully set up example for GET and POST requests, complete with schemas, definitions, and global error handling through a custom Zodius plugin.
192+
A pre-configured Orval setup generates a typed API client and TanStack Query hooks from your OpenAPI spec. The `api/generated` folder contains endpoints, models, and optional MSW mocks, powered by a custom Axios mutator and React Query.
193+
194+
```bash
195+
# Generate the client from your OpenAPI schema
196+
yarn gen-api
197+
```
194198

195199
```typescript
196-
import { Zodios } from '@zodios/core';
197-
import { ZodiosHooks } from '@zodios/react';
198-
import apiErrorPlugin from './api-error-plugin';
199-
import exampleApi from './example';
200+
// Use generated React Query hooks
201+
import { useGetRandomFact, useGetFacts } from 'api/generated/endpoints';
200202

201-
const API_URL = process.env.EXPO_PUBLIC_API_URL || '';
203+
const { data, isLoading, error } = useGetRandomFact({ max_length: 140 });
204+
```
202205

203-
// Zodios API client
204-
const apiClient = new Zodios(API_URL, [...exampleApi]);
206+
```typescript
207+
// Imperative request (without a hook)
208+
import { getRandomFact } from 'api/generated/endpoints';
205209

206-
// Apply global error handling
207-
apiClient.use(apiErrorPlugin);
210+
const { data } = await getRandomFact({ max_length: 140 });
211+
```
208212

209-
// Zodios hooks for react
210-
const api = new ZodiosHooks('exampleApi', apiClient);
213+
```typescript
214+
// Global headers and base URL are configured via Axios
215+
// Base URL: env.EXPO_PUBLIC_API_URL (see api/axios-instance.ts)
216+
// Headers: injected by ApiProvider (see utils/providers/api-provider.ts)
217+
import { ApiProvider } from '@utils/providers/api-provider';
211218

212-
export { api, apiClient };
219+
// Wrap your app (e.g., in your root layout)
220+
<ApiProvider>{children}</ApiProvider>;
213221
```
214222

215223
<a name="7-custom-utility-hooks"></a>
@@ -623,55 +631,6 @@ import { WithValidationError } from '@components/ValidationError';
623631

624632
The `ValidationError` and `WithValidationError` components help maintain a clean UI by only showing error messages when necessary, enhancing the user experience with clear feedback.
625633

626-
<a name="toaster"></a>
627-
628-
## Toaster 🍞
629-
630-
The `Toaster` component is a dynamic and interactive toast notification system designed to provide immediate feedback to users. It's connected to a store for global state management and comes with an API plugin for automatic display on API events.
631-
632-
### Component Features
633-
634-
- **Gesture Support**: Users can dismiss the toast by dragging it down, thanks to the integrated gesture handler.
635-
- **Animated Visibility**: Uses `react-native-reanimated` for smooth show and hide animations.
636-
- **Safe Area Handling**: Accounts for device safe areas, ensuring the toast is always visible and accessible.
637-
- **Custom Icons**: Displays icons for error, success, or information based on the toast type.
638-
639-
### How It Works
640-
641-
The `Toaster` component listens to the toast state from `useToastStore`. When a toast is set, it animates into view. It can be dismissed with a drag gesture or by pressing the 'Dismiss' button.
642-
643-
### Usage
644-
645-
The `Toaster` component does not need to be manually managed; it works by setting the toast state through the `useToastStore` actions:
646-
647-
```javascript
648-
useToastStore.getState().setToast({
649-
type: 'success',
650-
message: 'Your changes have been saved!',
651-
});
652-
```
653-
654-
### Customizing the Toaster
655-
656-
While the `Toaster` itself does not require props, you can customize the animations and styles directly within the component's file if needed.
657-
658-
### API Integration
659-
660-
`apiToastPlugin` is set up to automatically display toasts in response to API calls, making use of the `ZodiosPlugin` system. It provides feedback for errors and successes, skipping certain URLs or GET requests as configured.
661-
662-
### Example of Plugin Usage
663-
664-
Simply add the `apiToastPlugin` to your Zodios API client configuration:
665-
666-
```javascript
667-
const apiClient = new Zodios(API_URL, [
668-
/* ...endpoints */
669-
]);
670-
apiClient.use(apiToastPlugin);
671-
```
672-
673-
The `Toaster` provides a smooth, user-friendly notification mechanism that enhances the interactivity of the application, keeping users informed with minimal disruption.
674-
675634
## More Components Comming Soon... 🎉
676635

677636
Stay tuned for more components and features that will be added to the template in the future. We're committed to providing a comprehensive set of tools and solutions to help you build your mobile applications with ease.

api/api-error-plugin.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

api/api-toast-plugin.ts

Lines changed: 0 additions & 66 deletions
This file was deleted.

api/api-token-plugin.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

api/api.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

api/axios-instance.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Axios, {
2+
type AxiosError,
3+
type AxiosRequestConfig,
4+
type AxiosResponse,
5+
} from 'axios';
6+
import env from '../env';
7+
8+
export const AXIOS_INSTANCE = Axios.create({
9+
baseURL: env.EXPO_PUBLIC_API_URL,
10+
});
11+
12+
// add a second `options` argument here if you want to pass extra options to each generated query
13+
export const customAxios = <T>(
14+
config: AxiosRequestConfig,
15+
options?: AxiosRequestConfig,
16+
): Promise<AxiosResponse<T, unknown>> => {
17+
const source = Axios.CancelToken.source();
18+
const promise = AXIOS_INSTANCE({
19+
...config,
20+
...options,
21+
cancelToken: source.token,
22+
}).then((data) => data);
23+
24+
// @ts-expect-error: The cancel method is not typed.
25+
promise.cancel = () => {
26+
source.cancel('Query was cancelled');
27+
};
28+
29+
return promise;
30+
};
31+
32+
// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
33+
export type ErrorType<Error> = AxiosError<Error>;
34+
35+
export type BodyType<BodyData> = BodyData;

api/example/index.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)