fit-file-parser 3.0.1 → 3.0.2

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/dist/cjs/fit.js CHANGED
@@ -6149,6 +6149,33 @@ exports.FIT = {
6149
6149
  23: 'u_turn',
6150
6150
  24: 'segment_start',
6151
6151
  25: 'segment_end',
6152
+ 27: 'campsite',
6153
+ 28: 'aid_station',
6154
+ 29: 'rest_area',
6155
+ 30: 'general_distance',
6156
+ 31: 'service',
6157
+ 32: 'energy_gel',
6158
+ 33: 'sports_drink',
6159
+ 34: 'mile_marker',
6160
+ 35: 'checkpoint',
6161
+ 36: 'shelter',
6162
+ 37: 'meeting_spot',
6163
+ 38: 'overlook',
6164
+ 39: 'toilet',
6165
+ 40: 'shower',
6166
+ 41: 'gear',
6167
+ 42: 'sharp_curve',
6168
+ 43: 'steep_incline',
6169
+ 44: 'tunnel',
6170
+ 45: 'bridge',
6171
+ 46: 'obstacle',
6172
+ 47: 'crossing',
6173
+ 48: 'store',
6174
+ 49: 'transition',
6175
+ 50: 'navaid',
6176
+ 51: 'transport',
6177
+ 52: 'alert',
6178
+ 53: 'info',
6152
6179
  },
6153
6180
  manufacturer: {
6154
6181
  0: 0,
@@ -69,7 +69,7 @@ export type Goal = 'time' | 'distance' | 'calories' | 'frequency' | 'steps' | 'a
69
69
  export type GoalRecurrence = 'off' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'custom';
70
70
  export type GoalSource = 'auto' | 'community' | 'user';
71
71
  export type Schedule = 'workout' | 'course';
72
- export type CoursePoint = 'generic' | 'summit' | 'valley' | 'water' | 'food' | 'danger' | 'left' | 'right' | 'straight' | 'first_aid' | 'fourth_category' | 'third_category' | 'second_category' | 'first_category' | 'hors_category' | 'sprint' | 'left_fork' | 'right_fork' | 'middle_fork' | 'slight_left' | 'sharp_left' | 'slight_right' | 'sharp_right' | 'u_turn' | 'segment_start' | 'segment_end';
72
+ export type CoursePoint = 'generic' | 'summit' | 'valley' | 'water' | 'food' | 'danger' | 'left' | 'right' | 'straight' | 'first_aid' | 'fourth_category' | 'third_category' | 'second_category' | 'first_category' | 'hors_category' | 'sprint' | 'left_fork' | 'right_fork' | 'middle_fork' | 'slight_left' | 'sharp_left' | 'slight_right' | 'sharp_right' | 'u_turn' | 'segment_start' | 'segment_end' | 'campsite' | 'aid_station' | 'rest_area' | 'general_distance' | 'service' | 'energy_gel' | 'sports_drink' | 'mile_marker' | 'checkpoint' | 'shelter' | 'meeting_spot' | 'overlook' | 'toilet' | 'shower' | 'gear' | 'sharp_curve' | 'steep_incline' | 'tunnel' | 'bridge' | 'obstacle' | 'crossing' | 'store' | 'transition' | 'navaid' | 'transport' | 'alert' | 'info';
73
73
  export type Manufacturer = '0' | 'garmin' | 'garmin_fr405_antfs' | 'zephyr' | 'dayton' | 'idt' | 'srm' | 'quarq' | 'ibike' | 'saris' | 'spark_hk' | 'tanita' | 'echowell' | 'dynastream_oem' | 'nautilus' | 'dynastream' | 'timex' | 'metrigear' | 'xelic' | 'beurer' | 'cardiosport' | 'a_and_d' | 'hmm' | 'suunto' | 'thita_elektronik' | 'gpulse' | 'clean_mobile' | 'pedal_brain' | 'peaksware' | 'saxonar' | 'lemond_fitness' | 'dexcom' | 'wahoo_fitness' | 'octane_fitness' | 'archinoetics' | 'the_hurt_box' | 'citizen_systems' | 'magellan' | 'osynce' | 'holux' | 'concept2' | 'one_giant_leap' | 'ace_sensor' | 'brim_brothers' | 'xplova' | 'perception_digital' | 'bf1systems' | 'pioneer' | 'spantec' | 'metalogics' | '4iiiis' | 'seiko_epson' | 'seiko_epson_oem' | 'ifor_powell' | 'maxwell_guider' | 'star_trac' | 'breakaway' | 'alatech_technology_ltd' | 'mio_technology_europe' | 'rotor' | 'geonaute' | 'id_bike' | 'specialized' | 'wtek' | 'physical_enterprises' | 'north_pole_engineering' | 'bkool' | 'cateye' | 'stages_cycling' | 'sigmasport' | 'tomtom' | 'peripedal' | 'wattbike' | 'moxy' | 'ciclosport' | 'powerbahn' | 'acorn_projects_aps' | 'lifebeam' | 'bontrager' | 'wellgo' | 'scosche' | 'magura' | 'woodway' | 'elite' | 'nielsen_kellerman' | 'dk_city' | 'tacx' | 'direction_technology' | 'magtonic' | '1partcarbon' | 'inside_ride_technologies' | 'sound_of_motion' | 'stryd' | 'icg' | 'mipulse' | 'bsx_athletics' | 'look' | 'campagnolo_srl' | 'body_bike_smart' | 'praxisworks' | 'limits_technology' | 'topaction_technology' | 'cosinuss' | 'fitcare' | 'magene' | 'giant_manufacturing_co' | 'tigrasport' | 'salutron' | 'technogym' | 'bryton_sensors' | 'latitude_limited' | 'soaring_technology' | 'igpsport' | 'thinkrider' | 'gopher_sport' | 'waterrower' | 'orangetheory' | 'inpeak' | 'kinetic' | 'johnson_health_tech' | 'polar_electro' | 'seesense' | 'nci_technology' | 'development' | 'healthandlife' | 'lezyne' | 'scribe_labs' | 'zwift' | 'watteam' | 'recon' | 'favero_electronics' | 'dynovelo' | 'strava' | 'precor' | 'bryton' | 'sram' | 'navman' | 'cobi' | 'spivi' | 'mio_magellan' | 'evesports' | 'sensitivus_gauge' | 'podoon' | 'life_time_fitness' | 'falco_e_motors' | 'minoura' | 'cycliq' | 'luxottica' | 'trainer_road' | 'the_sufferfest' | 'fullspeedahead' | 'virtualtraining' | 'feedbacksports' | 'omata' | 'vdo' | 'magneticdays' | 'hammerhead' | 'kinetic_by_kurt' | 'shapelog' | 'dabuziduo' | 'jetblack' | 'coros' | 'virtugo' | 'velosense' | 'actigraphcorp';
74
74
  export type GarminProduct = 'hrm_bike' | 'hrm1' | 'axh01' | 'axb01' | 'axb02' | 'hrm2ss' | 'dsi_alf02' | 'hrm3ss' | 'hrm_run_single_byte_product_id' | 'bsm' | 'bcm' | 'axs01' | 'hrm_tri_single_byte_product_id' | 'fr225_single_byte_product_id' | 'fr301_china' | 'fr301_japan' | 'fr301_korea' | 'fr301_taiwan' | 'fr405' | 'fr50' | 'fr405_japan' | 'fr60' | 'dsi_alf01' | 'fr310xt' | 'edge500' | 'fr110' | 'edge800' | 'edge500_taiwan' | 'edge500_japan' | 'chirp' | 'fr110_japan' | 'edge200' | 'fr910xt' | 'edge800_taiwan' | 'edge800_japan' | 'alf04' | 'fr610' | 'fr210_japan' | 'vector_ss' | 'vector_cp' | 'edge800_china' | 'edge500_china' | 'fr610_japan' | 'edge500_korea' | 'fr70' | 'fr310xt_4t' | 'amx' | 'fr10' | 'edge800_korea' | 'swim' | 'fr910xt_china' | 'fenix' | 'edge200_taiwan' | 'edge510' | 'edge810' | 'tempe' | 'fr910xt_japan' | 'fr620' | 'fr220' | 'fr910xt_korea' | 'fr10_japan' | 'edge810_japan' | 'virb_elite' | 'edge_touring' | 'edge510_japan' | 'hrm_tri' | 'hrm_run' | 'fr920xt' | 'edge510_asia' | 'edge810_china' | 'edge810_taiwan' | 'edge1000' | 'vivo_fit' | 'virb_remote' | 'vivo_ki' | 'fr15' | 'vivo_active' | 'edge510_korea' | 'fr620_japan' | 'fr620_china' | 'fr220_japan' | 'fr220_china' | 'approach_s6' | 'vivo_smart' | 'fenix2' | 'epix' | 'fenix3' | 'edge1000_taiwan' | 'edge1000_japan' | 'fr15_japan' | 'edge520' | 'edge1000_china' | 'fr620_russia' | 'fr220_russia' | 'vector_s' | 'edge1000_korea' | 'fr920xt_taiwan' | 'fr920xt_china' | 'fr920xt_japan' | 'virbx' | 'vivo_smart_apac' | 'etrex_touch' | 'edge25' | 'fr25' | 'vivo_fit2' | 'fr225' | 'fr630' | 'fr230' | 'fr735xt' | 'vivo_active_apac' | 'vector_2' | 'vector_2s' | 'virbxe' | 'fr620_taiwan' | 'fr220_taiwan' | 'truswing' | 'fenix3_china' | 'fenix3_twn' | 'varia_headlight' | 'varia_taillight_old' | 'edge_explore_1000' | 'fr225_asia' | 'varia_radar_taillight' | 'varia_radar_display' | 'edge20' | 'd2_bravo' | 'approach_s20' | 'varia_remote' | 'hrm4_run' | 'vivo_active_hr' | 'vivo_smart_hr' | 'vivo_move' | 'varia_vision' | 'vivo_fit3' | 'fenix3_hr' | 'virb_ultra_30' | 'index_smart_scale' | 'fr235' | 'fenix3_chronos' | 'oregon7xx' | 'rino7xx' | 'nautix' | 'edge_820' | 'edge_explore_820' | 'fenix5s' | 'd2_bravo_titanium' | 'varia_ut800' | 'running_dynamics_pod' | 'fenix5x' | 'vivo_fit_jr' | 'fr935' | 'fenix5' | 'descent' | 'sdm4' | 'edge_remote' | 'training_center' | 'connectiq_simulator' | 'android_antplus_plugin' | 'connect';
75
75
  export type AntplusDeviceType = 'antfs' | 'bike_power' | 'environment_sensor_legacy' | 'multi_sport_speed_distance' | 'control' | 'fitness_equipment' | 'blood_pressure' | 'geocache_node' | 'light_electric_vehicle' | 'env_sensor' | 'racquet' | 'control_hub' | 'muscle_oxygen' | 'shifting' | 'bike_light_main' | 'bike_light_shared' | 'exd' | 'bike_radar' | 'bike_aero' | 'weight_scale' | 'heart_rate' | 'bike_speed_cadence' | 'bike_cadence' | 'bike_speed' | 'stride_speed_distance';
package/dist/fit.js CHANGED
@@ -6146,6 +6146,33 @@ export const FIT = {
6146
6146
  23: 'u_turn',
6147
6147
  24: 'segment_start',
6148
6148
  25: 'segment_end',
6149
+ 27: 'campsite',
6150
+ 28: 'aid_station',
6151
+ 29: 'rest_area',
6152
+ 30: 'general_distance',
6153
+ 31: 'service',
6154
+ 32: 'energy_gel',
6155
+ 33: 'sports_drink',
6156
+ 34: 'mile_marker',
6157
+ 35: 'checkpoint',
6158
+ 36: 'shelter',
6159
+ 37: 'meeting_spot',
6160
+ 38: 'overlook',
6161
+ 39: 'toilet',
6162
+ 40: 'shower',
6163
+ 41: 'gear',
6164
+ 42: 'sharp_curve',
6165
+ 43: 'steep_incline',
6166
+ 44: 'tunnel',
6167
+ 45: 'bridge',
6168
+ 46: 'obstacle',
6169
+ 47: 'crossing',
6170
+ 48: 'store',
6171
+ 49: 'transition',
6172
+ 50: 'navaid',
6173
+ 51: 'transport',
6174
+ 52: 'alert',
6175
+ 53: 'info',
6149
6176
  },
6150
6177
  manufacturer: {
6151
6178
  0: 0,
@@ -69,7 +69,7 @@ export type Goal = 'time' | 'distance' | 'calories' | 'frequency' | 'steps' | 'a
69
69
  export type GoalRecurrence = 'off' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'custom';
70
70
  export type GoalSource = 'auto' | 'community' | 'user';
71
71
  export type Schedule = 'workout' | 'course';
72
- export type CoursePoint = 'generic' | 'summit' | 'valley' | 'water' | 'food' | 'danger' | 'left' | 'right' | 'straight' | 'first_aid' | 'fourth_category' | 'third_category' | 'second_category' | 'first_category' | 'hors_category' | 'sprint' | 'left_fork' | 'right_fork' | 'middle_fork' | 'slight_left' | 'sharp_left' | 'slight_right' | 'sharp_right' | 'u_turn' | 'segment_start' | 'segment_end';
72
+ export type CoursePoint = 'generic' | 'summit' | 'valley' | 'water' | 'food' | 'danger' | 'left' | 'right' | 'straight' | 'first_aid' | 'fourth_category' | 'third_category' | 'second_category' | 'first_category' | 'hors_category' | 'sprint' | 'left_fork' | 'right_fork' | 'middle_fork' | 'slight_left' | 'sharp_left' | 'slight_right' | 'sharp_right' | 'u_turn' | 'segment_start' | 'segment_end' | 'campsite' | 'aid_station' | 'rest_area' | 'general_distance' | 'service' | 'energy_gel' | 'sports_drink' | 'mile_marker' | 'checkpoint' | 'shelter' | 'meeting_spot' | 'overlook' | 'toilet' | 'shower' | 'gear' | 'sharp_curve' | 'steep_incline' | 'tunnel' | 'bridge' | 'obstacle' | 'crossing' | 'store' | 'transition' | 'navaid' | 'transport' | 'alert' | 'info';
73
73
  export type Manufacturer = '0' | 'garmin' | 'garmin_fr405_antfs' | 'zephyr' | 'dayton' | 'idt' | 'srm' | 'quarq' | 'ibike' | 'saris' | 'spark_hk' | 'tanita' | 'echowell' | 'dynastream_oem' | 'nautilus' | 'dynastream' | 'timex' | 'metrigear' | 'xelic' | 'beurer' | 'cardiosport' | 'a_and_d' | 'hmm' | 'suunto' | 'thita_elektronik' | 'gpulse' | 'clean_mobile' | 'pedal_brain' | 'peaksware' | 'saxonar' | 'lemond_fitness' | 'dexcom' | 'wahoo_fitness' | 'octane_fitness' | 'archinoetics' | 'the_hurt_box' | 'citizen_systems' | 'magellan' | 'osynce' | 'holux' | 'concept2' | 'one_giant_leap' | 'ace_sensor' | 'brim_brothers' | 'xplova' | 'perception_digital' | 'bf1systems' | 'pioneer' | 'spantec' | 'metalogics' | '4iiiis' | 'seiko_epson' | 'seiko_epson_oem' | 'ifor_powell' | 'maxwell_guider' | 'star_trac' | 'breakaway' | 'alatech_technology_ltd' | 'mio_technology_europe' | 'rotor' | 'geonaute' | 'id_bike' | 'specialized' | 'wtek' | 'physical_enterprises' | 'north_pole_engineering' | 'bkool' | 'cateye' | 'stages_cycling' | 'sigmasport' | 'tomtom' | 'peripedal' | 'wattbike' | 'moxy' | 'ciclosport' | 'powerbahn' | 'acorn_projects_aps' | 'lifebeam' | 'bontrager' | 'wellgo' | 'scosche' | 'magura' | 'woodway' | 'elite' | 'nielsen_kellerman' | 'dk_city' | 'tacx' | 'direction_technology' | 'magtonic' | '1partcarbon' | 'inside_ride_technologies' | 'sound_of_motion' | 'stryd' | 'icg' | 'mipulse' | 'bsx_athletics' | 'look' | 'campagnolo_srl' | 'body_bike_smart' | 'praxisworks' | 'limits_technology' | 'topaction_technology' | 'cosinuss' | 'fitcare' | 'magene' | 'giant_manufacturing_co' | 'tigrasport' | 'salutron' | 'technogym' | 'bryton_sensors' | 'latitude_limited' | 'soaring_technology' | 'igpsport' | 'thinkrider' | 'gopher_sport' | 'waterrower' | 'orangetheory' | 'inpeak' | 'kinetic' | 'johnson_health_tech' | 'polar_electro' | 'seesense' | 'nci_technology' | 'development' | 'healthandlife' | 'lezyne' | 'scribe_labs' | 'zwift' | 'watteam' | 'recon' | 'favero_electronics' | 'dynovelo' | 'strava' | 'precor' | 'bryton' | 'sram' | 'navman' | 'cobi' | 'spivi' | 'mio_magellan' | 'evesports' | 'sensitivus_gauge' | 'podoon' | 'life_time_fitness' | 'falco_e_motors' | 'minoura' | 'cycliq' | 'luxottica' | 'trainer_road' | 'the_sufferfest' | 'fullspeedahead' | 'virtualtraining' | 'feedbacksports' | 'omata' | 'vdo' | 'magneticdays' | 'hammerhead' | 'kinetic_by_kurt' | 'shapelog' | 'dabuziduo' | 'jetblack' | 'coros' | 'virtugo' | 'velosense' | 'actigraphcorp';
74
74
  export type GarminProduct = 'hrm_bike' | 'hrm1' | 'axh01' | 'axb01' | 'axb02' | 'hrm2ss' | 'dsi_alf02' | 'hrm3ss' | 'hrm_run_single_byte_product_id' | 'bsm' | 'bcm' | 'axs01' | 'hrm_tri_single_byte_product_id' | 'fr225_single_byte_product_id' | 'fr301_china' | 'fr301_japan' | 'fr301_korea' | 'fr301_taiwan' | 'fr405' | 'fr50' | 'fr405_japan' | 'fr60' | 'dsi_alf01' | 'fr310xt' | 'edge500' | 'fr110' | 'edge800' | 'edge500_taiwan' | 'edge500_japan' | 'chirp' | 'fr110_japan' | 'edge200' | 'fr910xt' | 'edge800_taiwan' | 'edge800_japan' | 'alf04' | 'fr610' | 'fr210_japan' | 'vector_ss' | 'vector_cp' | 'edge800_china' | 'edge500_china' | 'fr610_japan' | 'edge500_korea' | 'fr70' | 'fr310xt_4t' | 'amx' | 'fr10' | 'edge800_korea' | 'swim' | 'fr910xt_china' | 'fenix' | 'edge200_taiwan' | 'edge510' | 'edge810' | 'tempe' | 'fr910xt_japan' | 'fr620' | 'fr220' | 'fr910xt_korea' | 'fr10_japan' | 'edge810_japan' | 'virb_elite' | 'edge_touring' | 'edge510_japan' | 'hrm_tri' | 'hrm_run' | 'fr920xt' | 'edge510_asia' | 'edge810_china' | 'edge810_taiwan' | 'edge1000' | 'vivo_fit' | 'virb_remote' | 'vivo_ki' | 'fr15' | 'vivo_active' | 'edge510_korea' | 'fr620_japan' | 'fr620_china' | 'fr220_japan' | 'fr220_china' | 'approach_s6' | 'vivo_smart' | 'fenix2' | 'epix' | 'fenix3' | 'edge1000_taiwan' | 'edge1000_japan' | 'fr15_japan' | 'edge520' | 'edge1000_china' | 'fr620_russia' | 'fr220_russia' | 'vector_s' | 'edge1000_korea' | 'fr920xt_taiwan' | 'fr920xt_china' | 'fr920xt_japan' | 'virbx' | 'vivo_smart_apac' | 'etrex_touch' | 'edge25' | 'fr25' | 'vivo_fit2' | 'fr225' | 'fr630' | 'fr230' | 'fr735xt' | 'vivo_active_apac' | 'vector_2' | 'vector_2s' | 'virbxe' | 'fr620_taiwan' | 'fr220_taiwan' | 'truswing' | 'fenix3_china' | 'fenix3_twn' | 'varia_headlight' | 'varia_taillight_old' | 'edge_explore_1000' | 'fr225_asia' | 'varia_radar_taillight' | 'varia_radar_display' | 'edge20' | 'd2_bravo' | 'approach_s20' | 'varia_remote' | 'hrm4_run' | 'vivo_active_hr' | 'vivo_smart_hr' | 'vivo_move' | 'varia_vision' | 'vivo_fit3' | 'fenix3_hr' | 'virb_ultra_30' | 'index_smart_scale' | 'fr235' | 'fenix3_chronos' | 'oregon7xx' | 'rino7xx' | 'nautix' | 'edge_820' | 'edge_explore_820' | 'fenix5s' | 'd2_bravo_titanium' | 'varia_ut800' | 'running_dynamics_pod' | 'fenix5x' | 'vivo_fit_jr' | 'fr935' | 'fenix5' | 'descent' | 'sdm4' | 'edge_remote' | 'training_center' | 'connectiq_simulator' | 'android_antplus_plugin' | 'connect';
75
75
  export type AntplusDeviceType = 'antfs' | 'bike_power' | 'environment_sensor_legacy' | 'multi_sport_speed_distance' | 'control' | 'fitness_equipment' | 'blood_pressure' | 'geocache_node' | 'light_electric_vehicle' | 'env_sensor' | 'racquet' | 'control_hub' | 'muscle_oxygen' | 'shifting' | 'bike_light_main' | 'bike_light_shared' | 'exd' | 'bike_radar' | 'bike_aero' | 'weight_scale' | 'heart_rate' | 'bike_speed_cadence' | 'bike_cadence' | 'bike_speed' | 'stride_speed_distance';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fit-file-parser",
3
3
  "type": "module",
4
- "version": "3.0.1",
4
+ "version": "3.0.2",
5
5
  "private": false,
6
6
  "description": "Parse your .FIT files easily, directly from JS (Garmin, Polar, Suunto)",
7
7
  "author": {
@@ -32,6 +32,13 @@
32
32
  "garmin",
33
33
  "parse"
34
34
  ],
35
+ "files": [
36
+ "dist/",
37
+ "README.md",
38
+ "LICENSE",
39
+ "CHANGELOG.md",
40
+ "CONTRIBUTORS.md"
41
+ ],
35
42
  "exports": {
36
43
  ".": {
37
44
  "types": "./dist/fit-parser.d.ts",
@@ -75,4 +82,4 @@
75
82
  "typescript": "^5.9.3",
76
83
  "vitest": "^4.0.13"
77
84
  }
78
- }
85
+ }
@@ -1,35 +0,0 @@
1
- # FIT Parser Development Rules
2
-
3
- You are working on the `fit-parser` library. Follow these rules strictly to ensure correctness and stability.
4
-
5
- ## Core Principles
6
-
7
- 1. **Trust the Official SDK**:
8
- * Always verify Message IDs and Field IDs against the Official Garmin FIT SDK (`@garmin/fitsdk`).
9
- * **NEVER** guess or reuse existing IDs if they seem wrong (e.g., Message 140 vs 285).
10
- * If `@garmin/fitsdk` is available in `node_modules`, use it as the source of truth.
11
-
12
- 2. **Investigation First**:
13
- * If a field is missing, use `npm run inspect <file>` or `npm run probe <file> <value>` BEFORE modifying code.
14
- * Confirm the field exists in the file and identify its raw value.
15
-
16
- 3. **Testing is Mandatory**:
17
- * Every new message or field definition MUST have a corresponding test case in `test/`.
18
- * Test against real FIT files whenever possible (use `examples/` directory).
19
- * Use `npm run test` to verify changes.
20
-
21
- 4. **Code Generation**:
22
- * `src/fit_types.ts` is AUTO-GENERATED.
23
- * If you modify `src/fit.ts`, you **MUST** run `npm run codegen` to update types.
24
- * Do not edit `src/fit_types.ts` manually.
25
-
26
- ## Workflow checklist
27
-
28
- When adding a new message or fixing a field:
29
-
30
- - [ ] Locate official Message ID in Garmin SDK
31
- - [ ] Locate Field IDs and Types in Garmin SDK
32
- - [ ] Update `src/fit.ts` with new definition
33
- - [ ] Run `npm run codegen`
34
- - [ ] Add/Update test in `test/`
35
- - [ ] Run `npm run build && npm run test`
@@ -1,29 +0,0 @@
1
- ---
2
- name: add-fit-message
3
- description: Add a new FIT message or update an existing one
4
- ---
5
-
6
- # Add/Update FIT Message
7
-
8
- ## Prerequisites
9
-
10
- - Identify Message ID (e.g., 285 for Jump)
11
- - Identify Field IDs and Types from Garmin SDK
12
-
13
- ## Steps
14
-
15
- 1. **Modify `src/fit.ts`** - Add message definition
16
- 2. **Run `npm run codegen`** - Updates `src/fit_types.ts`
17
- 3. **Add Test** - Create test in `test/`
18
- 4. **Verify** - Run `npm run build && npm run test`
19
-
20
- ## Example Entry
21
-
22
- ```typescript
23
- 285: {
24
- name: 'jump',
25
- 253: { field: 'timestamp', type: 'date_time', scale: null, offset: 0, units: 's' },
26
- 0: { field: 'distance', type: 'float32', scale: null, offset: 0, units: 'm' },
27
- 5: { field: 'position_lat', type: 'sint32', scale: null, offset: 0, units: 'semicircles' },
28
- }
29
- ```
@@ -1,28 +0,0 @@
1
- ---
2
- description: common fit-parser development workflows
3
- ---
4
-
5
- # Inspect FIT File
6
-
7
- // turbo
8
- 1. node scripts/inspect_fit.js <path_to_fit_file> [message_key]
9
-
10
- # Probe FIT File for Value
11
-
12
- // turbo
13
- 1. node scripts/deep_probe.js <path_to_fit_file> <value> [tolerance]
14
-
15
- # Run Tests
16
-
17
- // turbo
18
- 1. npm run build && npm run test
19
-
20
- # Add New Message
21
-
22
- 1. Locate Message ID in `@garmin/fitsdk/src/profile.js`
23
- 2. Update `src/fit.ts` with message definition
24
- // turbo
25
- 3. npm run codegen
26
- 4. Add test in `test/`
27
- // turbo
28
- 5. npm run build && npm run test
package/.editorconfig DELETED
@@ -1,3 +0,0 @@
1
- [*]
2
- indent_style = space
3
- indent_size = 2
@@ -1,40 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [master]
6
- pull_request:
7
- branches: [master]
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
-
13
- strategy:
14
- matrix:
15
- node-version: [20.x, 22.x, 24.x, 25.x]
16
-
17
- steps:
18
- - uses: actions/checkout@v6
19
- - name: Use Node.js ${{ matrix.node-version }}
20
- uses: actions/setup-node@v6
21
- with:
22
- node-version: ${{ matrix.node-version }}
23
- cache: npm
24
- cache-dependency-path: package-lock.json
25
- - run: npm ci
26
- - run: npm run build
27
- - run: npm run test -- --coverage
28
- - run: npm run lint
29
- if: matrix.node-version == '25.x'
30
- - run: npm run type-check
31
- if: matrix.node-version == '25.x'
32
- - run: |
33
- npm run codegen
34
- if git diff --exit-code src/fit_types.ts; then
35
- echo "✓ src/fit_types.ts is unchanged after codegen"
36
- else
37
- echo "✗ src/fit_types.ts has been modified - please commit the changes"
38
- exit 1
39
- fi
40
- if: matrix.node-version == '25.x'
@@ -1,6 +0,0 @@
1
- {
2
- "recommendations": [
3
- "dbaeumer.vscode-eslint",
4
- "zixuanchen.vitest-explorer"
5
- ]
6
- }
@@ -1,27 +0,0 @@
1
- {
2
- "version": "0.2.0",
3
- "configurations": [
4
- {
5
- "name": "Run Dev (Codegen Watcher)",
6
- "type": "node",
7
- "request": "launch",
8
- "runtimeExecutable": "npm",
9
- "runtimeArgs": [
10
- "run",
11
- "dev"
12
- ],
13
- "console": "integratedTerminal"
14
- },
15
- {
16
- "type": "node",
17
- "request": "launch",
18
- "name": "Debug Vitest",
19
- "program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
20
- "args": [
21
- "run"
22
- ],
23
- "console": "integratedTerminal",
24
- "internalConsoleOptions": "neverOpen"
25
- }
26
- ]
27
- }
@@ -1,34 +0,0 @@
1
- {
2
- "version": "2.0.0",
3
- "tasks": [
4
- {
5
- "type": "npm",
6
- "script": "dev",
7
- "group": "build",
8
- "isBackground": true,
9
- "problemMatcher": {
10
- "owner": "typescript",
11
- "pattern": "$tsc",
12
- "background": {
13
- "activeOnStart": true,
14
- "beginsPattern": {
15
- "regexp": "^.*Starting compilation in watch mode.*$"
16
- },
17
- "endsPattern": {
18
- "regexp": "^.*Found [0-9]+ errors.*$"
19
- }
20
- }
21
- },
22
- "label": "npm: dev",
23
- "detail": "tsx --watch --watch-path=src/type_generator.ts --watch-path=src/fit.ts codegen/codegen.ts"
24
- },
25
- {
26
- "type": "npm",
27
- "script": "test",
28
- "group": "test",
29
- "problemMatcher": [],
30
- "label": "npm: test",
31
- "detail": "vitest"
32
- }
33
- ]
34
- }
package/INVESTIGATING.md DELETED
@@ -1,50 +0,0 @@
1
- # Investigating FIT Files
2
-
3
- This guide explains how to investigate FIT files when you suspect fields are missing or incorrectly parsed, and how to add support for new messages.
4
-
5
- ## Tools Included
6
-
7
- We provide scripts in the `scripts/` directory to help you probe FIT files.
8
-
9
- ### 1. Inspecting Parsed Data (`scripts/inspect_fit.js`)
10
-
11
- Use this script to see what the parser currently outputs for a file.
12
-
13
- ```bash
14
- # View summary of all messages in file
15
- node scripts/inspect_fit.js examples/jumps-mtb.fit
16
-
17
- # View specific message details
18
- node scripts/inspect_fit.js examples/jumps-mtb.fit jumps
19
- node scripts/inspect_fit.js examples/jumps-mtb.fit session
20
- ```
21
-
22
- ### 2. Probing for Unknown Data (`scripts/deep_probe.js`)
23
-
24
- Use this script when you know a value exists (e.g., from Garmin Connect or another tool) but can't find it in the parser output. It recursively searches the raw parsed structure for that value.
25
-
26
- ```bash
27
- # Edit the script to set the value you're looking for, then run:
28
- node scripts/deep_probe.js
29
- ```
30
-
31
- ## Workflow for Missing Fields
32
-
33
- If you suspect a field is missing (e.g., "Jump Hang Time"):
34
-
35
- 1. **Verify it exists**: Check the file with an external tool or online viewer. Note the exact value (e.g., `0.36` seconds).
36
- 2. **Probe**: Use `deep_probe.js` or inspect the `examples/` output to see if the value appears in an unknown field (e.g., `field_123`).
37
- 3. **Identify Message ID**:
38
- * Check `src/fit.ts` for the message definition.
39
- * If the message ID seems wrong, or fields are missing, compare with the **Official Garmin FIT SDK**.
40
- * *Tip: You can find the official SDK in `@garmin/fitsdk` if installed, or search online.*
41
- 4. **Fix**:
42
- * Update `src/fit.ts` with the correct Message ID and Field IDs.
43
- * Run `npm run codegen` to update types.
44
- * Add a test case in `test/` relative to your new message.
45
-
46
- ## Common Issues
47
-
48
- * **Wrong Message ID**: Sometimes `fit-parser` has legacy or guessed IDs (e.g., `jump` was 140, but official is 285).
49
- * **Missing Fields**: New devices add new fields. They often appear as `unknown_field_X`.
50
- * **Scale/Offset**: If values look huge (e.g., 20838184 instead of 20.838), check if they need a scale factor (e.g., `semicircles` to `degrees`).
package/check_ids.js DELETED
@@ -1,24 +0,0 @@
1
- import fs from 'fs';
2
- import FitParser from './dist/fit-parser.js';
3
-
4
- const content = fs.readFileSync('../sports-lib/samples/fit/jumps-mtb.fit');
5
- const fitParser = new (FitParser.default || FitParser)({ force: true, mode: 'both' });
6
-
7
- fitParser.parse(content, (error, data) => {
8
- if (error) { console.error(error); return; }
9
-
10
- // The parser stores messages in data[messageName]
11
- // Any unknown messages are in data[messageId] (if numeric)
12
- console.log('Keys in data:', Object.keys(data));
13
-
14
- // Let's check for anything that looks like a message ID
15
- for (const key of Object.keys(data)) {
16
- if (!isNaN(parseInt(key))) {
17
- console.log(`Unknown Message ID found: ${key} (${data[key].length} items)`);
18
- }
19
- }
20
-
21
- if (data.jumps) {
22
- console.log('Jumps fields:', Object.keys(data.jumps[0]));
23
- }
24
- });
@@ -1,46 +0,0 @@
1
- import fs from 'fs'
2
- import { createRequire } from 'module'
3
-
4
- const require = createRequire(import.meta.url)
5
- const FitParser = require('./dist/fit-parser.js').default
6
-
7
- const content = fs.readFileSync('./examples/jumps-mtb.fit')
8
- const fitParser = new FitParser({
9
- force: true,
10
- speedUnit: 'm/s',
11
- lengthUnit: 'm',
12
- temperatureUnit: 'celsius',
13
- elapsedRecordField: true,
14
- mode: 'both',
15
- })
16
-
17
- fitParser.parse(content, (error, data) => {
18
- if (error) {
19
- console.error(error)
20
- return
21
- }
22
-
23
- console.log('=== JUMPS ARRAY ===')
24
- if (data.jumps && data.jumps.length > 0) {
25
- data.jumps.forEach((jump, i) => {
26
- console.log(`\nJump ${i + 1}:`)
27
- Object.keys(jump).forEach((key) => {
28
- console.log(` ${key}: ${JSON.stringify(jump[key])}`)
29
- })
30
- })
31
- }
32
- else {
33
- console.log('No jumps found')
34
- }
35
-
36
- // Also check definitions array for message 140 (jump)
37
- console.log('\n=== DEFINITIONS FOR MESSAGE 140 (JUMP) ===')
38
- if (data.definitions) {
39
- const jumpDefs = data.definitions.filter(d => d && d.messageType === 140)
40
- console.log(`Found ${jumpDefs.length} jump definitions`)
41
- jumpDefs.forEach((def, i) => {
42
- console.log(`\nDefinition ${i + 1}:`)
43
- console.log(JSON.stringify(def, null, 2))
44
- })
45
- }
46
- })
@@ -1,9 +0,0 @@
1
- import { execSync } from 'node:child_process'
2
- import fs from 'node:fs'
3
- import { main } from '../src/type_generator.js'
4
-
5
- const out = main()
6
-
7
- fs.writeFileSync(`${import.meta.dirname}/../src/fit_types.ts`, out)
8
-
9
- execSync('npx eslint --fix src/fit_types.ts', { stdio: 'inherit' })
package/eslint.config.js DELETED
@@ -1,20 +0,0 @@
1
- import { antfu } from '@antfu/eslint-config'
2
-
3
- export default antfu({
4
- type: 'lib',
5
- gitignore: true,
6
- ignores: ['**/test/*.json'],
7
- stylistic: {
8
- indent: 2,
9
- quotes: 'single',
10
- },
11
- formatters: true,
12
- rules: {
13
- 'unicorn/prefer-node-protocol': 'off',
14
- },
15
- }, {
16
- files: ['**/examples/*.js', '**/codegen/*.ts', '**/probe_session.js', '**/deep_probe.js'],
17
- rules: {
18
- 'no-console': 'off',
19
- },
20
- })
package/find_field.js DELETED
@@ -1,23 +0,0 @@
1
- const fs = require('fs');
2
- const FitParser = require('./dist/fit-parser.js').default;
3
-
4
- const content = fs.readFileSync('../sports-lib/samples/fit/jumps-mtb.fit');
5
- const fitParser = new FitParser({ force: true, mode: 'both' });
6
-
7
- fitParser.parse(content, (error, data) => {
8
- if (error) { console.error(error); return; }
9
-
10
- function search(obj, path = '') {
11
- if (!obj || typeof obj !== 'object') return;
12
- for (const [key, value] of Object.entries(obj)) {
13
- const currentPath = path ? `${path}.${key}` : key;
14
- if (key === 'enhanced_mets') {
15
- console.log(`FOUND enhanced_mets at ${currentPath}: ${value}`);
16
- }
17
- search(value, currentPath);
18
- }
19
- }
20
-
21
- search(data);
22
- console.log('Search finished.');
23
- });
package/find_field_esm.js DELETED
@@ -1,28 +0,0 @@
1
- import fs from 'fs';
2
- import FitParser from './dist/fit-parser.js';
3
-
4
- const content = fs.readFileSync('../sports-lib/samples/fit/jumps-mtb.fit');
5
- // Try both ways to instantiate
6
- const fitParser = new (FitParser.default || FitParser)({ force: true, mode: 'both' });
7
-
8
- fitParser.parse(content, (error, data) => {
9
- if (error) { console.error(error); return; }
10
-
11
- function search(obj, path = '') {
12
- if (!obj || typeof obj !== 'object') return;
13
- if (Array.isArray(obj)) {
14
- obj.forEach((item, index) => search(item, `${path}[${index}]`));
15
- return;
16
- }
17
- for (const [key, value] of Object.entries(obj)) {
18
- const currentPath = path ? `${path}.${key}` : key;
19
- if (key === 'enhanced_mets') {
20
- console.log(`FOUND enhanced_mets at ${currentPath}: ${value}`);
21
- }
22
- search(value, currentPath);
23
- }
24
- }
25
-
26
- search(data);
27
- console.log('Search finished.');
28
- });
package/inspect_parser.ts DELETED
@@ -1,34 +0,0 @@
1
-
2
- import FitParser from './src/fit-parser';
3
- import * as fs from 'fs';
4
-
5
- const filePath = 'examples/road-with-power.fit';
6
-
7
- async function run() {
8
- try {
9
- const content = fs.readFileSync(filePath);
10
- const parser = new FitParser({
11
- force: true,
12
- });
13
-
14
- parser.parse(content, (error: any, data: any) => {
15
- if (error) {
16
- console.error(error);
17
- } else {
18
- console.log('Parsed successfully');
19
- // Check sessions for power zone data
20
- if (data.sessions && data.sessions.length > 0) {
21
- const session = data.sessions[0];
22
- console.log('Session keys:', Object.keys(session));
23
- console.log('time_in_power_zone:', session.time_in_power_zone);
24
- console.log('time_in_hr_zone:', session.time_in_hr_zone);
25
- console.log('time_in_speed_zone:', session.time_in_speed_zone);
26
- }
27
- }
28
- });
29
- } catch (e) {
30
- console.error(e);
31
- }
32
- }
33
-
34
- run();
package/output.txt DELETED
@@ -1,154 +0,0 @@
1
- >>> LOADING BINARY.TS <<<
2
- [DEBUG] Session field: 253 (timestamp), Type: date_time, Data: 1137663486
3
- [DEBUG] Session field: 2 (start_time), Type: date_time, Data: 1137663486
4
- [DEBUG] Session field: 3 (start_position_lat), Type: sint32, Data: 472983081
5
- [DEBUG] Session field: 4 (start_position_long), Type: sint32, Data: 250374956
6
- [DEBUG] Session field: 7 (total_elapsed_time), Type: uint32, Data: 14455786
7
- [DEBUG] Session field: 8 (total_timer_time), Type: uint32, Data: 14455786
8
- [DEBUG] Session field: 9 (total_distance), Type: uint32, Data: 3628685
9
- [DEBUG] Session field: 10 (total_cycles), Type: uint32, Data: 4294967295
10
- [DEBUG] Session field: 29 (nec_lat), Type: sint32, Data: 473011054
11
- [DEBUG] Session field: 30 (nec_long), Type: sint32, Data: 250518365
12
- [DEBUG] Session field: 31 (swc_lat), Type: sint32, Data: 472847023
13
- [DEBUG] Session field: 32 (swc_long), Type: sint32, Data: 250368555
14
- [DEBUG] Session field: 38 (end_position_lat), Type: sint32, Data: 472990941
15
- [DEBUG] Session field: 39 (end_position_long), Type: sint32, Data: 250515862
16
- [DEBUG] Session field: 48 (total_work), Type: uint32, Data: 4294967295
17
- [DEBUG] Session field: 110 (sport_profile_name), Type: string, Data: DOWNHILL MTB
18
- [DEBUG] Session field: 112 (time_standing), Type: uint32, Data: 4294967295
19
- [DEBUG] Session field: 116 (avg_left_power_phase), Type: uint8, Data: 255
20
- [DEBUG] Session field: 117 (avg_left_power_phase_peak), Type: uint8, Data: 255
21
- [DEBUG] Session field: 118 (avg_right_power_phase), Type: uint8, Data: 255
22
- [DEBUG] Session field: 119 (avg_right_power_phase_peak), Type: uint8, Data: 255
23
- [DEBUG] Session field: 120 (avg_power_position), Type: uint16, Data: 65535
24
- [DEBUG] Session field: 121 (max_power_position), Type: uint16, Data: 65535
25
- [DEBUG] Session field: 124 (enhanced_avg_speed), Type: uint32, Data: 2510
26
- [DEBUG] Session field: 125 (enhanced_max_speed), Type: uint32, Data: 11561
27
- [DEBUG] Session field: 168 (training_load_peak), Type: uint32, Data: 10061199
28
- [DEBUG] Session field: 181 (total_grit), Type: float32, Data: 180.6374969482422
29
- [DEBUG] Session field: 187 (avg_flow), Type: float32, Data: 5.879695892333984
30
- [DEBUG] Session field: 203 (undefined), Type: undefined, Data: 4294967295
31
- [DEBUG] Session field: 224 (undefined), Type: undefined, Data: 2147483647
32
- [DEBUG] Session field: 225 (undefined), Type: undefined, Data: 2147483647
33
- [DEBUG] Session field: 226 (undefined), Type: undefined, Data: 2147483647
34
- [DEBUG] Session field: 229 (undefined), Type: undefined, Data: 4294967295
35
- [DEBUG] Session field: 254 (message_index), Type: message_index, Data: 0
36
- [DEBUG] Session field: 11 (total_calories), Type: uint16, Data: 1215
37
- [DEBUG] Session field: 13 (total_fat_calories), Type: uint16, Data: 65535
38
- [DEBUG] Session field: 20 (avg_power), Type: uint16, Data: 65535
39
- [DEBUG] Session field: 21 (max_power), Type: uint16, Data: 65535
40
- [DEBUG] Session field: 22 (total_ascent), Type: uint16, Data: 1633
41
- [DEBUG] Session field: 23 (total_descent), Type: uint16, Data: 1880
42
- [DEBUG] Session field: 25 (first_lap_index), Type: uint16, Data: 0
43
- [DEBUG] Session field: 26 (num_laps), Type: uint16, Data: 1
44
- [DEBUG] Session field: 34 (normalized_power), Type: uint16, Data: 65535
45
- [DEBUG] Session field: 35 (training_stress_score), Type: uint16, Data: 65535
46
- [DEBUG] Session field: 36 (intensity_factor), Type: uint16, Data: 65535
47
- [DEBUG] Session field: 37 (left_right_balance), Type: left_right_balance_100, Data: 65535
48
- [DEBUG] Session field: 45 (threshold_power), Type: uint16, Data: 65535
49
- [DEBUG] Session field: 106 (undefined), Type: undefined, Data: 0
50
- [DEBUG] Session field: 107 (undefined), Type: undefined, Data: 65535
51
- [DEBUG] Session field: 108 (undefined), Type: undefined, Data: 178
52
- [DEBUG] Session field: 113 (stand_count), Type: uint16, Data: 65535
53
- [DEBUG] Session field: 139 (avg_vam), Type: uint16, Data: 189
54
- [DEBUG] Session field: 151 (undefined), Type: undefined, Data: 65535
55
- [DEBUG] Session field: 169 (enhanced_avg_respiration_rate), Type: uint16, Data: 2295
56
- [DEBUG] Session field: 170 (enhanced_max_respiration_rate), Type: uint16, Data: 4511
57
- [DEBUG] Session field: 177 (undefined), Type: undefined, Data: 65535
58
- [DEBUG] Session field: 178 (est_sweat_loss), Type: uint16, Data: 1455
59
- [DEBUG] Session field: 179 (undefined), Type: undefined, Data: 65535
60
- [DEBUG] Session field: 180 (enhanced_min_respiration_rate), Type: uint16, Data: 1040
61
- [DEBUG] Session field: 183 (jump_count), Type: uint16, Data: 129
62
- [DEBUG] Session field: 196 (resting_calories), Type: uint16, Data: 317
63
- [DEBUG] Session field: 204 (undefined), Type: undefined, Data: 65535
64
- [DEBUG] Session field: 0 (event), Type: event, Data: 8
65
- [DEBUG] Session field: 1 (event_type), Type: event_type, Data: 1
66
- [DEBUG] Session field: 5 (sport), Type: sport, Data: 2
67
- [DEBUG] Session field: 6 (sub_sport), Type: sub_sport, Data: 9
68
- [DEBUG] Session field: 16 (avg_heart_rate), Type: uint8, Data: 108
69
- [DEBUG] Session field: 17 (max_heart_rate), Type: uint8, Data: 179
70
- [DEBUG] Session field: 18 (avg_cadence), Type: uint8, Data: 255
71
- [DEBUG] Session field: 19 (max_cadence), Type: uint8, Data: 255
72
- [DEBUG] Session field: 24 (total_training_effect), Type: uint8, Data: 31
73
- [DEBUG] Session field: 27 (event_group), Type: uint8, Data: 255
74
- [DEBUG] Session field: 28 (trigger), Type: session_trigger, Data: 0
75
- [DEBUG] Session field: 57 (avg_temperature), Type: sint8, Data: 8
76
- [DEBUG] Session field: 58 (max_temperature), Type: sint8, Data: 16
77
- [DEBUG] Session field: 81 (undefined), Type: undefined, Data: 0
78
- [DEBUG] Session field: 92 (avg_fractional_cadence), Type: uint8, Data: 255
79
- [DEBUG] Session field: 93 (max_fractional_cadence), Type: uint8, Data: 255
80
- [DEBUG] Session field: 94 (total_fractional_cycles), Type: uint8, Data: 255
81
- [DEBUG] Session field: 101 (avg_left_torque_effectiveness), Type: uint8, Data: 255
82
- [DEBUG] Session field: 102 (avg_right_torque_effectiveness), Type: uint8, Data: 255
83
- [DEBUG] Session field: 103 (avg_left_pedal_smoothness), Type: uint8, Data: 255
84
- [DEBUG] Session field: 104 (avg_right_pedal_smoothness), Type: uint8, Data: 255
85
- [DEBUG] Session field: 105 (avg_combined_pedal_smoothness), Type: uint8, Data: 255
86
- [DEBUG] Session field: 109 (undefined), Type: undefined, Data: 255
87
- [DEBUG] Session field: 111 (sport_index), Type: uint8, Data: 255
88
- [DEBUG] Session field: 114 (avg_left_pco), Type: sint8, Data: 127
89
- [DEBUG] Session field: 115 (avg_right_pco), Type: sint8, Data: 127
90
- [DEBUG] Session field: 122 (avg_cadence_position), Type: uint8, Data: 255
91
- [DEBUG] Session field: 123 (max_cadence_position), Type: uint8, Data: 255
92
- [DEBUG] Session field: 137 (total_anaerobic_training_effect), Type: uint8, Data: 31
93
- [DEBUG] Session field: 138 (undefined), Type: undefined, Data: 8
94
- [DEBUG] Session field: 150 (min_temperature), Type: sint8, Data: 4
95
- [DEBUG] Session field: 184 (undefined), Type: undefined, Data: 0
96
- [DEBUG] Session field: 185 (undefined), Type: undefined, Data: 255
97
- [DEBUG] Session field: 188 (primary_benefit), Type: uint8, Data: 6
98
- [DEBUG] Session field: 192 (workout_feel), Type: uint8, Data: 255
99
- [DEBUG] Session field: 193 (workout_rpe), Type: uint8, Data: 255
100
- [DEBUG] Session field: 202 (undefined), Type: undefined, Data: 255
101
- [DEBUG] Session field: 205 (undefined), Type: undefined, Data: 255
102
- [DEBUG] Session field: 206 (undefined), Type: undefined, Data: 255
103
- [DEBUG] Session field: 207 (undefined), Type: undefined, Data: 255
104
- [DEBUG] Session field: 219 (undefined), Type: undefined, Data: 45
105
- Parsed successfully
106
- Session keys: [
107
- 'timestamp',
108
- 'start_time',
109
- 'start_position_lat',
110
- 'start_position_long',
111
- 'total_elapsed_time',
112
- 'total_timer_time',
113
- 'total_distance',
114
- 'nec_lat',
115
- 'nec_long',
116
- 'swc_lat',
117
- 'swc_long',
118
- 'end_position_lat',
119
- 'end_position_long',
120
- 'sport_profile_name',
121
- 'enhanced_avg_speed',
122
- 'enhanced_max_speed',
123
- 'training_load_peak',
124
- 'total_grit',
125
- 'avg_flow',
126
- 'message_index',
127
- 'total_calories',
128
- 'total_ascent',
129
- 'total_descent',
130
- 'first_lap_index',
131
- 'num_laps',
132
- 'left_right_balance',
133
- 'avg_vam',
134
- 'enhanced_avg_respiration_rate',
135
- 'enhanced_max_respiration_rate',
136
- 'est_sweat_loss',
137
- 'enhanced_min_respiration_rate',
138
- 'jump_count',
139
- 'resting_calories',
140
- 'event',
141
- 'event_type',
142
- 'sport',
143
- 'sub_sport',
144
- 'avg_heart_rate',
145
- 'max_heart_rate',
146
- 'total_training_effect',
147
- 'trigger',
148
- 'avg_temperature',
149
- 'max_temperature',
150
- 'total_anaerobic_training_effect',
151
- 'min_temperature',
152
- 'primary_benefit'
153
- ]
154
- time_in_power_zone: undefined
package/scan_jumps.js DELETED
@@ -1,29 +0,0 @@
1
- import fs from 'fs';
2
- import FitParser from './dist/fit-parser.js';
3
-
4
- const content = fs.readFileSync('../sports-lib/samples/fit/jumps-mtb.fit');
5
- const fitParser = new (FitParser.default || FitParser)({ force: true, mode: 'both' });
6
-
7
- fitParser.parse(content, (error, data) => {
8
- if (error) { console.error(error); return; }
9
-
10
- if (data.jumps && data.jumps.length > 0) {
11
- console.log(`Found ${data.jumps.length} jumps.`);
12
- data.jumps.forEach((j, i) => {
13
- // check for values close to 16.3038
14
- const target = 16.3038;
15
- const epsilon = 0.1;
16
-
17
- Object.entries(j).forEach(([key, val]) => {
18
- if (typeof val === 'number' && Math.abs(val - target) < epsilon) {
19
- console.log(`MATCH INDEX ${i} KEY ${key}: ${val}`);
20
- }
21
- });
22
-
23
- // Also just print field 7 ('speed' in new def)
24
- console.log(`Jump ${i}: speed=${j.speed}`);
25
- });
26
- } else {
27
- console.log('No jumps found.');
28
- }
29
- });
@@ -1,74 +0,0 @@
1
- import fs from 'fs'
2
- import { createRequire } from 'module'
3
-
4
- const require = createRequire(import.meta.url)
5
- // Try to load from local build or node_modules
6
- let FitParser
7
- try {
8
- FitParser = require('../dist/fit-parser.js').default
9
- }
10
- catch (e) {
11
- FitParser = require('fit-file-parser').default
12
- }
13
-
14
- const args = process.argv.slice(2)
15
- if (args.length < 2) {
16
- console.log('Usage: node deep_probe.js <path_to_fit_file> <search_value> [tolerance]')
17
- console.log('Example: node deep_probe.js ../examples/jumps-mtb.fit 11 0.1')
18
- process.exit(1)
19
- }
20
-
21
- const filePath = args[0]
22
- const targetValue = Number.parseFloat(args[1])
23
- const tolerance = args[2] ? Number.parseFloat(args[2]) : 0.001
24
-
25
- if (isNaN(targetValue)) {
26
- console.error('Error: Search value must be a number')
27
- process.exit(1)
28
- }
29
-
30
- try {
31
- const content = fs.readFileSync(filePath)
32
- const fitParser = new FitParser({
33
- force: true,
34
- speedUnit: 'm/s',
35
- lengthUnit: 'm',
36
- temperatureUnit: 'celsius',
37
- elapsedRecordField: true,
38
- mode: 'both',
39
- })
40
-
41
- function search(obj, path = []) {
42
- if (!obj || typeof obj !== 'object')
43
- return
44
-
45
- Object.keys(obj).forEach((key) => {
46
- const val = obj[key]
47
- const newPath = [...path, key]
48
-
49
- if (typeof val === 'number') {
50
- if (Math.abs(val - targetValue) <= tolerance) {
51
- console.log(`>>> FOUND MATCH at: ${newPath.join('.')} (Value: ${val})`)
52
- }
53
- }
54
-
55
- if (typeof val === 'object') {
56
- search(val, newPath)
57
- }
58
- })
59
- }
60
-
61
- fitParser.parse(content, (error, data) => {
62
- if (error) {
63
- console.error(error)
64
- }
65
- else {
66
- console.log(`Searching for value ${targetValue} (±${tolerance}) in ${filePath}...`)
67
- search(data)
68
- console.log('Search complete.')
69
- }
70
- })
71
- }
72
- catch (e) {
73
- console.error('Error:', e.message)
74
- }
@@ -1,69 +0,0 @@
1
- import fs from 'fs'
2
- import { createRequire } from 'module'
3
-
4
- const require = createRequire(import.meta.url)
5
- // Try to load from local build or node_modules
6
- let FitParser
7
- try {
8
- FitParser = require('../dist/fit-parser.js').default
9
- }
10
- catch (e) {
11
- FitParser = require('fit-file-parser').default
12
- }
13
-
14
- const args = process.argv.slice(2)
15
- if (args.length < 1) {
16
- console.log('Usage: node inspect_fit.js <path_to_fit_file> [message_key]')
17
- console.log('Example: node inspect_fit.js ../examples/jumps-mtb.fit jumps')
18
- process.exit(1)
19
- }
20
-
21
- const filePath = args[0]
22
- const messageKey = args[1]
23
-
24
- try {
25
- const content = fs.readFileSync(filePath)
26
- const fitParser = new FitParser({
27
- force: true,
28
- mode: 'both',
29
- speedUnit: 'm/s',
30
- lengthUnit: 'm',
31
- })
32
-
33
- fitParser.parse(content, (error, data) => {
34
- if (error) {
35
- console.error('Error parsing FIT file:', error)
36
- return
37
- }
38
-
39
- if (messageKey) {
40
- if (data[messageKey]) {
41
- console.log(`\n=== ${messageKey.toUpperCase()} (${Array.isArray(data[messageKey]) ? data[messageKey].length : 'object'}) ===`)
42
- console.log(JSON.stringify(data[messageKey], null, 2))
43
- }
44
- else if (data.activity && data.activity[messageKey]) {
45
- console.log(`\n=== ACTIVITY.${messageKey.toUpperCase()} ===`)
46
- console.log(JSON.stringify(data.activity[messageKey], null, 2))
47
- }
48
- else {
49
- console.log(`\nMessage key '${messageKey}' not found in root or activity object.`)
50
- console.log('Available keys:', Object.keys(data).join(', '))
51
- }
52
- }
53
- else {
54
- console.log('\n=== ROOT KEYS ===')
55
- console.log(Object.keys(data).join('\n'))
56
-
57
- // Print summary of counts
58
- console.log('\n=== SUMMARY ===')
59
- Object.keys(data).forEach((key) => {
60
- if (Array.isArray(data[key])) {
61
- console.log(`${key}: ${data[key].length} items`)
62
- }
63
- })
64
- }
65
- })
66
- }
67
- catch (e) {
68
- console.error('Error reading file:', e.message)
69
- }
package/tsconfig.cjs.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "module": "commonjs",
5
- "outDir": "./dist/cjs",
6
- "verbatimModuleSyntax": false
7
- }
8
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es6",
4
- "rootDir": "./src",
5
- "module": "Node16",
6
- "strict": true,
7
- "declaration": true,
8
- "outDir": "./dist",
9
- "esModuleInterop": true,
10
- "forceConsistentCasingInFileNames": true,
11
- "skipLibCheck": true
12
- },
13
- "include": ["src/**/*"],
14
- "exclude": ["node_modules"]
15
-
16
- }
package/vitest.config.js DELETED
@@ -1,8 +0,0 @@
1
- import { defineConfig } from 'vitest/config'
2
-
3
- export default defineConfig({
4
- test: {
5
- include: ['test/**/*.js', 'test/**/*.ts'],
6
- globals: true,
7
- },
8
- })