@openlifelog/sdk 1.0.0

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/index.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * OpenLifeLog TypeScript SDK
3
+ *
4
+ * A comprehensive TypeScript SDK for the OpenLifeLog API - the complete
5
+ * fitness and nutrition tracking platform.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ // Main client
11
+ export { OpenLifeLog } from './client';
12
+
13
+ // Configuration
14
+ export type { OpenLifeLogConfig } from './config';
15
+
16
+ // All types
17
+ export * from './types';
18
+
19
+ // Constants (metrics, etc.)
20
+ export * from './constants/metrics';
21
+
22
+ // Utilities (for advanced usage)
23
+ export {
24
+ // Errors
25
+ OpenLifeLogError,
26
+ AuthenticationError,
27
+ AuthorizationError,
28
+ NotFoundError,
29
+ ValidationError,
30
+ RateLimitError,
31
+ ServerError,
32
+ NetworkError,
33
+ TimeoutError,
34
+ UnitConversionError,
35
+ // Unit conversion
36
+ WeightConverter,
37
+ DistanceConverter,
38
+ HeightConverter,
39
+ UnitConverter,
40
+ createUnitConverter,
41
+ // Pagination
42
+ PaginatedIterator,
43
+ createPaginatedIterator,
44
+ fetchAllPages,
45
+ hasMorePages,
46
+ } from './utils';
47
+
48
+ // Default export
49
+ export { OpenLifeLog as default } from './client';
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@openlifelog/sdk",
3
+ "version": "1.0.0",
4
+ "description": "TypeScript SDK for the OpenLifeLog API - A comprehensive fitness and nutrition tracking platform",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup index.ts --format cjs,esm --dts",
17
+ "dev": "tsup index.ts --format cjs,esm --dts --watch",
18
+ "test": "jest",
19
+ "lint": "eslint . --ext .ts",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "keywords": [
23
+ "openlifelog",
24
+ "fitness",
25
+ "nutrition",
26
+ "workout",
27
+ "tracking",
28
+ "health",
29
+ "sdk",
30
+ "typescript",
31
+ "api-client"
32
+ ],
33
+ "author": "OpenLifeLog",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/kukicado/openlifelog.git",
38
+ "directory": "src/sdk/typescript"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/kukicado/openlifelog/issues"
42
+ },
43
+ "homepage": "https://github.com/kukicado/openlifelog#readme",
44
+ "devDependencies": {
45
+ "@types/node": "^20.0.0",
46
+ "tsup": "^8.0.0",
47
+ "typescript": "^5.3.0"
48
+ },
49
+ "dependencies": {},
50
+ "engines": {
51
+ "node": ">=18.0.0"
52
+ }
53
+ }
@@ -0,0 +1,26 @@
1
+ import type { HttpClient } from '../utils/http';
2
+ import type { FoodInsightsResponse, GetFoodInsightsParams } from '../types';
3
+
4
+ /**
5
+ * AI resource
6
+ * Handles AI-powered insights and recommendations
7
+ */
8
+ export class AIResource {
9
+ constructor(private http: HttpClient) {}
10
+
11
+ /**
12
+ * Get AI-generated nutrition insights
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const insights = await client.ai.getFoodInsights({
17
+ * startDate: '2024-01-01',
18
+ * endDate: '2024-01-15'
19
+ * });
20
+ * ```
21
+ */
22
+ async getFoodInsights(params?: GetFoodInsightsParams): Promise<FoodInsightsResponse> {
23
+ const response = await this.http.get<FoodInsightsResponse>('/v1/ai/food-insights', params);
24
+ return response.data;
25
+ }
26
+ }
@@ -0,0 +1,98 @@
1
+ import type { HttpClient } from '../utils/http';
2
+ import type {
3
+ SignupRequest,
4
+ LoginRequest,
5
+ AuthResponse,
6
+ PasswordResetRequest,
7
+ PasswordResetConfirm,
8
+ } from '../types';
9
+
10
+ /**
11
+ * Authentication resource
12
+ * Handles user authentication operations
13
+ */
14
+ export class AuthResource {
15
+ constructor(private http: HttpClient) {}
16
+
17
+ /**
18
+ * Sign up a new user
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const { token, user } = await client.auth.signup({
23
+ * name: 'John Doe',
24
+ * email: 'john@example.com',
25
+ * password: 'securePassword123'
26
+ * });
27
+ * ```
28
+ */
29
+ async signup(request: SignupRequest): Promise<AuthResponse> {
30
+ const response = await this.http.post<AuthResponse>('/v1/auth/signup', request);
31
+
32
+ // Automatically set the API key after successful signup
33
+ this.http.setApiKey(response.data.token);
34
+
35
+ return response.data;
36
+ }
37
+
38
+ /**
39
+ * Log in an existing user
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const { token, user } = await client.auth.login({
44
+ * email: 'john@example.com',
45
+ * password: 'securePassword123'
46
+ * });
47
+ * ```
48
+ */
49
+ async login(request: LoginRequest): Promise<AuthResponse> {
50
+ const response = await this.http.post<AuthResponse>('/v1/auth/login', request);
51
+
52
+ // Automatically set the API key after successful login
53
+ this.http.setApiKey(response.data.token);
54
+
55
+ return response.data;
56
+ }
57
+
58
+ /**
59
+ * Request a password reset
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * await client.auth.requestPasswordReset({
64
+ * email: 'john@example.com'
65
+ * });
66
+ * ```
67
+ */
68
+ async requestPasswordReset(request: PasswordResetRequest): Promise<void> {
69
+ await this.http.post('/v1/auth/password-reset/request', request);
70
+ }
71
+
72
+ /**
73
+ * Confirm password reset with token
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * await client.auth.confirmPasswordReset({
78
+ * token: 'reset-token-from-email',
79
+ * newPassword: 'newSecurePassword123'
80
+ * });
81
+ * ```
82
+ */
83
+ async confirmPasswordReset(request: PasswordResetConfirm): Promise<void> {
84
+ await this.http.post('/v1/auth/password-reset/confirm', request);
85
+ }
86
+
87
+ /**
88
+ * Log out the current user (clears the API key)
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * client.auth.logout();
93
+ * ```
94
+ */
95
+ logout(): void {
96
+ this.http.setApiKey('');
97
+ }
98
+ }
@@ -0,0 +1,112 @@
1
+ import type { HttpClient } from '../utils/http';
2
+ import type {
3
+ Exercise,
4
+ CreateExerciseRequest,
5
+ UpdateExerciseRequest,
6
+ ListExercisesParams,
7
+ ListResponse,
8
+ CountResponse,
9
+ } from '../types';
10
+ import { createPaginatedIterator, type PaginatedIterator } from '../utils/pagination';
11
+
12
+ /**
13
+ * Exercises resource
14
+ * Handles exercise database operations
15
+ */
16
+ export class ExercisesResource {
17
+ constructor(private http: HttpClient) {}
18
+
19
+ /**
20
+ * List exercises with filtering
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const { data } = await client.exercises.list({
25
+ * category: 'strength',
26
+ * muscleGroup: 'chest'
27
+ * });
28
+ * ```
29
+ */
30
+ async list(params?: ListExercisesParams): Promise<ListResponse<Exercise>> {
31
+ const response = await this.http.get<ListResponse<Exercise>>('/v1/exercises', params);
32
+ return response.data;
33
+ }
34
+
35
+ /**
36
+ * List exercises with automatic pagination
37
+ */
38
+ listAutoPaginate(params?: ListExercisesParams): PaginatedIterator<Exercise> {
39
+ return createPaginatedIterator((cursor) =>
40
+ this.list({ ...params, cursor })
41
+ );
42
+ }
43
+
44
+ /**
45
+ * Get total count of exercises
46
+ */
47
+ async count(): Promise<CountResponse> {
48
+ const response = await this.http.get<CountResponse>('/v1/exercises/count');
49
+ return response.data;
50
+ }
51
+
52
+ /**
53
+ * Search exercises by name
54
+ */
55
+ async search(params: { q: string; limit?: number; cursor?: string }): Promise<ListResponse<Exercise>> {
56
+ const response = await this.http.get<ListResponse<Exercise>>('/v1/exercises/search', params);
57
+ return response.data;
58
+ }
59
+
60
+ /**
61
+ * Get specific exercise by ID
62
+ */
63
+ async get(exerciseId: string): Promise<Exercise> {
64
+ const response = await this.http.get<Exercise>(`/v1/exercises/${exerciseId}`);
65
+ return response.data;
66
+ }
67
+
68
+ /**
69
+ * Create a new exercise
70
+ */
71
+ async create(request: CreateExerciseRequest): Promise<Exercise> {
72
+ const response = await this.http.post<Exercise>('/v1/exercises', request);
73
+ return response.data;
74
+ }
75
+
76
+ /**
77
+ * Update an existing exercise
78
+ */
79
+ async update(exerciseId: string, request: UpdateExerciseRequest): Promise<Exercise> {
80
+ const response = await this.http.put<Exercise>(`/v1/exercises/${exerciseId}`, request);
81
+ return response.data;
82
+ }
83
+
84
+ /**
85
+ * Delete an exercise
86
+ */
87
+ async delete(exerciseId: string): Promise<void> {
88
+ await this.http.delete(`/v1/exercises/${exerciseId}`);
89
+ }
90
+
91
+ /**
92
+ * Get favorite exercises
93
+ */
94
+ async getFavorites(params?: ListExercisesParams): Promise<ListResponse<Exercise>> {
95
+ const response = await this.http.get<ListResponse<Exercise>>('/v1/exercises/favorites', params);
96
+ return response.data;
97
+ }
98
+
99
+ /**
100
+ * Add exercise to favorites
101
+ */
102
+ async addToFavorites(exerciseId: string): Promise<void> {
103
+ await this.http.post(`/v1/exercises/${exerciseId}/favorite`);
104
+ }
105
+
106
+ /**
107
+ * Remove exercise from favorites
108
+ */
109
+ async removeFromFavorites(exerciseId: string): Promise<void> {
110
+ await this.http.delete(`/v1/exercises/${exerciseId}/favorite`);
111
+ }
112
+ }
@@ -0,0 +1,132 @@
1
+ import type { HttpClient } from '../utils/http';
2
+ import type {
3
+ FoodLog,
4
+ CreateFoodLogRequest,
5
+ UpdateFoodLogRequest,
6
+ QuickEntryFoodLogRequest,
7
+ ListFoodLogsParams,
8
+ DailyNutritionSummary,
9
+ GetDailySummaryParams,
10
+ } from '../types';
11
+
12
+ /**
13
+ * Food Logs resource
14
+ * Handles food logging and nutrition tracking
15
+ */
16
+ export class FoodLogsResource {
17
+ constructor(private http: HttpClient) {}
18
+
19
+ /**
20
+ * List food log entries with filtering
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const logs = await client.foodLogs.list({
25
+ * date: '2024-01-15',
26
+ * mealType: 'lunch'
27
+ * });
28
+ * ```
29
+ */
30
+ async list(params?: ListFoodLogsParams): Promise<FoodLog[]> {
31
+ const response = await this.http.get<FoodLog[]>('/v1/food-logs', params);
32
+ return response.data;
33
+ }
34
+
35
+ /**
36
+ * Get daily nutrition summary
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const summary = await client.foodLogs.getDailySummary({
41
+ * date: '2024-01-15'
42
+ * });
43
+ * console.log(`Total calories: ${summary.totalCalories}`);
44
+ * ```
45
+ */
46
+ async getDailySummary(params?: GetDailySummaryParams): Promise<DailyNutritionSummary> {
47
+ const response = await this.http.get<DailyNutritionSummary>('/v1/food-logs/summary', params);
48
+ return response.data;
49
+ }
50
+
51
+ /**
52
+ * Get specific food log entry
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const log = await client.foodLogs.get('log-id');
57
+ * ```
58
+ */
59
+ async get(logId: string): Promise<FoodLog> {
60
+ const response = await this.http.get<FoodLog>(`/v1/food-logs/${logId}`);
61
+ return response.data;
62
+ }
63
+
64
+ /**
65
+ * Create a food log entry
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const log = await client.foodLogs.create({
70
+ * foodId: 'food-uuid',
71
+ * name: 'Chicken Breast',
72
+ * servingSizeName: 'breast (200g)',
73
+ * quantity: 1.5,
74
+ * unitGrams: 200,
75
+ * mealType: 'lunch',
76
+ * notes: 'Grilled with olive oil'
77
+ * });
78
+ * ```
79
+ */
80
+ async create(request: CreateFoodLogRequest): Promise<FoodLog> {
81
+ const response = await this.http.post<FoodLog>('/v1/food-logs', request);
82
+ return response.data;
83
+ }
84
+
85
+ /**
86
+ * Quick entry food log with just name and nutrients
87
+ * Creates a food log entry without creating a food (one-off entry)
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const log = await client.foodLogs.quickEntry({
92
+ * name: 'Homemade Salad',
93
+ * protein: 15,
94
+ * carbohydrates: 20,
95
+ * fat: 10,
96
+ * mealType: 'lunch'
97
+ * });
98
+ * ```
99
+ */
100
+ async quickEntry(request: QuickEntryFoodLogRequest): Promise<FoodLog> {
101
+ const response = await this.http.post<FoodLog>('/v1/food-logs-quick-entry', request);
102
+ return response.data;
103
+ }
104
+
105
+ /**
106
+ * Update a food log entry
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const log = await client.foodLogs.update('log-id', {
111
+ * quantity: 2,
112
+ * notes: 'Updated portion size'
113
+ * });
114
+ * ```
115
+ */
116
+ async update(logId: string, request: UpdateFoodLogRequest): Promise<FoodLog> {
117
+ const response = await this.http.put<FoodLog>(`/v1/food-logs/${logId}`, request);
118
+ return response.data;
119
+ }
120
+
121
+ /**
122
+ * Delete a food log entry
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * await client.foodLogs.delete('log-id');
127
+ * ```
128
+ */
129
+ async delete(logId: string): Promise<void> {
130
+ await this.http.delete(`/v1/food-logs/${logId}`);
131
+ }
132
+ }
@@ -0,0 +1,185 @@
1
+ import type { HttpClient } from '../utils/http';
2
+ import type {
3
+ Food,
4
+ CreateFoodRequest,
5
+ UpdateFoodRequest,
6
+ ListFoodsParams,
7
+ ListResponse,
8
+ CountResponse,
9
+ } from '../types';
10
+ import { createPaginatedIterator, type PaginatedIterator } from '../utils/pagination';
11
+
12
+ /**
13
+ * Foods resource
14
+ * Handles food database operations
15
+ */
16
+ export class FoodsResource {
17
+ constructor(private http: HttpClient) {}
18
+
19
+ /**
20
+ * List foods with pagination and search
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const { data, pageInfo } = await client.foods.list({
25
+ * limit: 20,
26
+ * search: 'chicken'
27
+ * });
28
+ * ```
29
+ */
30
+ async list(params?: ListFoodsParams): Promise<ListResponse<Food>> {
31
+ const response = await this.http.get<ListResponse<Food>>('/v1/foods', params);
32
+ return response.data;
33
+ }
34
+
35
+ /**
36
+ * List foods with automatic pagination
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * for await (const food of client.foods.listAutoPaginate({ limit: 100 })) {
41
+ * console.log(food.name);
42
+ * }
43
+ * ```
44
+ */
45
+ listAutoPaginate(params?: ListFoodsParams): PaginatedIterator<Food> {
46
+ return createPaginatedIterator((cursor) =>
47
+ this.list({ ...params, cursor })
48
+ );
49
+ }
50
+
51
+ /**
52
+ * Get total count of foods
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const { count } = await client.foods.count();
57
+ * console.log(`Database has ${count} foods`);
58
+ * ```
59
+ */
60
+ async count(): Promise<CountResponse> {
61
+ const response = await this.http.get<CountResponse>('/v1/foods/count');
62
+ return response.data;
63
+ }
64
+
65
+ /**
66
+ * Search foods by name or brand
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const { data } = await client.foods.search({
71
+ * q: 'chicken breast',
72
+ * limit: 10
73
+ * });
74
+ * ```
75
+ */
76
+ async search(params: { q: string; limit?: number; cursor?: string }): Promise<ListResponse<Food>> {
77
+ const response = await this.http.get<ListResponse<Food>>('/v1/foods/search', params);
78
+ return response.data;
79
+ }
80
+
81
+ /**
82
+ * Get specific food by ID
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const food = await client.foods.get('food-id');
87
+ * console.log(food.nutrients);
88
+ * ```
89
+ */
90
+ async get(foodId: string): Promise<Food> {
91
+ const response = await this.http.get<Food>(`/v1/foods/${foodId}`);
92
+ return response.data;
93
+ }
94
+
95
+ /**
96
+ * Create a new food item
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const food = await client.foods.create({
101
+ * name: 'Custom Protein Shake',
102
+ * type: 'beverage',
103
+ * nutrients: {
104
+ * calories: 300,
105
+ * protein: 40,
106
+ * carbohydrates: 20,
107
+ * fat: 5
108
+ * },
109
+ * servingSizes: [{
110
+ * name: '1 serving',
111
+ * grams: 300,
112
+ * isDefault: true
113
+ * }]
114
+ * });
115
+ * ```
116
+ */
117
+ async create(request: CreateFoodRequest): Promise<Food> {
118
+ const response = await this.http.post<Food>('/v1/foods', request);
119
+ return response.data;
120
+ }
121
+
122
+ /**
123
+ * Update an existing food item
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const food = await client.foods.update('food-id', {
128
+ * description: 'Updated description'
129
+ * });
130
+ * ```
131
+ */
132
+ async update(foodId: string, request: UpdateFoodRequest): Promise<Food> {
133
+ const response = await this.http.put<Food>(`/v1/foods/${foodId}`, request);
134
+ return response.data;
135
+ }
136
+
137
+ /**
138
+ * Delete a food item
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * await client.foods.delete('food-id');
143
+ * ```
144
+ */
145
+ async delete(foodId: string): Promise<void> {
146
+ await this.http.delete(`/v1/foods/${foodId}`);
147
+ }
148
+
149
+ /**
150
+ * Get favorite foods
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * const { data } = await client.foods.getFavorites();
155
+ * ```
156
+ */
157
+ async getFavorites(params?: ListFoodsParams): Promise<ListResponse<Food>> {
158
+ const response = await this.http.get<ListResponse<Food>>('/v1/foods/favorites', params);
159
+ return response.data;
160
+ }
161
+
162
+ /**
163
+ * Add food to favorites
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * await client.foods.addToFavorites('food-id');
168
+ * ```
169
+ */
170
+ async addToFavorites(foodId: string): Promise<void> {
171
+ await this.http.post(`/v1/foods/${foodId}/favorite`);
172
+ }
173
+
174
+ /**
175
+ * Remove food from favorites
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * await client.foods.removeFromFavorites('food-id');
180
+ * ```
181
+ */
182
+ async removeFromFavorites(foodId: string): Promise<void> {
183
+ await this.http.delete(`/v1/foods/${foodId}/favorite`);
184
+ }
185
+ }