@osise/api-client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +474 -0
- package/dist/cjs/api/admin.js +277 -0
- package/dist/cjs/api/admin.js.map +1 -0
- package/dist/cjs/api/artisans.js +277 -0
- package/dist/cjs/api/artisans.js.map +1 -0
- package/dist/cjs/api/auth.js +83 -0
- package/dist/cjs/api/auth.js.map +1 -0
- package/dist/cjs/api/consumers.js +170 -0
- package/dist/cjs/api/consumers.js.map +1 -0
- package/dist/cjs/api/index.js +22 -0
- package/dist/cjs/api/index.js.map +1 -0
- package/dist/cjs/api/jobs.js +202 -0
- package/dist/cjs/api/jobs.js.map +1 -0
- package/dist/cjs/hooks/index.js +435 -0
- package/dist/cjs/hooks/index.js.map +1 -0
- package/dist/cjs/index.js +189 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/types/admin.js +6 -0
- package/dist/cjs/types/admin.js.map +1 -0
- package/dist/cjs/types/artisan.js +6 -0
- package/dist/cjs/types/artisan.js.map +1 -0
- package/dist/cjs/types/auth.js +6 -0
- package/dist/cjs/types/auth.js.map +1 -0
- package/dist/cjs/types/common.js +6 -0
- package/dist/cjs/types/common.js.map +1 -0
- package/dist/cjs/types/consumer.js +6 -0
- package/dist/cjs/types/consumer.js.map +1 -0
- package/dist/cjs/types/enums.js +226 -0
- package/dist/cjs/types/enums.js.map +1 -0
- package/dist/cjs/types/index.js +35 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/job.js +6 -0
- package/dist/cjs/types/job.js.map +1 -0
- package/dist/cjs/utils/http-client.js +214 -0
- package/dist/cjs/utils/http-client.js.map +1 -0
- package/dist/cjs/utils/index.js +19 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/storage.js +105 -0
- package/dist/cjs/utils/storage.js.map +1 -0
- package/dist/esm/api/admin.js +269 -0
- package/dist/esm/api/admin.js.map +1 -0
- package/dist/esm/api/artisans.js +270 -0
- package/dist/esm/api/artisans.js.map +1 -0
- package/dist/esm/api/auth.js +79 -0
- package/dist/esm/api/auth.js.map +1 -0
- package/dist/esm/api/consumers.js +165 -0
- package/dist/esm/api/consumers.js.map +1 -0
- package/dist/esm/api/index.js +6 -0
- package/dist/esm/api/index.js.map +1 -0
- package/dist/esm/api/jobs.js +197 -0
- package/dist/esm/api/jobs.js.map +1 -0
- package/dist/esm/hooks/index.js +408 -0
- package/dist/esm/hooks/index.js.map +1 -0
- package/dist/esm/index.js +165 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types/admin.js +5 -0
- package/dist/esm/types/admin.js.map +1 -0
- package/dist/esm/types/artisan.js +5 -0
- package/dist/esm/types/artisan.js.map +1 -0
- package/dist/esm/types/auth.js +5 -0
- package/dist/esm/types/auth.js.map +1 -0
- package/dist/esm/types/common.js +5 -0
- package/dist/esm/types/common.js.map +1 -0
- package/dist/esm/types/consumer.js +5 -0
- package/dist/esm/types/consumer.js.map +1 -0
- package/dist/esm/types/enums.js +223 -0
- package/dist/esm/types/enums.js.map +1 -0
- package/dist/esm/types/index.js +19 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/job.js +5 -0
- package/dist/esm/types/job.js.map +1 -0
- package/dist/esm/utils/http-client.js +208 -0
- package/dist/esm/utils/http-client.js.map +1 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/storage.js +99 -0
- package/dist/esm/utils/storage.js.map +1 -0
- package/dist/types/api/admin.d.ts +188 -0
- package/dist/types/api/admin.d.ts.map +1 -0
- package/dist/types/api/artisans.d.ts +183 -0
- package/dist/types/api/artisans.d.ts.map +1 -0
- package/dist/types/api/auth.d.ts +58 -0
- package/dist/types/api/auth.d.ts.map +1 -0
- package/dist/types/api/consumers.d.ts +113 -0
- package/dist/types/api/consumers.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +6 -0
- package/dist/types/api/index.d.ts.map +1 -0
- package/dist/types/api/jobs.d.ts +136 -0
- package/dist/types/api/jobs.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +225 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +127 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types/admin.d.ts +226 -0
- package/dist/types/types/admin.d.ts.map +1 -0
- package/dist/types/types/artisan.d.ts +438 -0
- package/dist/types/types/artisan.d.ts.map +1 -0
- package/dist/types/types/auth.d.ts +92 -0
- package/dist/types/types/auth.d.ts.map +1 -0
- package/dist/types/types/common.d.ts +105 -0
- package/dist/types/types/common.d.ts.map +1 -0
- package/dist/types/types/consumer.d.ts +144 -0
- package/dist/types/types/consumer.d.ts.map +1 -0
- package/dist/types/types/enums.d.ts +199 -0
- package/dist/types/types/enums.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +12 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/job.d.ts +226 -0
- package/dist/types/types/job.d.ts.map +1 -0
- package/dist/types/utils/http-client.d.ts +65 -0
- package/dist/types/utils/http-client.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +3 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/storage.d.ts +48 -0
- package/dist/types/utils/storage.d.ts.map +1 -0
- package/package.json +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
# @osise/api-client
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the Osise API - connecting consumers with skilled artisans in Nigeria.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @osise/api-client
|
|
9
|
+
# or
|
|
10
|
+
yarn add @osise/api-client
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @osise/api-client
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { OsiseClient, BrowserTokenStorage } from '@osise/api-client';
|
|
21
|
+
|
|
22
|
+
// Create client instance
|
|
23
|
+
const client = new OsiseClient({
|
|
24
|
+
baseUrl: 'https://api.osise.com',
|
|
25
|
+
storage: new BrowserTokenStorage(), // Persists tokens in localStorage
|
|
26
|
+
onAuthRequired: () => {
|
|
27
|
+
// Handle auth required (e.g., redirect to login)
|
|
28
|
+
window.location.href = '/login';
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Request OTP
|
|
33
|
+
const otpResponse = await client.auth.requestOtp({
|
|
34
|
+
phoneNumber: '+2348012345678',
|
|
35
|
+
purpose: 'Login',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Verify OTP
|
|
39
|
+
const authResponse = await client.auth.verifyOtp({
|
|
40
|
+
phoneNumber: '+2348012345678',
|
|
41
|
+
code: '123456',
|
|
42
|
+
deviceId: 'unique-device-id',
|
|
43
|
+
deviceName: 'iPhone 15',
|
|
44
|
+
deviceType: 'iOS',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Tokens are automatically stored and used for subsequent requests
|
|
48
|
+
console.log('Logged in as:', authResponse.data?.user.firstName);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### React Integration
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { OsiseProvider, useOsiseClient, useConsumerProfile, useMutation } from '@osise/api-client/react';
|
|
55
|
+
import { BrowserTokenStorage } from '@osise/api-client';
|
|
56
|
+
|
|
57
|
+
// Wrap your app with the provider
|
|
58
|
+
function App() {
|
|
59
|
+
return (
|
|
60
|
+
<OsiseProvider
|
|
61
|
+
config={{
|
|
62
|
+
baseUrl: 'https://api.osise.com',
|
|
63
|
+
storage: new BrowserTokenStorage(),
|
|
64
|
+
onAuthRequired: () => navigate('/login'),
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<MyApp />
|
|
68
|
+
</OsiseProvider>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Use hooks in components
|
|
73
|
+
function Profile() {
|
|
74
|
+
const { data: profile, isLoading, error } = useConsumerProfile();
|
|
75
|
+
|
|
76
|
+
if (isLoading) return <div>Loading...</div>;
|
|
77
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div>
|
|
81
|
+
<h1>Welcome, {profile?.firstName}!</h1>
|
|
82
|
+
<p>Phone: {profile?.phoneNumber}</p>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Use mutations for actions
|
|
88
|
+
function CreateJobButton() {
|
|
89
|
+
const client = useOsiseClient();
|
|
90
|
+
|
|
91
|
+
const { mutate, isLoading } = useMutation(
|
|
92
|
+
(data) => client.jobs.create(data),
|
|
93
|
+
{
|
|
94
|
+
onSuccess: (job) => {
|
|
95
|
+
console.log('Job created:', job.id);
|
|
96
|
+
},
|
|
97
|
+
onError: (error) => {
|
|
98
|
+
alert(error.message);
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<button
|
|
105
|
+
onClick={() => mutate({
|
|
106
|
+
serviceCategory: 'Plumbing',
|
|
107
|
+
title: 'Fix leaky faucet',
|
|
108
|
+
description: 'Kitchen faucet is leaking',
|
|
109
|
+
addressId: 'addr-123',
|
|
110
|
+
})}
|
|
111
|
+
disabled={isLoading}
|
|
112
|
+
>
|
|
113
|
+
Create Job
|
|
114
|
+
</button>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### React Native Integration
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { OsiseClient, SecureTokenStorage } from '@osise/api-client';
|
|
123
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
124
|
+
|
|
125
|
+
// Create secure storage for React Native
|
|
126
|
+
const storage = new SecureTokenStorage(AsyncStorage);
|
|
127
|
+
await storage.initialize(); // Load tokens from storage
|
|
128
|
+
|
|
129
|
+
const client = new OsiseClient({
|
|
130
|
+
baseUrl: 'https://api.osise.com',
|
|
131
|
+
storage,
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## API Reference
|
|
136
|
+
|
|
137
|
+
### Authentication
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Request OTP
|
|
141
|
+
await client.auth.requestOtp({
|
|
142
|
+
phoneNumber: '+234...',
|
|
143
|
+
purpose: 'Login', // or 'Registration'
|
|
144
|
+
deviceId: 'optional-device-id',
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Verify OTP
|
|
148
|
+
await client.auth.verifyOtp({
|
|
149
|
+
phoneNumber: '+234...',
|
|
150
|
+
code: '123456',
|
|
151
|
+
deviceId: 'device-id',
|
|
152
|
+
deviceName: 'My Phone',
|
|
153
|
+
deviceType: 'Android',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Register new user
|
|
157
|
+
await client.auth.register({
|
|
158
|
+
phoneNumber: '+234...',
|
|
159
|
+
otpCode: '123456',
|
|
160
|
+
firstName: 'John',
|
|
161
|
+
lastName: 'Doe',
|
|
162
|
+
role: 'Consumer',
|
|
163
|
+
deviceId: 'device-id',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Get current user
|
|
167
|
+
await client.auth.getCurrentUser();
|
|
168
|
+
|
|
169
|
+
// Get active sessions
|
|
170
|
+
await client.auth.getSessions();
|
|
171
|
+
|
|
172
|
+
// Revoke a session
|
|
173
|
+
await client.auth.revokeSession('session-id');
|
|
174
|
+
|
|
175
|
+
// Logout
|
|
176
|
+
await client.auth.logout();
|
|
177
|
+
|
|
178
|
+
// Logout all sessions
|
|
179
|
+
await client.auth.logoutAll();
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Consumer Features
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Profile
|
|
186
|
+
await client.consumers.getProfile();
|
|
187
|
+
await client.consumers.updateProfile({ firstName: 'Jane' });
|
|
188
|
+
await client.consumers.uploadProfilePhoto('https://uploadcare.com/...');
|
|
189
|
+
|
|
190
|
+
// Addresses
|
|
191
|
+
await client.consumerAddresses.getAll();
|
|
192
|
+
await client.consumerAddresses.create({
|
|
193
|
+
label: 'Home',
|
|
194
|
+
street: '123 Main St',
|
|
195
|
+
area: 'Lekki',
|
|
196
|
+
city: 'Lagos',
|
|
197
|
+
state: 'Lagos',
|
|
198
|
+
latitude: 6.4541,
|
|
199
|
+
longitude: 3.3947,
|
|
200
|
+
});
|
|
201
|
+
await client.consumerAddresses.setDefault('address-id');
|
|
202
|
+
|
|
203
|
+
// Favorites
|
|
204
|
+
await client.consumers.getFavorites();
|
|
205
|
+
await client.consumers.addFavorite('artisan-id');
|
|
206
|
+
await client.consumers.removeFavorite('artisan-id');
|
|
207
|
+
|
|
208
|
+
// Notification Settings
|
|
209
|
+
await client.consumers.getNotificationSettings();
|
|
210
|
+
await client.consumers.updateNotificationSettings({
|
|
211
|
+
pushEnabled: true,
|
|
212
|
+
jobUpdates: true,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// NDPR Compliance
|
|
216
|
+
await client.consumers.exportData();
|
|
217
|
+
await client.consumers.requestAccountDeletion({ reason: 'Moving abroad' });
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Artisan Features
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// Profile
|
|
224
|
+
await client.artisans.getProfile();
|
|
225
|
+
await client.artisans.updateProfile({ bio: 'Experienced plumber' });
|
|
226
|
+
|
|
227
|
+
// Documents
|
|
228
|
+
await client.artisans.getDocuments();
|
|
229
|
+
await client.artisans.submitDocument({
|
|
230
|
+
documentType: 'Nin',
|
|
231
|
+
fileUrl: 'https://...',
|
|
232
|
+
fileName: 'nin.pdf',
|
|
233
|
+
fileSize: 1024,
|
|
234
|
+
mimeType: 'application/pdf',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Guarantors
|
|
238
|
+
await client.artisans.getGuarantors();
|
|
239
|
+
await client.artisans.addGuarantor({
|
|
240
|
+
fullName: 'Jane Smith',
|
|
241
|
+
phoneNumber: '+234...',
|
|
242
|
+
relationship: 'Former Employer',
|
|
243
|
+
occupation: 'Business Owner',
|
|
244
|
+
address: '456 Oak St, Lagos',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Bank Account
|
|
248
|
+
await client.artisans.getBankAccount();
|
|
249
|
+
await client.artisans.setBankAccount({
|
|
250
|
+
bankCode: '044',
|
|
251
|
+
accountNumber: '0123456789',
|
|
252
|
+
accountName: 'John Doe',
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Application Status
|
|
256
|
+
await client.artisans.getApplicationStatus();
|
|
257
|
+
await client.artisans.getSkillTestSlots();
|
|
258
|
+
await client.artisans.bookSkillTest({ slotId: 'slot-id' });
|
|
259
|
+
|
|
260
|
+
// Availability
|
|
261
|
+
await client.artisanAvailability.getStatus();
|
|
262
|
+
await client.artisanAvailability.updateStatus({ status: 'Online' });
|
|
263
|
+
await client.artisanAvailability.updateWorkingHours({
|
|
264
|
+
workingHours: [
|
|
265
|
+
{ dayOfWeek: 'Monday', isWorking: true, startTime: '08:00', endTime: '17:00' },
|
|
266
|
+
// ...
|
|
267
|
+
],
|
|
268
|
+
});
|
|
269
|
+
await client.artisanAvailability.updateLocation({ latitude: 6.45, longitude: 3.39 });
|
|
270
|
+
|
|
271
|
+
// Earnings
|
|
272
|
+
await client.artisanEarnings.getSummary();
|
|
273
|
+
await client.artisanEarnings.getJobEarnings({ page: 1, pageSize: 20 });
|
|
274
|
+
await client.artisanEarnings.getPendingEarnings();
|
|
275
|
+
await client.artisanEarnings.getPayouts();
|
|
276
|
+
|
|
277
|
+
// Performance
|
|
278
|
+
await client.artisanPerformance.getRating();
|
|
279
|
+
await client.artisanPerformance.getReviews();
|
|
280
|
+
await client.artisanPerformance.getMetrics({ period: 'month' });
|
|
281
|
+
await client.artisanPerformance.getAlerts();
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Jobs
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// Consumer - Create and manage jobs
|
|
288
|
+
await client.jobs.create({
|
|
289
|
+
serviceCategory: 'Electrical',
|
|
290
|
+
title: 'Fix electrical outlet',
|
|
291
|
+
description: 'Outlet in bedroom not working',
|
|
292
|
+
addressId: 'address-id',
|
|
293
|
+
isUrgent: true,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await client.jobs.list({ status: 'Pending', page: 1 });
|
|
297
|
+
await client.jobs.get('job-id');
|
|
298
|
+
await client.jobs.cancel('job-id', { reason: 'Found another solution' });
|
|
299
|
+
await client.jobs.getTimeline('job-id');
|
|
300
|
+
|
|
301
|
+
// Quotes
|
|
302
|
+
await client.jobs.getQuote('job-id');
|
|
303
|
+
await client.jobs.respondToQuote('job-id', { decision: 'approve' });
|
|
304
|
+
|
|
305
|
+
// Payments
|
|
306
|
+
await client.jobs.initiatePayment('job-id', { method: 'Card' });
|
|
307
|
+
await client.jobs.verifyPayment('job-id', 'payment-reference');
|
|
308
|
+
|
|
309
|
+
// Ratings
|
|
310
|
+
await client.jobs.submitRating('job-id', {
|
|
311
|
+
overall: 5,
|
|
312
|
+
quality: 5,
|
|
313
|
+
punctuality: 4,
|
|
314
|
+
professionalism: 5,
|
|
315
|
+
value: 4,
|
|
316
|
+
reviewText: 'Great work!',
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Artisan - Handle assigned jobs
|
|
320
|
+
await client.artisanJobs.list({ status: 'Assigned' });
|
|
321
|
+
await client.artisanJobs.accept('job-id');
|
|
322
|
+
await client.artisanJobs.decline('job-id', 'Too far away');
|
|
323
|
+
await client.artisanJobs.startEnRoute('job-id');
|
|
324
|
+
await client.artisanJobs.markArrived('job-id', { latitude: 6.45, longitude: 3.39 });
|
|
325
|
+
await client.artisanJobs.submitQuote('job-id', {
|
|
326
|
+
laborCost: 5000,
|
|
327
|
+
materials: [
|
|
328
|
+
{ item: 'Wire', quantity: 2, unitPrice: 500 },
|
|
329
|
+
],
|
|
330
|
+
estimatedDuration: '2 hours',
|
|
331
|
+
});
|
|
332
|
+
await client.artisanJobs.startWork('job-id');
|
|
333
|
+
await client.artisanJobs.complete('job-id', 'All fixed');
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Admin Features
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// Dashboard
|
|
340
|
+
await client.adminDashboard.getStats();
|
|
341
|
+
|
|
342
|
+
// Artisan Management
|
|
343
|
+
await client.adminArtisans.list({ search: 'John', status: 'Active' });
|
|
344
|
+
await client.adminArtisans.get('artisan-id');
|
|
345
|
+
await client.adminArtisans.suspend('artisan-id', 'Policy violation');
|
|
346
|
+
await client.adminArtisans.issueStrike('artisan-id', {
|
|
347
|
+
type: 'QualityIssue',
|
|
348
|
+
reason: 'Poor workmanship reported',
|
|
349
|
+
severity: 'warning',
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Application Review
|
|
353
|
+
await client.adminApplications.list({ verificationStatus: 'DocumentsReview' });
|
|
354
|
+
await client.adminApplications.reviewDocument('artisan-id', 'doc-id', {
|
|
355
|
+
status: 'Approved',
|
|
356
|
+
});
|
|
357
|
+
await client.adminApplications.process('artisan-id', { action: 'approve' });
|
|
358
|
+
|
|
359
|
+
// Consumer Management
|
|
360
|
+
await client.adminConsumers.list({ accountType: 'Business' });
|
|
361
|
+
await client.adminConsumers.block('consumer-id', { reason: 'Fraud' });
|
|
362
|
+
await client.adminConsumers.unblock('consumer-id');
|
|
363
|
+
|
|
364
|
+
// Job Management
|
|
365
|
+
await client.adminJobs.list();
|
|
366
|
+
await client.adminJobs.assignArtisan('job-id', 'artisan-id');
|
|
367
|
+
await client.adminJobs.resolveDispute('job-id', 'Refund issued', 5000);
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Error Handling
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
import { OsiseApiError } from '@osise/api-client';
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
await client.auth.verifyOtp({ ... });
|
|
377
|
+
} catch (error) {
|
|
378
|
+
if (error instanceof OsiseApiError) {
|
|
379
|
+
if (error.isUnauthorized) {
|
|
380
|
+
// Token expired or invalid
|
|
381
|
+
} else if (error.isValidationError) {
|
|
382
|
+
// Validation failed - check error.errors
|
|
383
|
+
console.log(error.errors);
|
|
384
|
+
} else if (error.isRateLimited) {
|
|
385
|
+
// Too many requests
|
|
386
|
+
} else if (error.isNetworkError) {
|
|
387
|
+
// Network issue
|
|
388
|
+
} else if (error.isTimeoutError) {
|
|
389
|
+
// Request timed out
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
console.error(error.message, error.statusCode);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## TypeScript Support
|
|
398
|
+
|
|
399
|
+
All types are fully exported:
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import type {
|
|
403
|
+
// Auth
|
|
404
|
+
AuthResponseDto,
|
|
405
|
+
UserProfileDto,
|
|
406
|
+
SessionDto,
|
|
407
|
+
|
|
408
|
+
// Consumer
|
|
409
|
+
ConsumerProfileDto,
|
|
410
|
+
AddressDto,
|
|
411
|
+
|
|
412
|
+
// Artisan
|
|
413
|
+
ArtisanProfileDto,
|
|
414
|
+
ApplicationStatusDto,
|
|
415
|
+
VerificationStatus,
|
|
416
|
+
|
|
417
|
+
// Jobs
|
|
418
|
+
JobRequestDto,
|
|
419
|
+
JobStatus,
|
|
420
|
+
Quote,
|
|
421
|
+
|
|
422
|
+
// Common
|
|
423
|
+
StandardResponse,
|
|
424
|
+
PagedResult,
|
|
425
|
+
|
|
426
|
+
// Enums
|
|
427
|
+
ServiceCategory,
|
|
428
|
+
PaymentMethod,
|
|
429
|
+
AccountType,
|
|
430
|
+
} from '@osise/api-client';
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Configuration Options
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
const client = new OsiseClient({
|
|
437
|
+
// Required
|
|
438
|
+
baseUrl: 'https://api.osise.com',
|
|
439
|
+
|
|
440
|
+
// Optional
|
|
441
|
+
timeout: 30000, // Request timeout in ms
|
|
442
|
+
storage: new BrowserTokenStorage(), // Token storage
|
|
443
|
+
headers: { 'X-Custom-Header': 'value' }, // Custom headers
|
|
444
|
+
autoRefresh: true, // Auto refresh tokens (default: true)
|
|
445
|
+
|
|
446
|
+
// Callbacks
|
|
447
|
+
onError: (error) => console.error(error),
|
|
448
|
+
onAuthRequired: () => redirectToLogin(),
|
|
449
|
+
onTokenRefresh: (accessToken, refreshToken) => {
|
|
450
|
+
console.log('Tokens refreshed');
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Storage Options
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
// Browser (localStorage)
|
|
459
|
+
import { BrowserTokenStorage } from '@osise/api-client';
|
|
460
|
+
const storage = new BrowserTokenStorage('osise'); // optional key prefix
|
|
461
|
+
|
|
462
|
+
// React Native (AsyncStorage)
|
|
463
|
+
import { SecureTokenStorage } from '@osise/api-client';
|
|
464
|
+
const storage = new SecureTokenStorage(AsyncStorage);
|
|
465
|
+
await storage.initialize();
|
|
466
|
+
|
|
467
|
+
// In-memory (SSR, testing)
|
|
468
|
+
import { MemoryTokenStorage } from '@osise/api-client';
|
|
469
|
+
const storage = new MemoryTokenStorage();
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
## License
|
|
473
|
+
|
|
474
|
+
MIT
|