@modelhealth/sdk 0.1.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.
@@ -0,0 +1,850 @@
1
+ /**
2
+ * Model Health SDK Client
3
+ *
4
+ * TypeScript/JavaScript client for the Model Health biomechanics SDK.
5
+ * Provides a clean, typed API over the WASM bindings.
6
+ *
7
+ * @packageDocumentation
8
+ *
9
+ * @example Basic usage
10
+ * ```typescript
11
+ * import { ModelHealthService } from '@modelhealth/sdk';
12
+ *
13
+ * // Create and initialize client with API key
14
+ * const client = new ModelHealthService({ apiKey: "your-api-key-here" });
15
+ * await client.init();
16
+ *
17
+ * // Authenticate (optional - API key already provides authentication)
18
+ * const result = await client.login("user@example.com", "password");
19
+ * if (result === "verification_required") {
20
+ * await client.verify("123456", true);
21
+ * }
22
+ *
23
+ * // Get sessions
24
+ * const sessions = await client.sessionList();
25
+ * ```
26
+ */
27
+ import type { LoginResult, RegistrationParameters, CheckerboardDetails, Session, Subject, SubjectParameters, Activity, ActivitySort, ActivityTag, VideoVersion, ResultDataType, ResultData, AnalysisType, AnalysisTask, AnalysisTaskStatus, ActivityProcessingStatus, TokenStorage, CalibrationStatus, AnalysisResult } from "./types.js";
28
+ import { MemoryTokenStorage, LocalStorageTokenStorage } from "./types.js";
29
+ /**
30
+ * Configuration options for the Model Health client.
31
+ */
32
+ export interface ModelHealthConfig {
33
+ /**
34
+ * Your ModelHealth API key for authentication.
35
+ *
36
+ * This is required to use the SDK. Get your API key from the
37
+ * ModelHealth dashboard.
38
+ *
39
+ * @required
40
+ */
41
+ apiKey: string;
42
+ /**
43
+ * Token storage implementation for persisting authentication.
44
+ *
45
+ * Provide a custom implementation for secure storage.
46
+ *
47
+ * @default MemoryTokenStorage (not secure - for development only)
48
+ */
49
+ storage?: TokenStorage;
50
+ /**
51
+ * Automatically initialize WASM on construction.
52
+ *
53
+ * When false, you must manually call `init()` before using the client.
54
+ *
55
+ * @default true
56
+ */
57
+ autoInit?: boolean;
58
+ }
59
+ /**
60
+ * Model Health SDK Client for biomechanical analysis.
61
+ *
62
+ * Main entry point for interacting with the Model Health SDK.
63
+ * Provides authentication, session management, data download,
64
+ * and analysis capabilities.
65
+ *
66
+ * @example Create with API key
67
+ * ```typescript
68
+ * const client = new ModelHealthService({
69
+ * apiKey: "your-api-key-here"
70
+ * });
71
+ * await client.init();
72
+ *
73
+ * // SDK is ready to use
74
+ * const sessions = await client.sessionList();
75
+ * ```
76
+ *
77
+ * @example With custom configuration
78
+ * ```typescript
79
+ * const client = new ModelHealthService({
80
+ * apiKey: "your-api-key",
81
+ * storage: new LocalStorageTokenStorage()
82
+ * });
83
+ * await client.init();
84
+ * ```
85
+ */
86
+ export declare class ModelHealthService {
87
+ private wasmClient;
88
+ private storage;
89
+ private config;
90
+ private initialized;
91
+ /**
92
+ * Create a new Model Health client.
93
+ *
94
+ * @param config Configuration options including API key
95
+ * @throws If API key is not provided
96
+ *
97
+ * @example Default configuration
98
+ * ```typescript
99
+ * const client = new ModelHealthService({
100
+ * apiKey: "your-api-key-here"
101
+ * });
102
+ * ```
103
+ *
104
+ * @example Custom configuration
105
+ * ```typescript
106
+ * const client = new ModelHealthService({
107
+ * apiKey: "your-api-key",
108
+ * storage: new LocalStorageTokenStorage(),
109
+ * autoInit: false
110
+ * });
111
+ * ```
112
+ */
113
+ constructor(config: ModelHealthConfig);
114
+ /**
115
+ * Initialize the WASM module and client.
116
+ *
117
+ * Must be called before using any other methods if `autoInit: false`
118
+ * was specified in the configuration. Safe to call multiple times.
119
+ *
120
+ * @throws If WASM initialization fails
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const client = new ModelHealthService({
125
+ * apiKey: "your-key",
126
+ * autoInit: false
127
+ * });
128
+ * await client.init();
129
+ * ```
130
+ */
131
+ init(): Promise<void>;
132
+ /**
133
+ * Ensure the client is initialized.
134
+ *
135
+ * @private
136
+ * @throws If client is not initialized
137
+ */
138
+ private ensureInitialized;
139
+ /**
140
+ * Registers a new user account.
141
+ *
142
+ * Creates a new user account and automatically authenticates the user.
143
+ * After successful registration, the SDK is ready to use immediately
144
+ * without requiring a separate login call.
145
+ *
146
+ * @param parameters Registration details including credentials and user information
147
+ * @throws If registration fails (duplicate username/email, validation errors, etc.)
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * const params = {
152
+ * username: "user123",
153
+ * email: "user@example.com",
154
+ * password: "securePassword123456789",
155
+ * first_name: "John",
156
+ * last_name: "Doe",
157
+ * country: "United States",
158
+ * institution: "Example University",
159
+ * profession: "Researcher",
160
+ * reason: "Biomechanical research",
161
+ * language: "en",
162
+ * unit: "metric",
163
+ * newsletter: false
164
+ * };
165
+ *
166
+ * await client.register(params);
167
+ * // User is now authenticated and ready to use SDK
168
+ * ```
169
+ */
170
+ register(parameters: RegistrationParameters): Promise<void>;
171
+ /**
172
+ * Authenticates a user with username and password.
173
+ *
174
+ * This initiates the login process. Depending on the account's security settings
175
+ * and device trust status, either:
176
+ * - Returns `"ok"` if the device is trusted (previously verified with
177
+ * `rememberDevice: true` within the last 90 days)
178
+ * - Returns `"verification_required"` if email verification is needed
179
+ *
180
+ * When verification is required, a code is automatically sent to the user's
181
+ * registered email address. Complete authentication by calling `verify()`.
182
+ *
183
+ * @param username User's email address
184
+ * @param password User's password
185
+ * @returns A `LoginResult` indicating whether verification is required
186
+ * @throws If authentication fails (invalid credentials, network issues, etc.)
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * const result = await client.login("user@example.com", "secure_pass");
191
+ *
192
+ * switch (result) {
193
+ * case "ok":
194
+ * // Authentication complete, proceed with SDK usage
195
+ * console.log("Login successful");
196
+ * break;
197
+ *
198
+ * case "verification_required":
199
+ * // Prompt user for email verification code and
200
+ * // trust this device for 90 days
201
+ * const code = await promptUserForCode();
202
+ * await client.verify(code, true);
203
+ * break;
204
+ * }
205
+ * ```
206
+ */
207
+ login(username: string, password: string): Promise<LoginResult>;
208
+ /**
209
+ * Completes authentication by verifying an email code.
210
+ *
211
+ * After `login()` returns `"verification_required"`, call this method with
212
+ * the verification code sent to the user's email.
213
+ *
214
+ * Set `rememberDevice: true` to skip email verification on this device for 90 days.
215
+ * Future login attempts from this device will return `"ok"` directly.
216
+ *
217
+ * @param code 6-digit verification code from email
218
+ * @param rememberDevice If `true`, trust this device for 90 days (default: `false`)
219
+ * @throws If the code is invalid or expired
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * // After receiving "verification_required" from login
224
+ * await client.verify("123456", true);
225
+ * // Authentication now complete, SDK ready for use
226
+ * ```
227
+ */
228
+ verify(code: string, rememberDevice: boolean): Promise<void>;
229
+ /**
230
+ * Logs out the current user.
231
+ *
232
+ * After logout, the user must call `login()` or `register()` to use the SDK again.
233
+ *
234
+ * @throws If the logout request fails
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * await client.logout();
239
+ * // User is now logged out
240
+ * ```
241
+ */
242
+ logout(): Promise<void>;
243
+ /**
244
+ * Checks if a user is currently authenticated.
245
+ *
246
+ * @returns `true` if authenticated, `false` otherwise
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * if (await client.isAuthenticated()) {
251
+ * // Proceed with authenticated operations
252
+ * const sessions = await client.sessionList();
253
+ * } else {
254
+ * // Show login screen
255
+ * }
256
+ * ```
257
+ */
258
+ isAuthenticated(): Promise<boolean>;
259
+ /**
260
+ * Get the current authentication token.
261
+ *
262
+ * @returns The authentication token string, or null if not authenticated
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * const token = client.getToken();
267
+ * if (token) {
268
+ * // Store for later use
269
+ * localStorage.setItem('backup_token', token);
270
+ * }
271
+ * ```
272
+ */
273
+ getToken(): string | null;
274
+ /**
275
+ * Set authentication token directly.
276
+ *
277
+ * Use this to restore a previously saved session without logging in again.
278
+ *
279
+ * @param token The authentication token to restore
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const savedToken = localStorage.getItem('backup_token');
284
+ * if (savedToken) {
285
+ * client.setToken(savedToken);
286
+ * }
287
+ * ```
288
+ */
289
+ setToken(token: string): void;
290
+ /**
291
+ * Retrieves all sessions for the authenticated user.
292
+ *
293
+ * @returns An array of `Session` objects. Returns an empty array if no sessions exist.
294
+ * @throws If the request fails due to network issues, authentication problems,
295
+ * or server errors.
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * try {
300
+ * const sessions = await client.sessionList();
301
+ * console.log(`Found ${sessions.length} sessions`);
302
+ * for (const session of sessions) {
303
+ * console.log(`Session: ${session.id}`);
304
+ * }
305
+ * } catch (error) {
306
+ * console.log(`Failed to fetch sessions: ${error}`);
307
+ * }
308
+ * ```
309
+ */
310
+ sessionList(): Promise<Session[]>;
311
+ /**
312
+ * Retrieve a specific session by ID with all activities populated.
313
+ *
314
+ * @param sessionId Unique session identifier
315
+ * @returns The requested session with complete activity data
316
+ * @throws If the session doesn't exist, user lacks access, or request fails
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * const session = await client.getSession("session-abc123");
321
+ * console.log(`Session has ${session.activities.length} activities`);
322
+ * ```
323
+ */
324
+ getSession(sessionId: string): Promise<Session>;
325
+ /**
326
+ * Creates a new session.
327
+ *
328
+ * A session is required before performing camera calibration. It represents
329
+ * a single calibration workflow and groups multiple cameras together.
330
+ *
331
+ * After creating a session, use camera calibration methods to calibrate your cameras.
332
+ *
333
+ * @returns A `Session` object with a unique identifier
334
+ * @throws If session creation fails
335
+ *
336
+ * @example
337
+ * ```typescript
338
+ * // Create session
339
+ * const session = await client.createSession();
340
+ *
341
+ * // Proceed with calibration
342
+ * const details = {
343
+ * rows: 4,
344
+ * columns: 5,
345
+ * square_size: 35,
346
+ * placement: "perpendicular"
347
+ * };
348
+ * // await client.calibrateCamera(session, details, (status) => { ... });
349
+ * ```
350
+ */
351
+ createSession(): Promise<Session>;
352
+ /**
353
+ * Calibrates a camera using a checkerboard pattern.
354
+ *
355
+ * **Requirements:**
356
+ * - A printed checkerboard pattern
357
+ * - Accurate measurement of square size in millimeters
358
+ * - Multiple views of the checkerboard from different angles
359
+ *
360
+ * The calibration is automated and typically completes in a few seconds
361
+ *
362
+ * @param session The session created with `createSession()`
363
+ * @param checkerboardDetails Configuration of the calibration checkerboard
364
+ * @param statusCallback Callback function called with calibration progress updates
365
+ * @throws If calibration fails (insufficient views, pattern not detected, etc.)
366
+ *
367
+ * @example
368
+ * ```typescript
369
+ * const session = await client.createSession();
370
+ *
371
+ * const details = {
372
+ * rows: 4, // Internal corners, not squares (for 5×6 board)
373
+ * columns: 5, // Internal corners, not squares (for 5×6 board)
374
+ * square_size: 35, // Measured in millimeters
375
+ * placement: "perpendicular"
376
+ * };
377
+ *
378
+ * await client.calibrateCamera(session, details, (status) => {
379
+ * console.log("Calibration status:", status);
380
+ * });
381
+ * // Calibration complete, proceed to neutral pose
382
+ * ```
383
+ */
384
+ calibrateCamera(session: Session, checkerboardDetails: CheckerboardDetails, statusCallback: (status: CalibrationStatus) => void): Promise<void>;
385
+ /**
386
+ * Captures the subject's neutral standing pose for model scaling.
387
+ *
388
+ * This step is required after camera calibration and before recording movement activities.
389
+ * It takes a quick video of the subject standing in a neutral position, which is
390
+ * used to scale the biomechanical model to match the subject's dimensions.
391
+ *
392
+ * **Instructions for subject:**
393
+ * - Stand upright in a relaxed, natural position
394
+ * - Face forward with arms spread slightly at sides
395
+ * - Remain still for a few seconds
396
+ *
397
+ * @param subject The subject to calibrate the neutral pose for
398
+ * @param session The session to perform calibration in
399
+ * @param statusCallback Callback function called with calibration progress updates
400
+ * @throws If pose capture fails (subject not detected, poor lighting, etc.)
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // After successful camera calibration
405
+ * await client.calibrateNeutralPose(subject, session, (status) => {
406
+ * console.log("Neutral pose status:", status);
407
+ * });
408
+ * // Model now scaled, ready to record movement activities
409
+ * ```
410
+ */
411
+ calibrateNeutralPose(subject: Subject, session: Session, statusCallback: (status: CalibrationStatus) => void): Promise<void>;
412
+ /**
413
+ * Retrieves all subjects associated with the authenticated account.
414
+ *
415
+ * Subjects represent individuals being monitored or assessed. Each subject
416
+ * contains demographic information, physical measurements, and categorization tags.
417
+ *
418
+ * @returns An array of `Subject` objects
419
+ * @throws If the request fails or authentication has expired
420
+ *
421
+ * @example
422
+ * ```typescript
423
+ * const subjects = await client.subjectList();
424
+ * for (const subject of subjects) {
425
+ * console.log(`${subject.name}: ${subject.height ?? 0}cm, ${subject.weight ?? 0}kg`);
426
+ * }
427
+ *
428
+ * // Filter by tags
429
+ * const athletes = subjects.filter(s => s.subject_tags.includes("athlete"));
430
+ * ```
431
+ */
432
+ subjectList(): Promise<Subject[]>;
433
+ /**
434
+ * Creates a new subject in the system.
435
+ *
436
+ * Subjects represent individuals being monitored or assessed. After creating
437
+ * a subject, they can be associated with sessions for neutral pose calibration
438
+ * and movement activities.
439
+ *
440
+ * @param parameters Subject details including name, measurements, and tags
441
+ * @returns The newly created `Subject` with its assigned ID
442
+ * @throws If creation fails (validation errors, duplicate name, etc.)
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * const params = {
447
+ * name: "John Doe",
448
+ * weight: 75.0, // kilograms
449
+ * height: 180.0, // centimeters
450
+ * birth_year: 1990,
451
+ * gender: "man",
452
+ * sex_at_birth: "man",
453
+ * characteristics: "Regular training schedule",
454
+ * subject_tags: ["athlete"],
455
+ * terms: true
456
+ * };
457
+ *
458
+ * const subject = await client.createSubject(params);
459
+ * console.log(`Created subject with ID: ${subject.id}`);
460
+ *
461
+ * // Use the subject for calibration
462
+ * // await client.calibrateNeutralPose(subject, session, (status) => { ... });
463
+ * ```
464
+ */
465
+ createSubject(parameters: SubjectParameters): Promise<Subject>;
466
+ /**
467
+ * Retrieves activities for a specific subject with pagination and sorting.
468
+ *
469
+ * This method allows you to fetch activities associated with a particular subject,
470
+ * with control over pagination and sort order. This is useful for displaying
471
+ * activity history or implementing infinite scroll interfaces.
472
+ *
473
+ * @param subjectId The ID of the subject whose activities to retrieve
474
+ * @param startIndex Zero-based index to start from (for pagination). Use 0 for first page.
475
+ * @param count Number of activities to retrieve per request
476
+ * @param sort Sort order for the results (e.g., "updated_at" for most recent first)
477
+ * @returns An array of activities for the specified subject
478
+ * @throws If the request fails or authentication has expired
479
+ *
480
+ * @example
481
+ * ```typescript
482
+ * // Get the 20 most recent activities for a subject
483
+ * const recentActivities = await client.getActivitiesForSubject(
484
+ * "subject-123",
485
+ * 0,
486
+ * 20,
487
+ * "updated_at"
488
+ * );
489
+ *
490
+ * // Pagination - get the next 20 activities
491
+ * const nextPage = await client.getActivitiesForSubject(
492
+ * "subject-123",
493
+ * 20,
494
+ * 20,
495
+ * "updated_at"
496
+ * );
497
+ * ```
498
+ */
499
+ getActivitiesForSubject(subjectId: string, startIndex: number, count: number, sort: ActivitySort): Promise<Activity[]>;
500
+ /**
501
+ * Retrieves a specific activity by its ID.
502
+ *
503
+ * Use this method to fetch the complete details of an activity, including
504
+ * its videos, results, and current processing status.
505
+ *
506
+ * @param activityId The unique identifier of the activity
507
+ * @returns The requested activity with all its details
508
+ * @throws If the activity doesn't exist, or if authentication has expired
509
+ *
510
+ * @example
511
+ * ```typescript
512
+ * const activity = await client.getActivity("abc123");
513
+ * console.log(`Activity: ${activity.name ?? "Unnamed"}`);
514
+ * console.log(`Status: ${activity.status}`);
515
+ * console.log(`Videos: ${activity.videos.length}`);
516
+ * ```
517
+ */
518
+ getActivity(activityId: string): Promise<Activity>;
519
+ /**
520
+ * Updates an existing activity.
521
+ *
522
+ * Use this method to modify activity properties such as the name.
523
+ * The activity is updated on the server and the updated version is returned.
524
+ *
525
+ * @param activity The activity to update (with modified properties)
526
+ * @returns The updated activity as stored on the server
527
+ * @throws If the update fails or authentication has expired
528
+ *
529
+ * @example
530
+ * ```typescript
531
+ * let activity = await client.getActivity("abc123");
532
+ * // Modify the activity name
533
+ * activity.name = "CMJ Baseline Test";
534
+ * const updated = await client.updateActivity(activity);
535
+ * console.log(`Updated: ${updated.name ?? ""}`);
536
+ * ```
537
+ *
538
+ * @note Not all activity properties can be modified. Only mutable fields
539
+ * (such as `name`) will be updated on the server.
540
+ */
541
+ updateActivity(activity: Activity): Promise<Activity>;
542
+ /**
543
+ * Deletes an activity from the system.
544
+ *
545
+ * This permanently removes the activity and all its associated data,
546
+ * including videos and analysis results. This action cannot be undone.
547
+ *
548
+ * @param activity The activity to delete
549
+ * @throws If the deletion fails or authentication has expired
550
+ *
551
+ * @example
552
+ * ```typescript
553
+ * const activity = await client.getActivity("abc123");
554
+ * await client.deleteActivity(activity);
555
+ * // Activity and all associated data are now permanently deleted
556
+ * ```
557
+ *
558
+ * @warning This operation is irreversible. All videos, analysis results,
559
+ * and metadata associated with this activity will be permanently lost.
560
+ */
561
+ deleteActivity(activity: Activity): Promise<void>;
562
+ /**
563
+ * Retrieves all available activity tags.
564
+ *
565
+ * Activity tags provide a way to categorize and filter activities.
566
+ * This method returns all tags configured in the system, which can be
567
+ * used for filtering or organizing activities in your application.
568
+ *
569
+ * @returns An array of available activity tags
570
+ * @throws If the request fails or authentication has expired
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * const tags = await client.getActivityTags();
575
+ * for (const tag of tags) {
576
+ * console.log(`${tag.label}: ${tag.value}`);
577
+ * }
578
+ *
579
+ * // Use tags for filtering or categorization
580
+ * const cmjTag = tags.find(t => t.value === "cmj");
581
+ * ```
582
+ */
583
+ getActivityTags(): Promise<ActivityTag[]>;
584
+ /**
585
+ * Retrieves all movement activities associated with the authenticated account.
586
+ *
587
+ * Activities represent individual recording sessions and contain references to
588
+ * captured videos and analysis results. Use this to review past data or
589
+ * fetch analysis for completed activities.
590
+ *
591
+ * @param sessionId Session identifier
592
+ * @returns An array of `Activity` objects
593
+ * @throws If the request fails or authentication has expired
594
+ *
595
+ * @example
596
+ * ```typescript
597
+ * const activities = await client.activityList(session.id);
598
+ *
599
+ * // Find completed activities ready for analysis
600
+ * const completed = activities.filter(t => t.status === "completed");
601
+ *
602
+ * // Access videos and results
603
+ * for (const activity of completed) {
604
+ * console.log(`Activity: ${activity.name ?? activity.id}`);
605
+ * console.log(`Videos: ${activity.videos.length}`);
606
+ * console.log(`Results: ${activity.results.length}`);
607
+ * }
608
+ * ```
609
+ */
610
+ activityList(sessionId: string): Promise<Activity[]>;
611
+ /**
612
+ * Download video data for a specific activity.
613
+ *
614
+ * Asynchronously fetches all videos associated with a given activity that match the specified type.
615
+ * Videos with invalid URLs or failed downloads are silently excluded from the result.
616
+ *
617
+ * @param activity The activity whose videos should be downloaded
618
+ * @param version The version type of videos to download (default: "synced")
619
+ * @returns An array of video data as Uint8Array. The array may be empty if no valid
620
+ * videos are available or all downloads fail.
621
+ *
622
+ * @example
623
+ * ```typescript
624
+ * const activity = // ... obtained activity
625
+ * const videoData = await client.downloadActivityVideos(activity, "raw");
626
+ *
627
+ * for (const data of videoData) {
628
+ * // Process video data
629
+ * }
630
+ * ```
631
+ *
632
+ * @note This method performs concurrent downloads for optimal performance. Individual download
633
+ * failures do not affect other requests.
634
+ */
635
+ downloadActivityVideos(activity: Activity, version?: VideoVersion): Promise<Uint8Array[]>;
636
+ /**
637
+ * Downloads result data files from a processed activity.
638
+ *
639
+ * After an activity completes processing, various result files become available for download.
640
+ * Use this method to retrieve specific types of data (kinematic measurements, visualizations)
641
+ * in their native file formats (JSON, CSV).
642
+ *
643
+ * This method is useful when you need access to raw analysis data rather than the
644
+ * structured metrics provided by analysis result methods.
645
+ *
646
+ * @param activity The completed activity to download data from
647
+ * @param dataTypes The types of result data to download (kinematic, visualization, or both)
648
+ * @returns An array of result files with their formats. Returns an empty array if no
649
+ * results are available or all downloads fail.
650
+ *
651
+ * @example
652
+ * ```typescript
653
+ * // Download kinematic data only
654
+ * const kinematicData = await client.downloadActivityResultData(activity, ["kinematic"]);
655
+ *
656
+ * for (const result of kinematicData) {
657
+ * switch (result.file_type) {
658
+ * case "json":
659
+ * const json = JSON.parse(new TextDecoder().decode(result.data));
660
+ * console.log("Parsed kinematic JSON");
661
+ * break;
662
+ *
663
+ * case "csv":
664
+ * const csvString = new TextDecoder().decode(result.data);
665
+ * console.log(`CSV data:\n${csvString}`);
666
+ * break;
667
+ * }
668
+ * }
669
+ *
670
+ * // Download all available data types
671
+ * const allData = await client.downloadActivityResultData(
672
+ * activity,
673
+ * ["kinematic", "visualization"]
674
+ * );
675
+ * console.log(`Downloaded ${allData.length} result files`);
676
+ * ```
677
+ *
678
+ * @note This method performs concurrent downloads for optimal performance.
679
+ * Individual download failures do not affect other requests and failed downloads
680
+ * are silently excluded from results.
681
+ */
682
+ downloadActivityResultData(activity: Activity, dataTypes: ResultDataType[]): Promise<ResultData[]>;
683
+ /**
684
+ * Starts recording a dynamic movement activity.
685
+ *
686
+ * After completing calibration steps (camera calibration and neutral pose),
687
+ * use this method to begin recording an activity.
688
+ *
689
+ * @param activityName A descriptive name for this activity (e.g., "cmj-test")
690
+ * @param session The session this activity is associated with
691
+ * @returns The newly created activity
692
+ * @throws If recording cannot start (session not calibrated, camera issues, etc.)
693
+ *
694
+ * @example
695
+ * ```typescript
696
+ * // Record a CMJ session
697
+ * const activity = await client.record("cmj-2024", session);
698
+ * // Subject performs CMJ while cameras record
699
+ *
700
+ * // When complete, stop recording
701
+ * await client.stopRecording(session);
702
+ * ```
703
+ */
704
+ record(activityName: string, session: Session): Promise<Activity>;
705
+ /**
706
+ * Stops recording of a dynamic movement activity in a session.
707
+ *
708
+ * Call this method when the subject has completed the movement activity.
709
+ *
710
+ * @param session The session to stop recording in
711
+ * @throws If the activity cannot be stopped (invalid session ID, already stopped, etc.)
712
+ *
713
+ * @example
714
+ * ```typescript
715
+ * // After recording is complete
716
+ * await client.stopRecording(session);
717
+ * ```
718
+ */
719
+ stopRecording(session: Session): Promise<void>;
720
+ /**
721
+ * Retrieves the current processing status of an activity.
722
+ *
723
+ * Poll this method to determine when an activity is ready for analysis.
724
+ * Activities must complete video upload and processing before analysis can begin.
725
+ *
726
+ * @param activity A completed activity
727
+ * @returns The current processing status
728
+ * @throws Network or authentication errors
729
+ *
730
+ * @example
731
+ * ```typescript
732
+ * const status = await client.getStatus(activity);
733
+ *
734
+ * switch (status.type) {
735
+ * case "ready":
736
+ * console.log("Activity ready for analysis");
737
+ * break;
738
+ * case "processing":
739
+ * console.log("Still processing...");
740
+ * break;
741
+ * case "uploading":
742
+ * console.log(`Uploaded ${status.uploaded}/${status.total} videos`);
743
+ * break;
744
+ * case "failed":
745
+ * console.log("Processing failed");
746
+ * break;
747
+ * }
748
+ * ```
749
+ */
750
+ getStatus(activity: Activity): Promise<ActivityProcessingStatus>;
751
+ /**
752
+ * Starts an analysis task for a completed activity.
753
+ *
754
+ * The activity must have completed processing (status `.ready`) before analysis can begin.
755
+ * Use the returned `AnalysisTask` to poll for completion.
756
+ *
757
+ * @param analysisType The type of analysis to perform
758
+ * @param activity The activity to analyze
759
+ * @param session The session containing the activity
760
+ * @returns An analysis task for tracking completion
761
+ * @throws Network or authentication errors
762
+ *
763
+ * @example
764
+ * ```typescript
765
+ * const task = await client.startAnalysis(
766
+ * "counter_movement_jump",
767
+ * activity,
768
+ * session
769
+ * );
770
+ *
771
+ * // Poll for completion
772
+ * const status = await client.getAnalysisStatus(task);
773
+ * ```
774
+ */
775
+ startAnalysis(analysisType: AnalysisType, activity: Activity, session: Session): Promise<AnalysisTask>;
776
+ /**
777
+ * Retrieves the current status of an analysis task.
778
+ *
779
+ * Poll this method to monitor analysis progress. When status is `.completed`,
780
+ * use the returned result tags to download analysis files.
781
+ *
782
+ * @param task The task returned from `startAnalysis`
783
+ * @returns The current analysis status
784
+ * @throws Network or authentication errors
785
+ *
786
+ * @example
787
+ * ```typescript
788
+ * const status = await client.getAnalysisStatus(task);
789
+ *
790
+ * switch (status.type) {
791
+ * case "processing":
792
+ * console.log("Analysis running...");
793
+ * break;
794
+ * case "completed":
795
+ * for (const tag of status.result_tags) {
796
+ * const data = await client.downloadAnalysisResult(activity, tag);
797
+ * }
798
+ * break;
799
+ * case "failed":
800
+ * console.log("Analysis failed");
801
+ * break;
802
+ * }
803
+ * ```
804
+ */
805
+ getAnalysisStatus(task: AnalysisTask): Promise<AnalysisTaskStatus>;
806
+ /**
807
+ * Downloads an analysis result.
808
+ *
809
+ * Result tags are provided in the `.completed` status from `getAnalysisStatus`.
810
+ * Each tag represents a specific analysis output with structured biomechanical metrics.
811
+ *
812
+ * @param activity The completed and analyzed activity
813
+ * @param resultTag The specific result identifier
814
+ * @returns An `AnalysisResult` containing structured metrics
815
+ * @throws Network or authentication errors
816
+ *
817
+ * @example
818
+ * ```typescript
819
+ * const result = await client.downloadAnalysisResult(
820
+ * activity,
821
+ * "countermovement_jump"
822
+ * );
823
+ *
824
+ * console.log(`Analysis: ${result.analysis_title}`);
825
+ * console.log(`Description: ${result.analysis_description}`);
826
+ *
827
+ * // Access specific metrics
828
+ * if (result.jump_height) {
829
+ * console.log(`Jump Height: ${result.jump_height} cm`);
830
+ * }
831
+ *
832
+ * // Iterate all metrics
833
+ * for (const [key, metric] of Object.entries(result.metrics)) {
834
+ * console.log(`${metric.label}:`, metric.value);
835
+ * }
836
+ * ```
837
+ */
838
+ downloadAnalysisResult(activity: Activity, resultTag: string): Promise<AnalysisResult>;
839
+ /**
840
+ * Parse JSON response from WASM.
841
+ *
842
+ * @private
843
+ * @param value Value from WASM (may be string or object)
844
+ * @returns Parsed TypeScript object
845
+ */
846
+ private parseResponse;
847
+ }
848
+ export * from "./types.js";
849
+ export { MemoryTokenStorage, LocalStorageTokenStorage };
850
+ //# sourceMappingURL=index.d.ts.map