@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/EXAMPLES.md +624 -0
- package/README.md +824 -0
- package/client.ts +190 -0
- package/config.ts +96 -0
- package/constants/metrics.ts +116 -0
- package/dist/index.d.mts +1101 -0
- package/dist/index.d.ts +1101 -0
- package/dist/index.js +2023 -0
- package/dist/index.mjs +1969 -0
- package/index.ts +49 -0
- package/package.json +53 -0
- package/resources/ai.ts +26 -0
- package/resources/auth.ts +98 -0
- package/resources/exercises.ts +112 -0
- package/resources/food-logs.ts +132 -0
- package/resources/foods.ts +185 -0
- package/resources/goals.ts +155 -0
- package/resources/metrics.ts +115 -0
- package/resources/programs.ts +123 -0
- package/resources/sessions.ts +142 -0
- package/resources/users.ts +132 -0
- package/resources/workouts.ts +147 -0
- package/tsconfig.json +27 -0
- package/types/ai.ts +55 -0
- package/types/common.ts +177 -0
- package/types/exercise.ts +75 -0
- package/types/food.ts +208 -0
- package/types/goal.ts +169 -0
- package/types/index.ts +17 -0
- package/types/metric.ts +108 -0
- package/types/program.ts +120 -0
- package/types/session.ts +196 -0
- package/types/user.ts +79 -0
- package/types/workout.ts +97 -0
- package/utils/errors.ts +159 -0
- package/utils/http.ts +313 -0
- package/utils/index.ts +8 -0
- package/utils/pagination.ts +106 -0
- package/utils/units.ts +279 -0
package/client.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { mergeConfig, type OpenLifeLogConfig, type ResolvedConfig } from './config';
|
|
2
|
+
import { HttpClient } from './utils/http';
|
|
3
|
+
import { createUnitConverter, type UnitConverter } from './utils/units';
|
|
4
|
+
import { AuthResource } from './resources/auth';
|
|
5
|
+
import { UsersResource } from './resources/users';
|
|
6
|
+
import { FoodsResource } from './resources/foods';
|
|
7
|
+
import { FoodLogsResource } from './resources/food-logs';
|
|
8
|
+
import { ExercisesResource } from './resources/exercises';
|
|
9
|
+
import { WorkoutsResource } from './resources/workouts';
|
|
10
|
+
import { SessionsResource } from './resources/sessions';
|
|
11
|
+
import { ProgramsResource } from './resources/programs';
|
|
12
|
+
import { MetricsResource } from './resources/metrics';
|
|
13
|
+
import { GoalsResource } from './resources/goals';
|
|
14
|
+
import { AIResource } from './resources/ai';
|
|
15
|
+
import type { CreateFoodLogRequest, FoodLog } from './types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* OpenLifeLog SDK Client
|
|
19
|
+
*
|
|
20
|
+
* Main entry point for interacting with the OpenLifeLog API
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { OpenLifeLog } from '@openlifelog/sdk';
|
|
25
|
+
*
|
|
26
|
+
* // Initialize the client
|
|
27
|
+
* const client = new OpenLifeLog({
|
|
28
|
+
* apiKey: 'your-jwt-token',
|
|
29
|
+
* baseUrl: 'http://localhost:8080',
|
|
30
|
+
* autoConvertUnits: true
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Or initialize without API key and login
|
|
34
|
+
* const client = new OpenLifeLog();
|
|
35
|
+
* await client.auth.login({ email: '...', password: '...' });
|
|
36
|
+
*
|
|
37
|
+
* // Use the client
|
|
38
|
+
* const user = await client.users.me();
|
|
39
|
+
* const foods = await client.foods.list();
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export class OpenLifeLog {
|
|
43
|
+
private config: ResolvedConfig;
|
|
44
|
+
private httpClient: HttpClient;
|
|
45
|
+
private unitConverter: UnitConverter;
|
|
46
|
+
|
|
47
|
+
// Resource instances
|
|
48
|
+
public readonly auth: AuthResource;
|
|
49
|
+
public readonly users: UsersResource;
|
|
50
|
+
public readonly foods: FoodsResource;
|
|
51
|
+
public readonly foodLogs: FoodLogsResource;
|
|
52
|
+
public readonly exercises: ExercisesResource;
|
|
53
|
+
public readonly workouts: WorkoutsResource;
|
|
54
|
+
public readonly sessions: SessionsResource;
|
|
55
|
+
public readonly programs: ProgramsResource;
|
|
56
|
+
public readonly metrics: MetricsResource;
|
|
57
|
+
public readonly goals: GoalsResource;
|
|
58
|
+
public readonly ai: AIResource;
|
|
59
|
+
|
|
60
|
+
constructor(config: OpenLifeLogConfig = {}) {
|
|
61
|
+
this.config = mergeConfig(config);
|
|
62
|
+
this.httpClient = new HttpClient(this.config);
|
|
63
|
+
this.unitConverter = createUnitConverter(this.config.measurementSystem);
|
|
64
|
+
|
|
65
|
+
// Initialize all resources
|
|
66
|
+
this.auth = new AuthResource(this.httpClient);
|
|
67
|
+
this.users = new UsersResource(this.httpClient);
|
|
68
|
+
this.foods = new FoodsResource(this.httpClient);
|
|
69
|
+
this.foodLogs = new FoodLogsResource(this.httpClient);
|
|
70
|
+
this.exercises = new ExercisesResource(this.httpClient);
|
|
71
|
+
this.workouts = new WorkoutsResource(this.httpClient);
|
|
72
|
+
this.sessions = new SessionsResource(this.httpClient);
|
|
73
|
+
this.programs = new ProgramsResource(this.httpClient);
|
|
74
|
+
this.metrics = new MetricsResource(this.httpClient);
|
|
75
|
+
this.goals = new GoalsResource(this.httpClient);
|
|
76
|
+
this.ai = new AIResource(this.httpClient);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Update the API key (JWT token)
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* client.setApiKey('new-jwt-token');
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
setApiKey(apiKey: string): void {
|
|
88
|
+
this.httpClient.setApiKey(apiKey);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the current API key
|
|
93
|
+
*/
|
|
94
|
+
getApiKey(): string | undefined {
|
|
95
|
+
return this.httpClient.getApiKey();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get the unit converter instance
|
|
100
|
+
*/
|
|
101
|
+
getUnitConverter(): UnitConverter {
|
|
102
|
+
return this.unitConverter;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Update the measurement system preference
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* client.setMeasurementSystem('imperial');
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
setMeasurementSystem(system: 'metric' | 'imperial'): void {
|
|
114
|
+
this.config.measurementSystem = system;
|
|
115
|
+
this.unitConverter.setMeasurementSystem(system);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get the current measurement system
|
|
120
|
+
*/
|
|
121
|
+
getMeasurementSystem(): 'metric' | 'imperial' {
|
|
122
|
+
return this.config.measurementSystem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Convenience method: Log food (combines food lookup and logging)
|
|
127
|
+
*
|
|
128
|
+
* This is a high-level method that developers love - simple and intuitive.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const log = await client.logFood({
|
|
133
|
+
* foodId: 'food-uuid',
|
|
134
|
+
* name: 'Chicken Breast',
|
|
135
|
+
* servingSizeName: 'breast (200g)',
|
|
136
|
+
* quantity: 1.5,
|
|
137
|
+
* mealType: 'lunch',
|
|
138
|
+
* notes: 'Grilled with olive oil'
|
|
139
|
+
* });
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
async logFood(request: CreateFoodLogRequest): Promise<FoodLog> {
|
|
143
|
+
return this.foodLogs.create(request);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Convenience method: Get today's nutrition summary
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* const summary = await client.getTodayNutrition();
|
|
152
|
+
* console.log(`Calories: ${summary.totalCalories}`);
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
async getTodayNutrition() {
|
|
156
|
+
const today = new Date().toISOString().split('T')[0];
|
|
157
|
+
return this.foodLogs.getDailySummary({ date: today });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Convenience method: Get today's goal progress
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const progress = await client.getTodayProgress();
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
async getTodayProgress() {
|
|
169
|
+
return this.goals.getProgress();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Convenience method: Get today's nutrition progress
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const progress = await client.getTodayNutritionProgress();
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
async getTodayNutritionProgress() {
|
|
181
|
+
return this.goals.getNutritionProgress();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Check if user is authenticated
|
|
186
|
+
*/
|
|
187
|
+
isAuthenticated(): boolean {
|
|
188
|
+
return !!this.httpClient.getApiKey();
|
|
189
|
+
}
|
|
190
|
+
}
|
package/config.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { MeasurementSystem } from './types/common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the OpenLifeLog SDK
|
|
5
|
+
*/
|
|
6
|
+
export interface OpenLifeLogConfig {
|
|
7
|
+
/**
|
|
8
|
+
* API key (JWT token) for authenticated requests.
|
|
9
|
+
* Can be omitted if using auth methods to obtain token.
|
|
10
|
+
*/
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for the API
|
|
15
|
+
* @default "https://api.openlifelog.com"
|
|
16
|
+
*/
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Measurement system preference (metric or imperial)
|
|
21
|
+
* @default "metric"
|
|
22
|
+
*/
|
|
23
|
+
measurementSystem?: MeasurementSystem;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Automatically convert units based on measurement system preference
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
autoConvertUnits?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Request timeout in milliseconds
|
|
33
|
+
* @default 30000 (30 seconds)
|
|
34
|
+
*/
|
|
35
|
+
timeout?: number;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maximum number of retry attempts for failed requests
|
|
39
|
+
* @default 3
|
|
40
|
+
*/
|
|
41
|
+
maxRetries?: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Enable automatic retries for network errors and 5xx errors
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
enableRetries?: boolean;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Custom headers to include in all requests
|
|
51
|
+
*/
|
|
52
|
+
headers?: Record<string, string>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Enable debug logging
|
|
56
|
+
* @default false
|
|
57
|
+
*/
|
|
58
|
+
debug?: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Custom fetch implementation (useful for Node.js < 18 or testing)
|
|
62
|
+
*/
|
|
63
|
+
fetch?: typeof fetch;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Default configuration values
|
|
68
|
+
*/
|
|
69
|
+
export const DEFAULT_CONFIG: Required<Omit<OpenLifeLogConfig, 'apiKey' | 'fetch' | 'headers'>> = {
|
|
70
|
+
baseUrl: 'https://api.openlifelog.com',
|
|
71
|
+
measurementSystem: 'metric',
|
|
72
|
+
autoConvertUnits: true,
|
|
73
|
+
timeout: 30000,
|
|
74
|
+
maxRetries: 3,
|
|
75
|
+
enableRetries: true,
|
|
76
|
+
debug: false,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resolved configuration with all defaults applied
|
|
81
|
+
*/
|
|
82
|
+
export type ResolvedConfig = Required<Omit<OpenLifeLogConfig, 'apiKey'>> & { apiKey?: string };
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Merge user config with defaults
|
|
86
|
+
*/
|
|
87
|
+
export function mergeConfig(userConfig: OpenLifeLogConfig): ResolvedConfig {
|
|
88
|
+
return {
|
|
89
|
+
...DEFAULT_CONFIG,
|
|
90
|
+
...userConfig,
|
|
91
|
+
apiKey: userConfig.apiKey,
|
|
92
|
+
headers: userConfig.headers || {},
|
|
93
|
+
// Bind fetch to globalThis to preserve context
|
|
94
|
+
fetch: userConfig.fetch || globalThis.fetch.bind(globalThis),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metric definitions matching the database reference_data.sql
|
|
3
|
+
* These are the available metrics that users can track
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface MetricDefinition {
|
|
7
|
+
key: string;
|
|
8
|
+
displayName: string;
|
|
9
|
+
category: 'body' | 'activity' | 'sleep' | 'vital' | 'wellness';
|
|
10
|
+
unit: string;
|
|
11
|
+
aggregation: 'last' | 'sum' | 'avg' | 'min' | 'max';
|
|
12
|
+
imperialUnit?: string;
|
|
13
|
+
imperialConversion?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Body Metrics - measurements related to body composition and physical attributes
|
|
18
|
+
*/
|
|
19
|
+
export const BODY_METRICS: MetricDefinition[] = [
|
|
20
|
+
{ key: 'height', displayName: 'Height', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
21
|
+
{ key: 'weight', displayName: 'Body Weight', category: 'body', unit: 'kg', aggregation: 'last', imperialUnit: 'lbs', imperialConversion: 2.20462 },
|
|
22
|
+
{ key: 'body_fat', displayName: 'Body Fat %', category: 'body', unit: '%', aggregation: 'last' },
|
|
23
|
+
{ key: 'muscle_mass', displayName: 'Muscle Mass', category: 'body', unit: 'kg', aggregation: 'last', imperialUnit: 'lbs', imperialConversion: 2.20462 },
|
|
24
|
+
{ key: 'bone_mass', displayName: 'Bone Mass', category: 'body', unit: 'kg', aggregation: 'last', imperialUnit: 'lbs', imperialConversion: 2.20462 },
|
|
25
|
+
{ key: 'body_water', displayName: 'Body Water %', category: 'body', unit: '%', aggregation: 'last' },
|
|
26
|
+
{ key: 'bmi', displayName: 'BMI', category: 'body', unit: 'kg/m²', aggregation: 'last' },
|
|
27
|
+
{ key: 'waist', displayName: 'Waist Circumference', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
28
|
+
{ key: 'hip', displayName: 'Hip Circumference', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
29
|
+
{ key: 'chest', displayName: 'Chest Circumference', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
30
|
+
{ key: 'neck', displayName: 'Neck Circumference', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
31
|
+
{ key: 'left_bicep', displayName: 'Left Bicep', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
32
|
+
{ key: 'right_bicep', displayName: 'Right Bicep', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
33
|
+
{ key: 'left_forearm', displayName: 'Left Forearm', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
34
|
+
{ key: 'right_forearm', displayName: 'Right Forearm', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
35
|
+
{ key: 'left_thigh', displayName: 'Left Thigh', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
36
|
+
{ key: 'right_thigh', displayName: 'Right Thigh', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
37
|
+
{ key: 'left_calf', displayName: 'Left Calf', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
38
|
+
{ key: 'right_calf', displayName: 'Right Calf', category: 'body', unit: 'cm', aggregation: 'last', imperialUnit: 'in', imperialConversion: 0.393701 },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Activity Metrics - measurements related to daily activity and exercise
|
|
43
|
+
*/
|
|
44
|
+
export const ACTIVITY_METRICS: MetricDefinition[] = [
|
|
45
|
+
{ key: 'steps', displayName: 'Steps', category: 'activity', unit: 'steps', aggregation: 'sum' },
|
|
46
|
+
{ key: 'distance', displayName: 'Distance', category: 'activity', unit: 'km', aggregation: 'sum', imperialUnit: 'mi', imperialConversion: 0.621371 },
|
|
47
|
+
{ key: 'active_minutes', displayName: 'Active Minutes', category: 'activity', unit: 'min', aggregation: 'sum' },
|
|
48
|
+
{ key: 'exercise_minutes', displayName: 'Exercise Minutes', category: 'activity', unit: 'min', aggregation: 'sum' },
|
|
49
|
+
{ key: 'exercise_calories', displayName: 'Exercise Calories', category: 'activity', unit: 'kcal', aggregation: 'sum' },
|
|
50
|
+
{ key: 'floors_climbed', displayName: 'Floors Climbed', category: 'activity', unit: 'floors', aggregation: 'sum' },
|
|
51
|
+
{ key: 'standing_hours', displayName: 'Standing Hours', category: 'activity', unit: 'hours', aggregation: 'sum' },
|
|
52
|
+
{ key: 'vo2_max', displayName: 'VO2 Max', category: 'activity', unit: 'ml/kg/min', aggregation: 'last' },
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Sleep Metrics - measurements related to sleep quality and duration
|
|
57
|
+
*/
|
|
58
|
+
export const SLEEP_METRICS: MetricDefinition[] = [
|
|
59
|
+
{ key: 'sleep_duration', displayName: 'Sleep Duration', category: 'sleep', unit: 'hours', aggregation: 'last' },
|
|
60
|
+
{ key: 'deep_sleep', displayName: 'Deep Sleep', category: 'sleep', unit: 'hours', aggregation: 'last' },
|
|
61
|
+
{ key: 'rem_sleep', displayName: 'REM Sleep', category: 'sleep', unit: 'hours', aggregation: 'last' },
|
|
62
|
+
{ key: 'light_sleep', displayName: 'Light Sleep', category: 'sleep', unit: 'hours', aggregation: 'last' },
|
|
63
|
+
{ key: 'sleep_quality', displayName: 'Sleep Quality', category: 'sleep', unit: 'score', aggregation: 'avg' },
|
|
64
|
+
{ key: 'sleep_efficiency', displayName: 'Sleep Efficiency', category: 'sleep', unit: '%', aggregation: 'avg' },
|
|
65
|
+
{ key: 'time_to_fall_asleep', displayName: 'Time to Fall Asleep', category: 'sleep', unit: 'min', aggregation: 'avg' },
|
|
66
|
+
{ key: 'times_awakened', displayName: 'Times Awakened', category: 'sleep', unit: 'count', aggregation: 'sum' },
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Vital Metrics - measurements related to vital signs and health indicators
|
|
71
|
+
*/
|
|
72
|
+
export const VITAL_METRICS: MetricDefinition[] = [
|
|
73
|
+
{ key: 'heart_rate', displayName: 'Heart Rate', category: 'vital', unit: 'bpm', aggregation: 'avg' },
|
|
74
|
+
{ key: 'resting_heart_rate', displayName: 'Resting Heart Rate', category: 'vital', unit: 'bpm', aggregation: 'min' },
|
|
75
|
+
{ key: 'heart_rate_variability', displayName: 'Heart Rate Variability', category: 'vital', unit: 'ms', aggregation: 'avg' },
|
|
76
|
+
{ key: 'blood_pressure_systolic', displayName: 'Blood Pressure (Systolic)', category: 'vital', unit: 'mmHg', aggregation: 'last' },
|
|
77
|
+
{ key: 'blood_pressure_diastolic', displayName: 'Blood Pressure (Diastolic)', category: 'vital', unit: 'mmHg', aggregation: 'last' },
|
|
78
|
+
{ key: 'blood_glucose', displayName: 'Blood Glucose', category: 'vital', unit: 'mg/dL', aggregation: 'avg' },
|
|
79
|
+
{ key: 'blood_oxygen', displayName: 'Blood Oxygen', category: 'vital', unit: '%', aggregation: 'avg' },
|
|
80
|
+
{ key: 'respiratory_rate', displayName: 'Respiratory Rate', category: 'vital', unit: 'breaths/min', aggregation: 'avg' },
|
|
81
|
+
{ key: 'body_temperature', displayName: 'Body Temperature', category: 'vital', unit: '°C', aggregation: 'avg', imperialUnit: '°F', imperialConversion: 1.8 }, // Note: Fahrenheit conversion requires adding 32, handle separately
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Wellness Metrics - measurements related to mental health and well-being
|
|
86
|
+
*/
|
|
87
|
+
export const WELLNESS_METRICS: MetricDefinition[] = [
|
|
88
|
+
{ key: 'mood', displayName: 'Mood', category: 'wellness', unit: 'score', aggregation: 'avg' },
|
|
89
|
+
{ key: 'energy_level', displayName: 'Energy Level', category: 'wellness', unit: 'score', aggregation: 'avg' },
|
|
90
|
+
{ key: 'stress_level', displayName: 'Stress Level', category: 'wellness', unit: 'score', aggregation: 'avg' },
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* All available metrics
|
|
95
|
+
*/
|
|
96
|
+
export const ALL_METRICS: MetricDefinition[] = [
|
|
97
|
+
...BODY_METRICS,
|
|
98
|
+
...ACTIVITY_METRICS,
|
|
99
|
+
...SLEEP_METRICS,
|
|
100
|
+
...VITAL_METRICS,
|
|
101
|
+
...WELLNESS_METRICS,
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Helper function to get a metric definition by key
|
|
106
|
+
*/
|
|
107
|
+
export function getMetricDefinition(key: string): MetricDefinition | undefined {
|
|
108
|
+
return ALL_METRICS.find(m => m.key === key);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Helper function to get metrics by category
|
|
113
|
+
*/
|
|
114
|
+
export function getMetricsByCategory(category: MetricDefinition['category']): MetricDefinition[] {
|
|
115
|
+
return ALL_METRICS.filter(m => m.category === category);
|
|
116
|
+
}
|