@dimrev4/fitness-v3-backend 0.0.3 → 0.0.4
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 +329 -176
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# @dimrev4/
|
|
1
|
+
# @dimrev4/fitness-v3-backend SDK
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<img src="https://img.shields.io/npm/v/@dimrev4/
|
|
5
|
-
<img src="https://img.shields.io/npm/dm/@dimrev4/
|
|
6
|
-
<img src="https://img.shields.io/github/license/dimRev/
|
|
4
|
+
<img src="https://img.shields.io/npm/v/@dimrev4/fitness-v3-backend" alt="npm version" />
|
|
5
|
+
<img src="https://img.shields.io/npm/dm/@dimrev4/fitness-v3-backend" alt="npm downloads" />
|
|
6
|
+
<img src="https://img.shields.io/github/license/dimRev/fitness-v3-backend" alt="license" />
|
|
7
7
|
<img src="https://img.shields.io/badge/TypeScript-100%25-blue" alt="TypeScript" />
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
-
TypeScript SDK for
|
|
10
|
+
TypeScript SDK for Fitness V3 Backend API - Comprehensive client for body measurements, meal tracking, and fitness data management in fitness applications.
|
|
11
11
|
|
|
12
12
|
## 🚀 Features
|
|
13
13
|
|
|
14
|
-
-
|
|
14
|
+
- � **Body Measurements** - Track weight, body fat, muscle mass, and other metrics
|
|
15
15
|
|
|
16
|
-
-
|
|
16
|
+
- 🔐 **Authentication Integration** - Seamless integration with User Core API
|
|
17
17
|
|
|
18
|
-
-
|
|
18
|
+
- �️ **Meal Management** - Save meals and track consumption (planned)
|
|
19
19
|
|
|
20
|
-
-
|
|
20
|
+
- � **Time-based Filtering** - Query data by date ranges with pagination
|
|
21
21
|
|
|
22
|
-
-
|
|
22
|
+
- 👥 **Group Support** - Access group-shared measurements with proper permissions
|
|
23
23
|
|
|
24
24
|
- 💪 100% TypeScript with full type safety
|
|
25
25
|
|
|
@@ -28,11 +28,11 @@ TypeScript SDK for User Core API - Comprehensive client for user management, aut
|
|
|
28
28
|
## 📦 Installation
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
npm install @dimrev4/
|
|
31
|
+
npm install @dimrev4/fitness-v3-backend
|
|
32
32
|
# or
|
|
33
|
-
yarn add @dimrev4/
|
|
33
|
+
yarn add @dimrev4/fitness-v3-backend
|
|
34
34
|
# or
|
|
35
|
-
pnpm add @dimrev4/
|
|
35
|
+
pnpm add @dimrev4/fitness-v3-backend
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## 🔧 Quick Start
|
|
@@ -43,23 +43,21 @@ pnpm add @dimrev4/user-core
|
|
|
43
43
|
import {
|
|
44
44
|
Configuration,
|
|
45
45
|
AuthV1Api,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} from '@dimrev4/user-core';
|
|
46
|
+
MeasurementsV1Api,
|
|
47
|
+
} from '@dimrev4/fitness-v3-backend';
|
|
49
48
|
|
|
50
49
|
const config = new Configuration({
|
|
51
|
-
basePath: 'https://api.yourdomain.com',
|
|
50
|
+
basePath: 'https://fitness-api.yourdomain.com',
|
|
52
51
|
});
|
|
53
52
|
|
|
54
53
|
const authApi = new AuthV1Api(config);
|
|
55
|
-
const
|
|
56
|
-
const groupApi = new GroupV1Api(config);
|
|
54
|
+
const measurementsApi = new MeasurementsV1Api(config);
|
|
57
55
|
```
|
|
58
56
|
|
|
59
57
|
### 2. Authentication
|
|
60
58
|
|
|
61
59
|
```typescript
|
|
62
|
-
// Login
|
|
60
|
+
// Login (integrates with User Core API)
|
|
63
61
|
const loginResponse = await authApi.authV1ControllerLogin({
|
|
64
62
|
email: 'user@example.com',
|
|
65
63
|
password: 'securePassword123!',
|
|
@@ -69,121 +67,210 @@ const { user, accessToken } = loginResponse.data;
|
|
|
69
67
|
|
|
70
68
|
// Create authenticated client
|
|
71
69
|
const authConfig = new Configuration({
|
|
72
|
-
basePath: 'https://api.yourdomain.com',
|
|
70
|
+
basePath: 'https://fitness-api.yourdomain.com',
|
|
73
71
|
accessToken,
|
|
74
72
|
});
|
|
75
73
|
|
|
76
|
-
const
|
|
74
|
+
const authenticatedMeasurementsApi = new MeasurementsV1Api(authConfig);
|
|
77
75
|
```
|
|
78
76
|
|
|
79
|
-
### 3.
|
|
77
|
+
### 3. Body Measurements
|
|
80
78
|
|
|
81
79
|
```typescript
|
|
82
|
-
// Get current user
|
|
83
|
-
const
|
|
84
|
-
console.log('Current user:', me.data.username);
|
|
85
|
-
|
|
86
|
-
// List users with pagination
|
|
87
|
-
const users = await authenticatedUserApi.userV1ControllerGetUsers({
|
|
80
|
+
// Get current user's measurements with date filtering
|
|
81
|
+
const measurements = await authenticatedMeasurementsApi.getAllByUserId({
|
|
88
82
|
limit: 10,
|
|
89
83
|
offset: 0,
|
|
90
|
-
|
|
84
|
+
fromDate: '2025-01-01',
|
|
85
|
+
toDate: '2025-01-31',
|
|
91
86
|
});
|
|
92
87
|
|
|
93
|
-
|
|
94
|
-
const newUser = await authenticatedUserApi.userV1ControllerCreate({
|
|
95
|
-
email: 'newuser@company.com',
|
|
96
|
-
username: 'newuser',
|
|
97
|
-
password: 'SecurePass123!',
|
|
98
|
-
});
|
|
99
|
-
```
|
|
88
|
+
console.log('Recent measurements:', measurements.data.measurements);
|
|
100
89
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
userId: 'creator-user-id',
|
|
90
|
+
// Create a new measurement
|
|
91
|
+
const newMeasurement = await authenticatedMeasurementsApi.createMeasurement({
|
|
92
|
+
date: new Date().toISOString(),
|
|
93
|
+
weightKG: 75.5,
|
|
94
|
+
heightCM: 175.2,
|
|
95
|
+
bmi: 24.6,
|
|
108
96
|
});
|
|
109
97
|
|
|
110
|
-
|
|
98
|
+
// Get specific measurement
|
|
99
|
+
const measurement =
|
|
100
|
+
await authenticatedMeasurementsApi.getMeasurementById('measurement-id');
|
|
111
101
|
|
|
112
|
-
//
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
groupId,
|
|
116
|
-
'user-id',
|
|
102
|
+
// Update measurement
|
|
103
|
+
const updatedMeasurement = await authenticatedMeasurementsApi.updateMeasurement(
|
|
104
|
+
'measurement-id',
|
|
117
105
|
{
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
canUpdate: true,
|
|
121
|
-
canDelete: false,
|
|
106
|
+
weightKG: 75.8,
|
|
107
|
+
bmi: 24.7,
|
|
122
108
|
},
|
|
123
109
|
);
|
|
110
|
+
|
|
111
|
+
// Delete measurement (soft delete)
|
|
112
|
+
const deleteResponse =
|
|
113
|
+
await authenticatedMeasurementsApi.deleteMeasurement('measurement-id');
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 4. Group-Based Measurements
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Get measurements for a group (requires group read permissions)
|
|
120
|
+
const groupMeasurements =
|
|
121
|
+
await authenticatedMeasurementsApi.getAllByUserIdAdmin('group-id', {
|
|
122
|
+
limit: 20,
|
|
123
|
+
offset: 0,
|
|
124
|
+
fromDate: '2025-01-01',
|
|
125
|
+
toDate: '2025-01-31',
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Get specific measurement by group
|
|
129
|
+
const groupMeasurement =
|
|
130
|
+
await authenticatedMeasurementsApi.getMeasurementByGroupIdAndMeasurementId(
|
|
131
|
+
'group-id',
|
|
132
|
+
'measurement-id',
|
|
133
|
+
);
|
|
124
134
|
```
|
|
125
135
|
|
|
126
136
|
## 🏗️ API Overview
|
|
127
137
|
|
|
128
138
|
### Authentication (AuthV1Api)
|
|
129
139
|
|
|
130
|
-
- POST /api/auth/v1/login - Authenticate user
|
|
131
|
-
- POST /api/auth/v1/register - Create new account
|
|
140
|
+
- POST /api/auth/v1/login - Authenticate user (integrates with User Core)
|
|
141
|
+
- POST /api/auth/v1/register - Create new account (integrates with User Core)
|
|
142
|
+
- POST /api/auth/v1/confirm-otp - Confirm OTP for registration
|
|
132
143
|
- POST /api/auth/v1/logout - Invalidate session
|
|
133
144
|
- POST /api/auth/v1/get-me - Get current user info
|
|
134
145
|
|
|
135
|
-
###
|
|
146
|
+
### Body Measurements (MeasurementsV1Api)
|
|
136
147
|
|
|
137
|
-
- GET /api/
|
|
138
|
-
-
|
|
139
|
-
- GET /api/
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
- DELETE /api/users/v1/self - Delete own account
|
|
148
|
+
- GET /api/measurements/v1 - Get user's measurements (with date filtering)
|
|
149
|
+
- POST /api/measurements/v1 - Create new measurement
|
|
150
|
+
- GET /api/measurements/v1/{id} - Get specific measurement
|
|
151
|
+
- PATCH /api/measurements/v1/{id} - Update measurement
|
|
152
|
+
- DELETE /api/measurements/v1/{id} - Soft delete measurement
|
|
143
153
|
|
|
144
|
-
### Group
|
|
154
|
+
### Group-Based Measurements (MeasurementsV1Api)
|
|
145
155
|
|
|
146
|
-
- GET /api/
|
|
147
|
-
- GET /api/
|
|
148
|
-
- POST /api/groups/v1 - Create group
|
|
149
|
-
- PUT /api/groups/v1/{id} - Update group
|
|
150
|
-
- DELETE /api/groups/v1/{id} - Delete group
|
|
156
|
+
- GET /api/measurements/v1/group/{groupId} - Get group measurements (requires read permission)
|
|
157
|
+
- GET /api/measurements/v1/group/{groupId}/{measurementId} - Get specific group measurement
|
|
151
158
|
|
|
152
|
-
###
|
|
159
|
+
### Meals (Planned - SavedMealsV1Api, UserMealsV1Api)
|
|
153
160
|
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
161
|
+
- GET /api/meals/v1/saved - Get saved meal templates
|
|
162
|
+
- POST /api/meals/v1/saved - Create saved meal template
|
|
163
|
+
- GET /api/meals/v1/user - Get user meal consumption history
|
|
164
|
+
- POST /api/meals/v1/user - Log meal consumption
|
|
157
165
|
|
|
158
|
-
##
|
|
166
|
+
## � Data Models
|
|
159
167
|
|
|
160
|
-
###
|
|
168
|
+
### Measurement
|
|
161
169
|
|
|
162
170
|
```json
|
|
163
171
|
{
|
|
164
|
-
"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
"
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
"id": "e9c83a87-37ac-4938-8d88-379c4ac81c5c",
|
|
173
|
+
"date": "2025-01-15T10:30:00.000Z",
|
|
174
|
+
"weightKG": 75.5,
|
|
175
|
+
"heightCM": 175.2,
|
|
176
|
+
"bmi": 24.6,
|
|
177
|
+
"userId": "user-id",
|
|
178
|
+
"createdAt": "2025-01-15T10:30:00.000Z",
|
|
179
|
+
"updatedAt": "2025-01-15T10:30:00.000Z",
|
|
180
|
+
"deletedAt": null
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Saved Meal
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"id": "meal-id",
|
|
189
|
+
"name": "Protein Shake",
|
|
190
|
+
"description": "Post-workout protein shake with banana",
|
|
191
|
+
"recipe": "1 scoop protein powder, 1 banana, 200ml milk...",
|
|
192
|
+
"imgUrl": "https://example.com/protein-shake.jpg",
|
|
193
|
+
"MealType": "SNACK",
|
|
194
|
+
"FoodCategory": "PROTEIN",
|
|
195
|
+
"calories": 350.5,
|
|
196
|
+
"totalFatGrams": 8.2,
|
|
197
|
+
"saturatedFatGrams": 3.1,
|
|
198
|
+
"transFatGrams": 0.0,
|
|
199
|
+
"cholesterolMg": 15.0,
|
|
200
|
+
"sodiumMg": 120.0,
|
|
201
|
+
"totalCarbohydrateGrams": 35.0,
|
|
202
|
+
"dietaryFiberGrams": 4.2,
|
|
203
|
+
"totalSugarGrams": 28.0,
|
|
204
|
+
"addedSugarGrams": 5.0,
|
|
205
|
+
"proteinGrams": 30.0,
|
|
206
|
+
"vitaminDGrams": 2.5,
|
|
207
|
+
"calciumGrams": 250.0,
|
|
208
|
+
"ironGrams": 3.0,
|
|
209
|
+
"potassiumGrams": 450.0,
|
|
210
|
+
"createdAt": "2025-01-15T10:30:00.000Z",
|
|
211
|
+
"updatedAt": "2025-01-15T10:30:00.000Z",
|
|
212
|
+
"deletedAt": null
|
|
177
213
|
}
|
|
178
214
|
```
|
|
179
215
|
|
|
216
|
+
### User Meal
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"id": "user-meal-id",
|
|
221
|
+
"name": "My Custom Protein Shake",
|
|
222
|
+
"description": "My personalized post-workout shake",
|
|
223
|
+
"recipe": "1 scoop protein powder, 1 banana, 200ml almond milk...",
|
|
224
|
+
"imgUrl": "https://example.com/my-shake.jpg",
|
|
225
|
+
"MealType": "SNACK",
|
|
226
|
+
"FoodCategory": "PROTEIN",
|
|
227
|
+
"calories": 320.0,
|
|
228
|
+
"totalFatGrams": 6.5,
|
|
229
|
+
"saturatedFatGrams": 2.1,
|
|
230
|
+
"transFatGrams": 0.0,
|
|
231
|
+
"cholesterolMg": 10.0,
|
|
232
|
+
"sodiumMg": 100.0,
|
|
233
|
+
"totalCarbohydrateGrams": 32.0,
|
|
234
|
+
"dietaryFiberGrams": 4.0,
|
|
235
|
+
"totalSugarGrams": 25.0,
|
|
236
|
+
"addedSugarGrams": 3.0,
|
|
237
|
+
"proteinGrams": 28.0,
|
|
238
|
+
"vitaminDGrams": 2.0,
|
|
239
|
+
"calciumGrams": 200.0,
|
|
240
|
+
"ironGrams": 2.5,
|
|
241
|
+
"potassiumGrams": 400.0,
|
|
242
|
+
"userId": "user-id",
|
|
243
|
+
"createdAt": "2025-01-15T10:30:00.000Z",
|
|
244
|
+
"updatedAt": "2025-01-15T10:30:00.000Z",
|
|
245
|
+
"deletedAt": null
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### User Meal Consumption
|
|
250
|
+
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"id": "consumption-id",
|
|
254
|
+
"userId": "user-id",
|
|
255
|
+
"mealId": "user-meal-id",
|
|
256
|
+
"date": "2025-01-15T14:00:00.000Z",
|
|
257
|
+
"createdAt": "2025-01-15T14:00:00.000Z",
|
|
258
|
+
"updatedAt": "2025-01-15T14:00:00.000Z",
|
|
259
|
+
"deletedAt": null
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## 🔐 Group Permissions
|
|
264
|
+
|
|
265
|
+
For group-based endpoints, users must have appropriate permissions:
|
|
266
|
+
|
|
180
267
|
### Group Permissions
|
|
181
268
|
|
|
182
269
|
```json
|
|
183
270
|
{
|
|
184
271
|
"isRoot": true, // Full group admin
|
|
185
272
|
"canCreate": true, // Create group content
|
|
186
|
-
"canRead": true, // View group content
|
|
273
|
+
"canRead": true, // View group content (required for group measurement endpoints)
|
|
187
274
|
"canUpdate": true, // Modify group content
|
|
188
275
|
"canDelete": true // Delete group content
|
|
189
276
|
}
|
|
@@ -195,7 +282,7 @@ await groupMembersApi.groupMembersV1ControllerAddUserToGroup(
|
|
|
195
282
|
import { AxiosError } from 'axios';
|
|
196
283
|
|
|
197
284
|
try {
|
|
198
|
-
const
|
|
285
|
+
const measurements = await authenticatedMeasurementsApi.getAllByUserId();
|
|
199
286
|
} catch (error) {
|
|
200
287
|
if (error instanceof AxiosError) {
|
|
201
288
|
switch (error.response?.status) {
|
|
@@ -204,13 +291,13 @@ try {
|
|
|
204
291
|
break;
|
|
205
292
|
case 401:
|
|
206
293
|
console.error('Unauthorized:', error.response.data.message);
|
|
207
|
-
// Handle token refresh or redirect
|
|
294
|
+
// Handle token refresh or redirect to login
|
|
208
295
|
break;
|
|
209
296
|
case 403:
|
|
210
297
|
console.error('Forbidden: Insufficient permissions');
|
|
211
298
|
break;
|
|
212
299
|
case 404:
|
|
213
|
-
console.error('
|
|
300
|
+
console.error('Measurement not found');
|
|
214
301
|
break;
|
|
215
302
|
case 409:
|
|
216
303
|
console.error('Conflict:', error.response.data.message);
|
|
@@ -228,7 +315,7 @@ try {
|
|
|
228
315
|
|
|
229
316
|
```typescript
|
|
230
317
|
import axios from 'axios';
|
|
231
|
-
import { Configuration,
|
|
318
|
+
import { Configuration, MeasurementsV1Api } from '@dimrev4/fitness-v3-backend';
|
|
232
319
|
|
|
233
320
|
const axiosInstance = axios.create({
|
|
234
321
|
timeout: 15000,
|
|
@@ -244,7 +331,7 @@ axiosInstance.interceptors.request.use((config) => {
|
|
|
244
331
|
});
|
|
245
332
|
|
|
246
333
|
const config = new Configuration({});
|
|
247
|
-
const
|
|
334
|
+
const measurementsApi = new MeasurementsV1Api(config, undefined, axiosInstance);
|
|
248
335
|
```
|
|
249
336
|
|
|
250
337
|
### Environment Setup
|
|
@@ -253,8 +340,8 @@ const userApi = new UserV1Api(config, undefined, axiosInstance);
|
|
|
253
340
|
const config = new Configuration({
|
|
254
341
|
basePath:
|
|
255
342
|
process.env.NODE_ENV === 'production'
|
|
256
|
-
? 'https://api.yourdomain.com'
|
|
257
|
-
: 'http://localhost:
|
|
343
|
+
? 'https://fitness-api.yourdomain.com'
|
|
344
|
+
: 'http://localhost:42070/api',
|
|
258
345
|
timeout: 10000,
|
|
259
346
|
accessToken: process.env.API_TOKEN,
|
|
260
347
|
});
|
|
@@ -263,102 +350,75 @@ const config = new Configuration({
|
|
|
263
350
|
## 🌍 Pagination & Filtering
|
|
264
351
|
|
|
265
352
|
```typescript
|
|
266
|
-
const
|
|
353
|
+
const measurements = await authenticatedMeasurementsApi.getAllByUserId({
|
|
267
354
|
// Pagination
|
|
268
355
|
offset: 0,
|
|
269
356
|
limit: 25,
|
|
270
357
|
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
// Sorting
|
|
276
|
-
orderBy: 'createdAt', // createdAt, updatedAt, username, email
|
|
358
|
+
// Date filtering
|
|
359
|
+
fromDate: '2025-01-01',
|
|
360
|
+
toDate: '2025-01-31',
|
|
277
361
|
});
|
|
278
362
|
|
|
279
|
-
console.log(`${
|
|
280
|
-
console.log(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
## 🧪 Testing
|
|
284
|
-
|
|
285
|
-
### Mock with MSW
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
import { rest } from 'msw';
|
|
289
|
-
import { setupServer } from 'msw/node';
|
|
290
|
-
import { UserV1Api } from '@dimrev4/user-core';
|
|
291
|
-
|
|
292
|
-
const server = setupServer(
|
|
293
|
-
rest.get('*/api/users/v1/self', (req, res, ctx) => {
|
|
294
|
-
return res(
|
|
295
|
-
ctx.status(200),
|
|
296
|
-
ctx.json({
|
|
297
|
-
id: '1',
|
|
298
|
-
username: 'testuser',
|
|
299
|
-
email: 'test@example.com',
|
|
300
|
-
createdAt: new Date().toISOString(),
|
|
301
|
-
updatedAt: new Date().toISOString(),
|
|
302
|
-
deletedAt: null,
|
|
303
|
-
userToGroup: [],
|
|
304
|
-
}),
|
|
305
|
-
);
|
|
306
|
-
}),
|
|
363
|
+
console.log(`${measurements.data.totalItems} measurements found`);
|
|
364
|
+
console.log(
|
|
365
|
+
`Page ${measurements.data.currentPage} of ${measurements.data.totalPages}`,
|
|
307
366
|
);
|
|
308
367
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
expect(response.data.username).toBe('testuser');
|
|
318
|
-
});
|
|
368
|
+
// Group measurements with filtering
|
|
369
|
+
const groupMeasurements =
|
|
370
|
+
await authenticatedMeasurementsApi.getAllByUserIdAdmin('group-id', {
|
|
371
|
+
offset: 0,
|
|
372
|
+
limit: 50,
|
|
373
|
+
fromDate: '2025-01-01',
|
|
374
|
+
toDate: '2025-01-31',
|
|
375
|
+
});
|
|
319
376
|
```
|
|
320
377
|
|
|
321
378
|
## 🚨 Common Issues
|
|
322
379
|
|
|
323
|
-
| Issue
|
|
324
|
-
|
|
|
325
|
-
| 401 Unauthorized
|
|
326
|
-
| 403 Forbidden
|
|
327
|
-
| CORS Error
|
|
328
|
-
| Token not sent
|
|
329
|
-
| Validation Error (400)
|
|
380
|
+
| Issue | Solution |
|
|
381
|
+
| ------------------------- | ------------------------------------------- |
|
|
382
|
+
| 401 Unauthorized | Set accessToken in Configuration |
|
|
383
|
+
| 403 Forbidden | Check group permissions for group endpoints |
|
|
384
|
+
| CORS Error | Configure API CORS or use proxy in dev |
|
|
385
|
+
| Token not sent | Use accessToken parameter in config |
|
|
386
|
+
| Validation Error (400) | Check request body against DTO schema |
|
|
387
|
+
| 404 Measurement Not Found | Verify measurement ID and user access |
|
|
330
388
|
|
|
331
389
|
### Token Management Helper
|
|
332
390
|
|
|
333
391
|
```typescript
|
|
334
|
-
class
|
|
335
|
-
static login(email: string, password: string, config: Configuration) {
|
|
392
|
+
class FitnessAuthManager {
|
|
393
|
+
static async login(email: string, password: string, config: Configuration) {
|
|
336
394
|
const authApi = new AuthV1Api(config);
|
|
337
395
|
return authApi
|
|
338
396
|
.authV1ControllerLogin({ email, password })
|
|
339
397
|
.then((response) => {
|
|
340
398
|
config.accessToken = response.data.accessToken;
|
|
341
|
-
localStorage.setItem('
|
|
399
|
+
localStorage.setItem('fitness_access_token', response.data.accessToken);
|
|
342
400
|
return response.data.user;
|
|
343
401
|
});
|
|
344
402
|
}
|
|
345
403
|
|
|
346
404
|
static logout(config: Configuration) {
|
|
347
|
-
localStorage.removeItem('
|
|
405
|
+
localStorage.removeItem('fitness_access_token');
|
|
348
406
|
config.accessToken = '';
|
|
349
407
|
}
|
|
350
408
|
|
|
351
409
|
static getAuthenticatedConfig(baseUrl: string): Configuration {
|
|
352
410
|
return new Configuration({
|
|
353
411
|
basePath: baseUrl,
|
|
354
|
-
accessToken: localStorage.getItem('
|
|
412
|
+
accessToken: localStorage.getItem('fitness_access_token') || '',
|
|
355
413
|
});
|
|
356
414
|
}
|
|
357
415
|
}
|
|
358
416
|
|
|
359
417
|
// Usage
|
|
360
|
-
const config =
|
|
361
|
-
|
|
418
|
+
const config = FitnessAuthManager.getAuthenticatedConfig(
|
|
419
|
+
'https://fitness-api.example.com',
|
|
420
|
+
);
|
|
421
|
+
const measurementsApi = new MeasurementsV1Api(config);
|
|
362
422
|
```
|
|
363
423
|
|
|
364
424
|
## 📊 TypeScript Types
|
|
@@ -366,41 +426,134 @@ const userApi = new UserV1Api(config);
|
|
|
366
426
|
Key interfaces for type safety:
|
|
367
427
|
|
|
368
428
|
```typescript
|
|
369
|
-
interface
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
429
|
+
interface CreateMeasurementRequestDto {
|
|
430
|
+
date: string; // ISO date string
|
|
431
|
+
weightKG: number;
|
|
432
|
+
heightCM: number;
|
|
433
|
+
bmi: number;
|
|
373
434
|
}
|
|
374
435
|
|
|
375
|
-
interface
|
|
436
|
+
interface MeasurementDto {
|
|
376
437
|
id: string;
|
|
377
|
-
|
|
378
|
-
|
|
438
|
+
date: string;
|
|
439
|
+
weightKG: number;
|
|
440
|
+
heightCM: number;
|
|
441
|
+
bmi: number;
|
|
442
|
+
userId: string;
|
|
379
443
|
createdAt: string;
|
|
380
444
|
updatedAt: string;
|
|
381
445
|
deletedAt: string | null;
|
|
382
|
-
userToGroup: UserToGroupDetailsDto[];
|
|
383
446
|
}
|
|
384
447
|
|
|
385
|
-
interface
|
|
448
|
+
interface GetMeasurementsResponseDto {
|
|
449
|
+
measurements: MeasurementDto[];
|
|
450
|
+
totalItems: number;
|
|
451
|
+
currentPage: number;
|
|
452
|
+
totalPages: number;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
interface UpdateMeasurementRequestDto {
|
|
456
|
+
date?: string;
|
|
457
|
+
weightKG?: number;
|
|
458
|
+
heightCM?: number;
|
|
459
|
+
bmi?: number;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
interface DeleteMeasurementResponseDto {
|
|
463
|
+
success: boolean;
|
|
464
|
+
message: string;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
interface SavedMealDto {
|
|
386
468
|
id: string;
|
|
387
469
|
name: string;
|
|
470
|
+
description: string;
|
|
471
|
+
recipe: string;
|
|
472
|
+
imgUrl: string;
|
|
473
|
+
MealType: 'BREAKFAST' | 'LUNCH' | 'DINNER' | 'SNACK' | 'DESSERT';
|
|
474
|
+
FoodCategory:
|
|
475
|
+
| 'DAIRY'
|
|
476
|
+
| 'PROTEIN'
|
|
477
|
+
| 'CARBOHYDRATES'
|
|
478
|
+
| 'FRUITS'
|
|
479
|
+
| 'VEGETABLES'
|
|
480
|
+
| 'FATS'
|
|
481
|
+
| 'GRAINS'
|
|
482
|
+
| 'BEVERAGES'
|
|
483
|
+
| 'SWEETS';
|
|
484
|
+
calories: number;
|
|
485
|
+
totalFatGrams: number;
|
|
486
|
+
saturatedFatGrams: number;
|
|
487
|
+
transFatGrams: number;
|
|
488
|
+
cholesterolMg: number;
|
|
489
|
+
sodiumMg: number;
|
|
490
|
+
totalCarbohydrateGrams: number;
|
|
491
|
+
dietaryFiberGrams: number;
|
|
492
|
+
totalSugarGrams: number;
|
|
493
|
+
addedSugarGrams: number;
|
|
494
|
+
proteinGrams: number;
|
|
495
|
+
vitaminDGrams: number;
|
|
496
|
+
calciumGrams: number;
|
|
497
|
+
ironGrams: number;
|
|
498
|
+
potassiumGrams: number;
|
|
388
499
|
createdAt: string;
|
|
389
500
|
updatedAt: string;
|
|
390
501
|
deletedAt: string | null;
|
|
391
|
-
userToGroup: UserToGroupDetailsDto[];
|
|
392
502
|
}
|
|
393
503
|
|
|
394
|
-
interface
|
|
395
|
-
|
|
504
|
+
interface UserMealDto {
|
|
505
|
+
id: string;
|
|
506
|
+
name: string;
|
|
507
|
+
description: string;
|
|
508
|
+
recipe: string;
|
|
509
|
+
imgUrl: string;
|
|
510
|
+
MealType: 'BREAKFAST' | 'LUNCH' | 'DINNER' | 'SNACK' | 'DESSERT';
|
|
511
|
+
FoodCategory:
|
|
512
|
+
| 'DAIRY'
|
|
513
|
+
| 'PROTEIN'
|
|
514
|
+
| 'CARBOHYDRATES'
|
|
515
|
+
| 'FRUITS'
|
|
516
|
+
| 'VEGETABLES'
|
|
517
|
+
| 'FATS'
|
|
518
|
+
| 'GRAINS'
|
|
519
|
+
| 'BEVERAGES'
|
|
520
|
+
| 'SWEETS';
|
|
521
|
+
calories: number;
|
|
522
|
+
totalFatGrams: number;
|
|
523
|
+
saturatedFatGrams: number;
|
|
524
|
+
transFatGrams: number;
|
|
525
|
+
cholesterolMg: number;
|
|
526
|
+
sodiumMg: number;
|
|
527
|
+
totalCarbohydrateGrams: number;
|
|
528
|
+
dietaryFiberGrams: number;
|
|
529
|
+
totalSugarGrams: number;
|
|
530
|
+
addedSugarGrams: number;
|
|
531
|
+
proteinGrams: number;
|
|
532
|
+
vitaminDGrams: number;
|
|
533
|
+
calciumGrams: number;
|
|
534
|
+
ironGrams: number;
|
|
535
|
+
potassiumGrams: number;
|
|
536
|
+
userId: string;
|
|
537
|
+
createdAt: string;
|
|
538
|
+
updatedAt: string;
|
|
539
|
+
deletedAt: string | null;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
interface UserMealConsumptionDto {
|
|
543
|
+
id: string;
|
|
396
544
|
userId: string;
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
545
|
+
mealId: string;
|
|
546
|
+
date: string;
|
|
547
|
+
createdAt: string;
|
|
548
|
+
updatedAt: string;
|
|
549
|
+
deletedAt: string | null;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
interface GetMeResponseDto {
|
|
553
|
+
id: string;
|
|
554
|
+
username: string;
|
|
555
|
+
email: string;
|
|
556
|
+
// ... other user properties from User Core API
|
|
404
557
|
}
|
|
405
558
|
```
|
|
406
559
|
|
|
@@ -415,9 +568,9 @@ interface UserToGroupDetailsDto {
|
|
|
415
568
|
|
|
416
569
|
1. Fork the repository
|
|
417
570
|
2. Update OpenAPI spec for new features
|
|
418
|
-
3. Run
|
|
571
|
+
3. Run `pnpm run sdk:generate` to rebuild SDK
|
|
419
572
|
4. Submit pull request with tests
|
|
420
573
|
|
|
421
574
|
---
|
|
422
575
|
|
|
423
|
-
Auto-generated from
|
|
576
|
+
Auto-generated from Fitness V3 Backend API v0.0.3 | Last Updated: Oct 2025
|