trackswap 0.2.6 → 0.2.7
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/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var Q=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapError",this.code=t,this.format=I.format,this.cause=I.cause}};function t_(R,t,_,I){if(R instanceof Q)return R;let T=R instanceof Error?R.message:String(R);return new Q(t,`${_}: ${T}`,{format:I,cause:R})}var y=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}};var n_="trackswap-health-ir-v1",Ct=new Set(["timestampCorrelationMesgs","monitoringInfoMesgs","monitoringMesgs","monitoringHrDataMesgs","stressLevelMesgs","respirationRateMesgs","spo2DataMesgs","hrvStatusSummaryMesgs","hrvValueMesgs","sleepLevelMesgs","sleepAssessmentMesgs","napEventMesgs","hsaStepDataMesgs","hsaSpo2DataMesgs","hsaStressDataMesgs","hsaRespirationDataMesgs","hsaHeartRateDataMesgs","hsaBodyBatteryDataMesgs","hsaWristTemperatureDataMesgs","skinTempOvernightMesgs","sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"]),TI=new Set([...Ct].filter(R=>R!=="timestampCorrelationMesgs")),AI=new Set(["fileIdMesgs","fileCreatorMesgs","deviceInfoMesgs","deviceSettingsMesgs","softwareMesgs","ohrSettingsMesgs","eventMesgs","activityMesgs","sessionMesgs","lapMesgs","recordMesgs","lengthMesgs","courseMesgs","coursePointMesgs","workoutMesgs","workoutStepMesgs","trainingFileMesgs"]),nI=[{field:"steps",metric:"steps",unit:"count",rolloverModulus:2**32,rolloverBits:32},{field:"distance",metric:"distance_m",unit:"m",rolloverModulus:2**32/100,rolloverBits:32},{field:"activeTime",metric:"active_time_s",unit:"s",rolloverModulus:2**32/1e3,rolloverBits:32},{field:"activeCalories",metric:"active_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16},{field:"calories",metric:"total_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16}],RI=[{field:"ascent",metric:"ascent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"descent",metric:"descent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"moderateActivityMinutes",metric:"moderate_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"},{field:"vigorousActivityMinutes",metric:"vigorous_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"}],ft=631065600,I_=2**16,Kt=18*60*60,LI=new Set([65519,65518]),EI=5;function X(R){return R&&typeof R=="object"?R:{}}function K(R){if(typeof R=="number")return Number.isFinite(R)?R:void 0;if(typeof R!="string"||R.trim()==="")return;let t=Number(R);return Number.isFinite(t)?t:void 0}function P(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R!="string"&&typeof R!="number"||typeof R=="string"&&R.trim()==="")return;let t=new Date(R);return Number.isFinite(t.valueOf())?t:void 0}function Dt(R){return vt(R)?.toISOString().replace(/Z$/,"")}function vt(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R=="string"&&!/^\s*[-+]?\d+(?:\.\d+)?\s*$/.test(R))return P(R);let t=K(R);if(!(t===void 0||t<0))return new Date((t+ft)*1e3)}function w(R,t,_){return{messageName:R,messageIndex:t,fieldName:_}}function Ht(R,t){return Object.fromEntries(t.map(_=>[_,R[_]]).filter(([,_])=>typeof _=="number"?Number.isFinite(_):["string","boolean"].includes(typeof _)))}function Xt(R){return Object.fromEntries(Object.entries(R).filter(([,t])=>Array.isArray(t)&&t.length>0).map(([t,_])=>[t,_?.length??0]))}function Pt(R){let t=[];return((R.activityMesgs?.length??0)>0||(R.sessionMesgs?.length??0)>0)&&t.push("activity"),[...TI].some(_=>(R[_]?.length??0)>0)&&t.push("health"),((R.workoutMesgs?.length??0)>0||(R.workoutStepMesgs?.length??0)>0)&&t.push("workout"),(R.courseMesgs?.length??0)>0&&t.push("course"),t.length===0&&((R.deviceInfoMesgs?.length??0)>0||(R.fileIdMesgs?.length??0)>0)&&t.push("device"),t.length>0?t:["unknown"]}function OI(R){let t=String(R??"").trim().toLowerCase().replace(/[_\s-]+/g,"");return t.includes("awake")?"awake":t.includes("deep")?"deep":t.includes("light")?"light":t.includes("rem")?"rem":t.includes("unmeasurable")?"unmeasurable":t.includes("sleep")?"sleeping":`vendor:${t||"unknown"}`}function SI(R,t=0){return new Date(R.valueOf()+t*1e3).toISOString().slice(0,10)}function wt(R,t,_=0){return SI(new Date(Math.max(R.valueOf(),t.valueOf()-1)),_)}function dt(R){let t=K(R);return t===void 0?void 0:t*60}function oI(R,t){let _=[],I=(n,L,E,f,F)=>{let U=P(E.timestamp),p=vt(E.localTimestamp);if(!U||!p)return;let W=Math.round((p.valueOf()-U.valueOf())/1e3),l=w(n,L,"localTimestamp");if(Math.abs(W)>Kt){t(l);return}_.push({at:U,offsetSeconds:W,priority:f,strategy:F,source:l})};(R.timestampCorrelationMesgs??[]).forEach((n,L)=>{I("timestampCorrelationMesgs",L,X(n),3,"timestamp_correlation")});for(let n of["monitoringInfoMesgs","monitoringMesgs","skinTempOvernightMesgs"])(R[n]??[]).forEach((L,E)=>{I(n,E,X(L),1,"inferred")});(R.napEventMesgs??[]).forEach((n,L)=>{let E=X(n);for(let[f,F]of[["startTime","startTimezoneOffset"],["endTime","endTimezoneOffset"]]){let U=P(E[f]),p=dt(E[F]);if(!U||p===void 0)continue;let W=w("napEventMesgs",L,F);if(Math.abs(p)>Kt){t(W);continue}_.push({at:U,offsetSeconds:p,priority:2,strategy:"explicit_offset",source:W})}}),_.sort((n,L)=>n.at.valueOf()-L.at.valueOf()||L.priority-n.priority);let T=_.filter((n,L)=>L===0||n.at.valueOf()!==_[L-1].at.valueOf()).map(({at:n,offsetSeconds:L})=>({at:n,offsetSeconds:L})),A=_.find(({strategy:n})=>n==="timestamp_correlation")?.strategy??_.find(({strategy:n})=>n==="explicit_offset")?.strategy??_.find(({strategy:n})=>n==="inferred")?.strategy??"unknown";return{offsets:T,strategy:A}}function DI(R,t){let _=K(R);if(!t||!Number.isInteger(_)||_<0||_>=I_)return;let I=Math.floor(t.valueOf()/1e3)-ft,T=Math.floor(I/I_)*I_+_;return T<I&&(T+=I_),new Date((T+ft)*1e3)}function HI(R){let t,_,I,T,A,n;return(R.monitoringMesgs??[]).map(L=>{let E=X(L),F=P(E.timestamp)??DI(E.timestamp16,t);F&&(t=F),F&&(!_||F>_)&&(I=_,_=F);let U=I;E.activityType!==void 0&&(T=E.activityType),E.deviceIndex!==void 0&&(n=E.deviceIndex);let p=E.intensity??E.activityLevel;return p!==void 0&&(A=p),{message:E,timestamp:F,intervalStartTime:U,deviceIndex:n,activityType:T,intensity:A}})}function Z(R,t){let _;for(let I of R){if(I.at>t)break;_=I.offsetSeconds}return _??R[0]?.offsetSeconds}function T_(R,t){if(t!==void 0)return new Date(R.valueOf()+t*1e3).toISOString().replace(/Z$/,"")}function CI(R,t,_,I){return t>=R?{value:t-R}:R>=_*.75&&R<_&&t>=0&&t<=_*.25?{value:_-R+t,rolloverBits:I}:null}function Yt(R){return R>=1&&R<=100?"valid":R===-1?"off_wrist":R===-2?"motion":R===-3?"not_enough_data":R===-4?"recovering":R===-5?"unidentified":R===-16?"gap":R===0||R>100?"invalid":"unknown"}function fI(R){return R>=0&&R<=100?"valid":Yt(R)}function dI(R){return R===255?"invalid":R===254?"motion":R===253?"off_wrist":R===252?"not_enough_data":R===2.4?"gap":R>=1&&R<=100?"valid":"invalid"}function i(R,t,_){return new Date(R.valueOf()+t*_*1e3)}function UI(R){let t=new Map,_={};R.warnings.forEach(I=>{_[I.code]=(_[I.code]??0)+1;let T=t.get(I.code)??[];T.length<EI&&(T.push(I),t.set(I.code,T))}),R.warningCounts=_,R.warnings=[...t.values()].flat()}function FI(R){return R===-1?"off_wrist":R===-2?"motion":R===-3?"invalid":R>0&&R<=100?"valid":"invalid"}function bt(R,t={},_={}){let I=Xt(R),T=Object.fromEntries(Object.entries(I).filter(([D])=>Ct.has(D))),A=Object.fromEntries(Object.entries(I).filter(([D])=>!Ct.has(D)&&!AI.has(D))),n={sdkProfileVersion:_.sdkProfileVersion,parserVersion:n_,messageCounts:I,recognizedMessageCounts:T,unknownMessageCounts:A,invalidValueCounts:{},warningCounts:{},warnings:[]};t.includeUnknownMessages&&(n.unknownMessages=Object.fromEntries(Object.keys(A).map(D=>[D,R[D]??[]])));let L=[],E=[],f=[],F=[],U=[],p=oI(R,D=>{n.warnings.push({code:"GARMIN_HEALTH_INVALID_TIMEZONE_OFFSET",message:"Ignored an implausible FIT timezone offset",source:D})}),{offsets:W}=p,l=D=>{let d=D.offsetSeconds??Z(W,D.timestamp);if(D.offsetSeconds=d,D.localTimestamp??=T_(D.timestamp,d),L.push(D),U.push(D.timestamp),D.status!=="valid"){let o=`${D.metric}:${D.status}`;n.invalidValueCounts[o]=(n.invalidValueCounts[o]??0)+1}},$=new Map;HI(R).forEach(({message:D,timestamp:d,intervalStartTime:o,deviceIndex:C,activityType:H,intensity:g},s)=>{if(!d){n.warnings.push({code:"GARMIN_HEALTH_NO_TIMESTAMP",message:"Monitoring message has no valid timestamp",source:w("monitoringMesgs",s)});return}U.push(d);let B=K(D.heartRate);if(B!==void 0){let G=B>0?"valid":"gap";l({metric:"heart_rate_bpm",timestamp:d,localTimestamp:Dt(D.localTimestamp),value:G==="valid"?B:void 0,unit:"bpm",status:G,aggregation:"instant",source:w("monitoringMesgs",s,"heartRate"),attributes:G==="valid"?void 0:{rawValue:B}})}let M=K(D.temperature);M!==void 0&&l({metric:"temperature_c",timestamp:d,localTimestamp:Dt(D.localTimestamp),value:M,unit:"degC",status:"valid",aggregation:"mean",source:w("monitoringMesgs",s,"temperature")});for(let G of nI){let v=K(D[G.field]);if(v===void 0)continue;let N=[C??"device",H??"activity",G.field].join(":"),V=$.get(N);if(V&&d>V.timestamp){let h=CI(V.value,v,G.rolloverModulus,G.rolloverBits);if(h){h.rolloverBits&&n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_ROLLOVER",message:`${G.field} accumulator rolled over at ${h.rolloverBits} bits`,source:w("monitoringMesgs",s,G.field)});let m=Z(W,V.timestamp);E.push({metric:G.metric,startTime:V.timestamp,endTime:d,localStartTime:T_(V.timestamp,m),offsetSeconds:m,value:h.value,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",s,G.field),attributes:t.health?.retainCumulativeValues===!1?void 0:{rawCumulativeValue:v}})}else n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_RESET",message:`${G.field} accumulator decreased; a new accumulation window was started`,source:w("monitoringMesgs",s,G.field)})}$.set(N,{timestamp:d,value:v})}for(let G of RI){let v=K(D[G.field]);if(v===void 0||v<0)continue;let N=v*(G.multiplier??1),V=G.intervalStrategy==="value_duration"?new Date(d.valueOf()-N*1e3):o;if(!V||V>=d)continue;let h=Z(W,V);U.push(V),E.push({metric:G.metric,startTime:V,endTime:d,localStartTime:T_(V,h),offsetSeconds:h,value:N,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",s,G.field)})}}),(R.monitoringHrDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);if(!C)return;[{field:"currentDayRestingHeartRate",metric:"resting_heart_rate_bpm"},{field:"restingHeartRate",metric:"resting_heart_rate_7_day_bpm"}].forEach(({field:g,metric:s})=>{let B=K(o[g]);if(B===void 0)return;let M=B>0?"valid":"invalid";l({metric:s,timestamp:C,value:M==="valid"?B:void 0,unit:"bpm",status:M,aggregation:"latest",source:w("monitoringHrDataMesgs",d,g),attributes:M==="valid"?void 0:{rawValue:B}})})}),(R.stressLevelMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.stressLevelTime),H=K(o.stressLevelValue);if(!C||H===void 0)return;let g=Yt(H);l({metric:"stress_level",timestamp:C,value:g==="valid"?H:void 0,unit:"score",status:g,aggregation:"instant",source:w("stressLevelMesgs",d,"stressLevelValue"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.respirationRateMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.respirationRate);if(!C||H===void 0)return;let g=FI(H);l({metric:"respiration_rate_bpm",timestamp:C,value:g==="valid"?H:void 0,unit:"breaths/min",status:g,aggregation:"instant",source:w("respirationRateMesgs",d,"respirationRate"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.spo2DataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.readingSpo2);if(!C||H===void 0)return;let g=K(o.readingConfidence),s=H<=0||H>100?"invalid":g!==void 0&&g<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:C,value:s==="invalid"?void 0:H,unit:"percent",status:s,quality:g,aggregation:"instant",source:w("spo2DataMesgs",d,"readingSpo2"),attributes:{measurementMode:o.mode===void 0?null:String(o.mode),...s==="invalid"?{rawValue:H}:{}}})}),(R.hrvValueMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.value);if(!C||H===void 0)return;let g=H>0?"valid":"invalid";l({metric:"hrv_rmssd_ms",timestamp:C,value:g==="valid"?H:void 0,unit:"ms",status:g,aggregation:"mean",source:w("hrvValueMesgs",d,"value"),attributes:{windowSeconds:300,...g==="valid"?{}:{rawValue:H}}})}),(R.hrvStatusSummaryMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);f.push({summaryType:"hrv_status",externalId:`fit:hrv-status:${C?.toISOString()??d}`,startTime:C,metrics:Ht(o,["weeklyAverage","lastNightAverage","lastNight5MinHigh","baselineLowUpper","baselineBalancedLower","baselineBalancedUpper","status"]),source:w("hrvStatusSummaryMesgs",d)}),C&&U.push(C)}),(R.monitoringInfoMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);f.push({summaryType:"device",externalId:`fit:monitoring-info:${C?.toISOString()??d}`,startTime:C,offsetSeconds:C?Z(W,C):void 0,metrics:Ht(o,["restingMetabolicRate","activityType","cyclesToDistance","cyclesToCalories"]),source:w("monitoringInfoMesgs",d)}),C&&U.push(C)}),(R.skinTempOvernightMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);if(!C)return;[{field:"averageDeviation",metric:"skin_temperature_deviation_c"},{field:"average7DayDeviation",metric:"skin_temperature_7_day_deviation_c"},{field:"nightlyValue",metric:"skin_temperature_nightly_c"}].forEach(({field:g,metric:s})=>{let B=K(o[g]);B!==void 0&&l({metric:s,timestamp:C,localTimestamp:Dt(o.localTimestamp),value:B,unit:"degC",status:"valid",aggregation:"mean",source:w("skinTempOvernightMesgs",d,g)})})});let Y=(R.sleepLevelMesgs??[]).map((D,d)=>({message:X(D),messageIndex:d,timestamp:P(X(D).timestamp)})).filter(D=>D.timestamp!==void 0).sort((D,d)=>D.timestamp.valueOf()-d.timestamp.valueOf());if(Y.length>=2){let D=X(R.sleepAssessmentMesgs?.[0]),d=[];for(let g=0;g<Y.length-1;g+=1){let s=Y[g],B=Y[g+1];if(B.timestamp<=s.timestamp)continue;let M={segmentType:OI(s.message.sleepLevel),startTime:s.timestamp,endTime:B.timestamp,status:"valid",source:w("sleepLevelMesgs",s.messageIndex,"sleepLevel")},G=d.at(-1);G&&G.segmentType===M.segmentType&&G.endTime.valueOf()===M.startTime.valueOf()?G.endTime=M.endTime:d.push(M)}let o=Y[0].timestamp,C=Y.at(-1).timestamp;U.push(o,C);let H=Z(W,C);F.push({sessionType:"sleep",externalId:`fit:sleep:${o.toISOString()}:${C.toISOString()}`,startTime:o,endTime:C,startOffsetSeconds:Z(W,o),endOffsetSeconds:H,calendarDate:wt(o,C,H),segments:d,metrics:Ht(D,["combinedAwakeScore","awakeTimeScore","awakeningsCountScore","deepSleepScore","sleepDurationScore","lightSleepScore","overallSleepScore","sleepQualityScore","sleepRecoveryScore","remSleepScore","sleepRestlessnessScore","awakeningsCount","interruptionsScore","averageStressDuringSleep"]),source:w("sleepLevelMesgs",Y[0].messageIndex),attributes:{calendarDateStrategy:H===void 0?"sleep_end_utc_fallback_date":"sleep_end_local_date"}})}else Y.length>0&&n.warnings.push({code:"GARMIN_HEALTH_SLEEP_BOUNDARY_INCOMPLETE",message:"Sleep level data does not contain enough boundaries",source:w("sleepLevelMesgs",Y[0].messageIndex)});for(let D of["sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"])(R[D]??[]).forEach((d,o)=>{let C=X(d),H=P(C.timestamp);!H||C.severity===void 0||(U.push(H),f.push({summaryType:"sleep",externalId:`fit:${D}:${C.messageIndex??o}:${H.toISOString()}`,startTime:H,offsetSeconds:Z(W,H),metrics:{severity:String(C.severity)},source:w(D,o,"severity")}))});return(R.napEventMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.startTime),H=P(o.endTime),g=o.isDeleted===!0;if(!C||!H||H<C||!g&&H.valueOf()===C.valueOf())return;let s=dt(o.startTimezoneOffset),B=dt(o.endTimezoneOffset);U.push(C,H),F.push({sessionType:"nap",externalId:`fit:nap:${o.messageIndex??d}:${C.toISOString()}`,startTime:C,endTime:H,startOffsetSeconds:s,endOffsetSeconds:B,calendarDate:wt(C,H,B??s),deleted:g,segments:[],metrics:{},source:w("napEventMesgs",d),attributes:{source:o.source===void 0?null:String(o.source),feedback:o.feedback===void 0?null:String(o.feedback),updateTimestamp:P(o.updateTimestamp)?.toISOString()??null}})}),(R.hsaStepDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.steps)?o.steps:[];!C||!H||H<=0||LI.has(H)||g.forEach((s,B)=>{let M=K(s);if(M===void 0||M<0)return;let G=i(C,H,B),v=new Date(G.valueOf()+H*1e3),N=Z(W,G);U.push(G,v),E.push({metric:"steps",startTime:G,endTime:v,localStartTime:T_(G,N),offsetSeconds:N,value:M,unit:"count",status:"valid",source:w("hsaStepDataMesgs",d,"steps"),attributes:{sequenceIndex:B,intervalSeconds:H}})})}),(R.hsaSpo2DataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.readingSpo2)?o.readingSpo2:[],s=Array.isArray(o.confidence)?o.confidence:[];!C||!H||H<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let v=K(s[M]),N=G<70||G>100||G===240?"invalid":v!==void 0&&v<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:i(C,H,M),value:N==="invalid"?void 0:G,unit:"percent",status:N,quality:v,aggregation:"instant",source:w("hsaSpo2DataMesgs",d,"readingSpo2"),attributes:{sequenceIndex:M,intervalSeconds:H,...N==="invalid"?{rawValue:G}:{}}})})}),(R.hsaStressDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.stressLevel)?o.stressLevel:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);if(M===void 0)return;let G=fI(M);l({metric:"stress_level",timestamp:i(C,H,B),value:G==="valid"?M:void 0,unit:"score",status:G,aggregation:"instant",source:w("hsaStressDataMesgs",d,"stressLevel"),attributes:{sequenceIndex:B,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaRespirationDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.respirationRate)?o.respirationRate:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);if(M===void 0)return;let G=dI(M);l({metric:"respiration_rate_bpm",timestamp:i(C,H,B),value:G==="valid"?M:void 0,unit:"breaths/min",status:G,aggregation:"instant",source:w("hsaRespirationDataMesgs",d,"respirationRate"),attributes:{sequenceIndex:B,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaHeartRateDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.heartRate)?o.heartRate:[],s=K(o.status);!C||!H||H<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let v=G===0?"gap":s===1?"valid":s===0?"low_confidence":"unknown";l({metric:"heart_rate_bpm",timestamp:i(C,H,M),value:v==="gap"?void 0:G,unit:"bpm",status:v,aggregation:"instant",source:w("hsaHeartRateDataMesgs",d,"heartRate"),attributes:{sequenceIndex:M,intervalSeconds:H,measurementStatus:s??null,...v==="gap"?{rawValue:G}:{}}})})}),(R.hsaWristTemperatureDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.value)?o.value:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);M!==void 0&&l({metric:"wrist_temperature_c",timestamp:i(C,H,B),value:M,unit:"degC",status:"valid",aggregation:"instant",source:w("hsaWristTemperatureDataMesgs",d,"value"),attributes:{sequenceIndex:B,intervalSeconds:H}})})}),(R.hsaBodyBatteryDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval)??0;if(!C||H<=0)return;[{field:"level",metric:"body_battery_level",unit:"score"},{field:"charged",metric:"body_battery_charged",unit:"score"},{field:"uncharged",metric:"body_battery_drained",unit:"score"}].forEach(({field:s,metric:B,unit:M})=>{(Array.isArray(o[s])?o[s]:[]).forEach((v,N)=>{let V=K(v);if(V===void 0)return;let h=s==="level"&&V===-16?"gap":s==="level"&&(V<0||V>100)?"invalid":"valid";l({metric:B,timestamp:i(C,H,N),value:h==="valid"?V:void 0,unit:M,status:h,aggregation:"instant",source:w("hsaBodyBatteryDataMesgs",d,s),attributes:{sequenceIndex:N,intervalSeconds:H,...h==="valid"?{}:{rawValue:V}}})})})}),L.sort((D,d)=>D.timestamp.valueOf()-d.timestamp.valueOf()),E.sort((D,d)=>D.startTime.valueOf()-d.startTime.valueOf()),F.sort((D,d)=>D.startTime.valueOf()-d.startTime.valueOf()),U.sort((D,d)=>D.valueOf()-d.valueOf()),UI(n),{schemaVersion:"1",observedStart:U[0],observedEnd:U.at(-1),timezone:{strategy:p.strategy,offsets:W},points:L,intervals:t.health?.reconstructIntervals===!1?[]:E,summaries:f,sessions:F,diagnostics:n}}var A_=class extends y{constructor(){super(...arguments);this.name="HealthStructurePlugin";this.priority=20}structureData(_,I){let T=I.userData?.fitDocumentOptions??{},A=Pt(_);return{healthDocument:A.includes("health")?bt(_,T,{sdkProfileVersion:I.metadata.get("fit-sdk-profile-version")}):void 0,fitDocumentMetadata:{detectedKinds:A,messageCounts:Xt(_)}}}};var R_=(S=>(S[S.GENERIC=0]="GENERIC",S[S.RUNNING=1]="RUNNING",S[S.CYCLING=2]="CYCLING",S[S.TRANSITION=3]="TRANSITION",S[S.FITNESS_EQUIPMENT=4]="FITNESS_EQUIPMENT",S[S.SWIMMING=5]="SWIMMING",S[S.BASKETBALL=6]="BASKETBALL",S[S.SOCCER=7]="SOCCER",S[S.TENNIS=8]="TENNIS",S[S.AMERICAN_FOOTBALL=9]="AMERICAN_FOOTBALL",S[S.TRAINING=10]="TRAINING",S[S.WALKING=11]="WALKING",S[S.CROSS_COUNTRY_SKIING=12]="CROSS_COUNTRY_SKIING",S[S.ALPINE_SKIING=13]="ALPINE_SKIING",S[S.SNOWBOARDING=14]="SNOWBOARDING",S[S.ROWING=15]="ROWING",S[S.MOUNTAINEERING=16]="MOUNTAINEERING",S[S.HIKING=17]="HIKING",S[S.MULTISPORT=18]="MULTISPORT",S[S.PADDLING=19]="PADDLING",S[S.FLYING=20]="FLYING",S[S.E_BIKING=21]="E_BIKING",S[S.MOTORCYCLING=22]="MOTORCYCLING",S[S.BOATING=23]="BOATING",S[S.DRIVING=24]="DRIVING",S[S.GOLF=25]="GOLF",S[S.HANG_GLIDING=26]="HANG_GLIDING",S[S.HORSEBACK_RIDING=27]="HORSEBACK_RIDING",S[S.HUNTING=28]="HUNTING",S[S.FISHING=29]="FISHING",S[S.INLINE_SKATING=30]="INLINE_SKATING",S[S.ROCK_CLIMBING=31]="ROCK_CLIMBING",S[S.SAILING=32]="SAILING",S[S.ICE_SKATING=33]="ICE_SKATING",S[S.SKY_DIVING=34]="SKY_DIVING",S[S.SNOWSHOEING=35]="SNOWSHOEING",S[S.SNOWMOBILING=36]="SNOWMOBILING",S[S.STAND_UP_PADDLEBOARDING=37]="STAND_UP_PADDLEBOARDING",S[S.SURFING=38]="SURFING",S[S.WAKEBOARDING=39]="WAKEBOARDING",S[S.WATER_SKIING=40]="WATER_SKIING",S[S.KAYAKING=41]="KAYAKING",S[S.RAFTING=42]="RAFTING",S[S.WINDSURFING=43]="WINDSURFING",S[S.KITESURFING=44]="KITESURFING",S[S.TACTICAL=45]="TACTICAL",S[S.JUMPMASTER=46]="JUMPMASTER",S[S.BOXING=47]="BOXING",S[S.FLOOR_CLIMBING=48]="FLOOR_CLIMBING",S[S.BASEBALL=49]="BASEBALL",S[S.DIVING=53]="DIVING",S[S.HIIT=62]="HIIT",S[S.RACKET=64]="RACKET",S[S.WHEELCHAIR_PUSH_WALK=65]="WHEELCHAIR_PUSH_WALK",S[S.WHEELCHAIR_PUSH_RUN=66]="WHEELCHAIR_PUSH_RUN",S[S.MEDITATION=67]="MEDITATION",S[S.DISC_GOLF=69]="DISC_GOLF",S[S.CRICKET=71]="CRICKET",S[S.RUGBY=72]="RUGBY",S[S.HOCKEY=73]="HOCKEY",S[S.LACROSSE=74]="LACROSSE",S[S.VOLLEYBALL=75]="VOLLEYBALL",S[S.WATER_TUBING=76]="WATER_TUBING",S[S.WAKESURFING=77]="WAKESURFING",S[S.MIXED_MARTIAL_ARTS=80]="MIXED_MARTIAL_ARTS",S[S.SNORKELING=82]="SNORKELING",S[S.DANCE=83]="DANCE",S[S.JUMP_ROPE=84]="JUMP_ROPE",S[S.ALL=254]="ALL",S))(R_||{});var L_=(O=>(O[O.GENERIC=0]="GENERIC",O[O.TREADMILL=1]="TREADMILL",O[O.STREET=2]="STREET",O[O.TRAIL=3]="TRAIL",O[O.TRACK=4]="TRACK",O[O.SPIN=5]="SPIN",O[O.INDOOR_CYCLING=6]="INDOOR_CYCLING",O[O.ROAD=7]="ROAD",O[O.MOUNTAIN=8]="MOUNTAIN",O[O.DOWNHILL=9]="DOWNHILL",O[O.RECUMBENT=10]="RECUMBENT",O[O.CYCLOCROSS=11]="CYCLOCROSS",O[O.HAND_CYCLING=12]="HAND_CYCLING",O[O.TRACK_CYCLING=13]="TRACK_CYCLING",O[O.INDOOR_ROWING=14]="INDOOR_ROWING",O[O.ELLIPTICAL=15]="ELLIPTICAL",O[O.STAIR_CLIMBING=16]="STAIR_CLIMBING",O[O.LAP_SWIMMING=17]="LAP_SWIMMING",O[O.OPEN_WATER=18]="OPEN_WATER",O[O.FLEXIBILITY_TRAINING=19]="FLEXIBILITY_TRAINING",O[O.STRENGTH_TRAINING=20]="STRENGTH_TRAINING",O[O.WARM_UP=21]="WARM_UP",O[O.MATCH=22]="MATCH",O[O.EXERCISE=23]="EXERCISE",O[O.CHALLENGE=24]="CHALLENGE",O[O.INDOOR_SKIING=25]="INDOOR_SKIING",O[O.CARDIO_TRAINING=26]="CARDIO_TRAINING",O[O.INDOOR_WALKING=27]="INDOOR_WALKING",O[O.E_BIKE_FITNESS=28]="E_BIKE_FITNESS",O[O.BMX=29]="BMX",O[O.CASUAL_WALKING=30]="CASUAL_WALKING",O[O.SPEED_WALKING=31]="SPEED_WALKING",O[O.BIKE_TO_RUN_TRANSITION=32]="BIKE_TO_RUN_TRANSITION",O[O.RUN_TO_BIKE_TRANSITION=33]="RUN_TO_BIKE_TRANSITION",O[O.SWIM_TO_BIKE_TRANSITION=34]="SWIM_TO_BIKE_TRANSITION",O[O.ATV=35]="ATV",O[O.MOTOCROSS=36]="MOTOCROSS",O[O.BACKCOUNTRY=37]="BACKCOUNTRY",O[O.RESORT=38]="RESORT",O[O.RC_DRONE=39]="RC_DRONE",O[O.WINGSUIT=40]="WINGSUIT",O[O.WHITEWATER=41]="WHITEWATER",O[O.SKATE_SKIING=42]="SKATE_SKIING",O[O.YOGA=43]="YOGA",O[O.PILATES=44]="PILATES",O[O.INDOOR_RUNNING=45]="INDOOR_RUNNING",O[O.GRAVEL_CYCLING=46]="GRAVEL_CYCLING",O[O.E_BIKE_MOUNTAIN=47]="E_BIKE_MOUNTAIN",O[O.COMMUTING=48]="COMMUTING",O[O.MIXED_SURFACE=49]="MIXED_SURFACE",O[O.NAVIGATE=50]="NAVIGATE",O[O.TRACK_ME=51]="TRACK_ME",O[O.MAP=52]="MAP",O[O.SINGLE_GAS_DIVING=53]="SINGLE_GAS_DIVING",O[O.MULTI_GAS_DIVING=54]="MULTI_GAS_DIVING",O[O.GAUGE_DIVING=55]="GAUGE_DIVING",O[O.APNEA_DIVING=56]="APNEA_DIVING",O[O.APNEA_HUNTING=57]="APNEA_HUNTING",O[O.VIRTUAL_ACTIVITY=58]="VIRTUAL_ACTIVITY",O[O.OBSTACLE=59]="OBSTACLE",O[O.BREATHING=62]="BREATHING",O[O.SAIL_RACE=65]="SAIL_RACE",O[O.ULTRA=67]="ULTRA",O[O.INDOOR_CLIMBING=68]="INDOOR_CLIMBING",O[O.BOULDERING=69]="BOULDERING",O[O.HIIT=70]="HIIT",O[O.AMRAP=73]="AMRAP",O[O.EMOM=74]="EMOM",O[O.TABATA=75]="TABATA",O[O.PICKLEBALL=84]="PICKLEBALL",O[O.PADEL=85]="PADEL",O[O.INDOOR_WHEELCHAIR_WALK=86]="INDOOR_WHEELCHAIR_WALK",O[O.INDOOR_WHEELCHAIR_RUN=87]="INDOOR_WHEELCHAIR_RUN",O[O.INDOOR_HAND_CYCLING=88]="INDOOR_HAND_CYCLING",O[O.SQUASH=94]="SQUASH",O[O.BADMINTON=95]="BADMINTON",O[O.RACQUETBALL=96]="RACQUETBALL",O[O.TABLE_TENNIS=97]="TABLE_TENNIS",O[O.FLY_CANOPY=110]="FLY_CANOPY",O[O.FLY_PARAGLIDE=111]="FLY_PARAGLIDE",O[O.FLY_PARAMOTOR=112]="FLY_PARAMOTOR",O[O.FLY_PRESSURIZED=113]="FLY_PRESSURIZED",O[O.FLY_NAVIGATE=114]="FLY_NAVIGATE",O[O.FLY_TIMER=115]="FLY_TIMER",O[O.FLY_ALTIMETER=116]="FLY_ALTIMETER",O[O.FLY_WX=117]="FLY_WX",O[O.FLY_VFR=118]="FLY_VFR",O[O.FLY_IFR=119]="FLY_IFR",O[O.ALL=254]="ALL",O))(L_||{});function Nt(R,t){if(!t)return;let _=t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let I of Object.keys(R)){if(!Number.isNaN(Number(I))||I.toUpperCase()!==_)continue;let T=R[I];return typeof T=="number"?T:void 0}}function GI(R){let t=R.metadata?.fileName?.trim();if(t)return t;let _=R.metadata?.originType;return _?`${_.toLowerCase()}-course`:"course"}function $t(R){let t=R.activities?.[0],I=[...(R.activities?.flatMap(T=>T.laps??[])??[]).flatMap(T=>T.records??[]),...R.routes?.flatMap(T=>T.records??[])??[],...R.points??[]].filter(T=>T.timestamp!=null&&T.positionLat!=null&&T.positionLong!=null).sort((T,A)=>new Date(T.timestamp).getTime()-new Date(A.timestamp).getTime()).map(T=>({timestamp:T.timestamp,latitude:T.positionLat,longitude:T.positionLong,distance:T.distance,altitude:T.enhancedAltitude??T.altitude,speed:T.enhancedSpeed??T.speed}));if(I.length===0)throw new Error("Cannot build a FIT course without timestamped coordinates");return{name:GI(R),sport:Nt(R_,t?.sport)??2,subSport:Nt(L_,t?.subSport)??0,records:I,timeCreated:I[0].timestamp}}function kt(){return process.env.TRACKSWAP_FIT_DEBUG==="1"||process.env.TRACKSWAP_DEBUG==="1"}function b(...R){kt()}function a(...R){kt()}var E_=class{constructor(){this.stage="parse"}async process(t){let _=Date.now();if(!t.rawData)throw new Error("FIT data cannot be empty");try{let I=await this.parseWithFitSDK(t.rawData,t);return t.rawMessages=I,b("\u{1F389} FIT parsing raw messages:",I),t.performance.parseTime=Date.now()-_,b(`\u{1F527} FIT parsing completed, contains message types: ${Object.keys(I).join(", ")}`),t}catch(I){throw new Error(`FIT parsing failed: ${I.message}`)}}async parseWithFitSDK(t,_){let{Decoder:I,Profile:T,Stream:A}=await import("@garmin/fitsdk"),n=[T.version?.major,T.version?.minor,T.version?.patch].filter(U=>U!==void 0);n.length>0&&_.metadata.set("fit-sdk-profile-version",n.join("."));let L=A.fromBuffer(t);if(!I.isFIT(L))throw new Error("Not a valid FIT file");let E=new I(L),{messages:f,errors:F}=E.read();return F&&F.length>0&&a("FIT parsing warnings:",F),f}};function gI(R){let t={...R};return t.position_lat!=null&&t.positionLat==null&&(t.positionLat=t.position_lat),t.position_long!=null&&t.positionLong==null&&(t.positionLong=t.position_long),t}var O_=class{constructor(t){this.getConverters=t;this.stage="extract"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Raw messages cannot be empty");let I={};for(let[T,A]of Object.entries(t.rawMessages)){if(!Array.isArray(A)||A.length===0){I[T]=A;continue}let n=this.getConverters(T);if(n.length===0)I[T]=T==="recordMesgs"?A.map(L=>gI(L)):A,b(`\u{1F4CB} Message type "${T}" has no converter, using raw data`);else{let L=n[0];try{let E=L.convertMessages(A,t);I[T]=E,b(`\u2705 Message type "${T}" using converter ${L.name}`)}catch(E){t.errors.push(E),I[T]=A,a(`FIT converter "${L.name}" failed for ${T}; raw messages were retained`,E)}}}return t.rawMessages=I,t.performance.extractTime=Date.now()-_,t}},S_=class{constructor(t){this.getStructurePlugins=t;this.stage="structure"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Message data cannot be empty");let I={...t.rawMessages},T=this.getStructurePlugins();for(let A of T)try{let n=A.structureData(t.rawMessages,t);I={...I,...n},b(`\u{1F527} Structure plugin ${A.name} processing completed`)}catch(n){throw t.errors.push(n),new Error(`FIT structure plugin "${A.name}" failed: ${n.message}`)}return t.result=I,t.performance.structureTime=Date.now()-_,t}},o_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,parseTime:t.performance.parseTime,extractTime:t.performance.extractTime,structureTime:t.performance.structureTime}),t.stats&&(t.stats.endTime=Date.now(),t.rawMessages&&(t.stats.processedTokens=this.countTotalMessages(t.rawMessages))),b(`\u2705 FIT processing completed, total time: ${_}ms`),t}countTotalMessages(t){let _=0;return Object.values(t).forEach(I=>{Array.isArray(I)&&(_+=I.length)}),_}};import k from"dayjs";var D_=class extends y{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(_,I){let{sessionMesgs:T,lapMesgs:A,recordMesgs:n,lengthMesgs:L,setMesgs:E}=_;if(!T?.length)return a("No structured session found, data structure is incomplete"),{};let f=T.map((p,W)=>{let l=k(p.startTime).valueOf(),$=l+(p.totalElapsedTime??0)*1e3,Y=k(p.timestamp).valueOf(),D=Math.max(Number.isFinite($)?$:Number.NEGATIVE_INFINITY,Number.isFinite(Y)?Y:Number.NEGATIVE_INFINITY),d=T[W+1],o=d?k(d.startTime).valueOf():Number.NaN,C=Number.isFinite(o)&&o>=l,H=p.firstLapIndex,g=p.numLaps,s=typeof H=="number"&&typeof g=="number"?(A??[]).filter(V=>{let h=V.messageIndex;return typeof h=="number"&&h>=H&&h<H+g}):[],B=(s.length===g&&s.length>0?s:(A??[]).filter(V=>{let h=k(V.startTime).valueOf();return Number.isFinite(h)&&h>=l&&h<=D+2e3})).sort((V,h)=>k(V.startTime).valueOf()-k(h.startTime).valueOf()),M=T.length===1?[...n??[]]:(n??[]).filter(V=>{let h=k(V.timestamp).valueOf();return Number.isFinite(h)?(W===0||h>=l)&&(!C||h<o):W===0}),G=(E??[]).filter(V=>{let h=k(V.startTime??V.timestamp).valueOf();return Number.isFinite(h)?h<l?!1:C?h<o:h<=D+2e3:T.length===1}),v=B.length>0?B:M.length>0?[{...p,messageIndex:typeof p.firstLapIndex=="number"?p.firstLapIndex:W,recordMesgs:M}]:[];if(B.length===0&&v.length===1){let V=Number(I.metadata.get("fit-synthetic-lap-count")??0);I.metadata.set("fit-synthetic-lap-count",V+1)}let N=v.map((V,h)=>{let m=k(V.startTime).valueOf(),Bt=v[h+1]?.startTime,Ot=Bt==null?Number.NaN:k(Bt).valueOf(),_I=m+(V.totalElapsedTime??0)*1e3,Vt=Number.isFinite(Ot)&&Ot>=m,tI=Vt?Ot:Math.max(_I,D),II=B.length===0?M:M.filter(ot=>{let c=k(ot.timestamp).valueOf();return Number.isFinite(c)?(h===0||c>=m)&&(!Vt||c<tI):h===0}),St=V.firstLengthIndex??void 0,pt=V.numLengths??void 0,ht=[];if(St!==void 0&&pt!==void 0){let ot=St+pt;ht=L?.filter(c=>c.messageIndex>=St&&c.messageIndex<ot)||[]}return{...V,recordMesgs:II,lengthMesgs:ht,messageIndex:V.messageIndex!==void 0?V.messageIndex:0}});return{...p,lapMesgs:N,setMesgs:G}}),F=new Set;for(let p of f)for(let W of p.lapMesgs??[])for(let l of W.recordMesgs??[])l?.timestamp!=null&&F.add(k(l.timestamp).valueOf());let U=0;for(let p of n??[]){if(p?.timestamp==null)continue;let W=k(p.timestamp).valueOf();F.has(W)||U++}return U>0&&(I.metadata.set("fit-unassigned-record-count",U),a(`SessionStructurePlugin: ${U} record(s) did not fall into any lap time window`)),{sessionMesgs:f}}},H_=class extends y{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(_,I){let{courseMesgs:T,lapMesgs:A,recordMesgs:n}=_;if(!T?.length)return{};let L=2e3;return{courseMesgs:T.map(f=>{let F=A?.map(U=>{let p=k(U.startTime).valueOf(),W=k(U.timestamp).valueOf(),l=n?.filter($=>{let Y=k($.timestamp).valueOf();return Y>=p-L&&Y<=W+L})||[];return{...U,recordMesgs:l}})||[];return{...f,lapMesgs:F}})}}},C_=class extends y{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(_,I){let{fileIdMesgs:T,fileCreatorMesgs:A,deviceInfoMesgs:n}=_;if(T?.length&&T[0]){let L=T[0];I.fileHeader={type:L.type,manufacturer:L.manufacturer,product:L.product}}return{fileIdMesgs:T,fileCreatorMesgs:A,deviceInfoMesgs:n}}};var f_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.structurePlugins=[];this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultPluginsRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new E_,new O_(t=>this.getConverters(t)),new S_(()=>this.structurePlugins),new o_],b("\u{1F527} FIT core pipeline processors initialized (fixed and not modifiable)")}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let t=[new C_,new D_,new H_,new A_];for(let _ of t)this.addStructurePlugin(_),this.registeredPlugins.add(_.name);this.defaultPluginsRegistered=!0,b("\u2705 Default FIT structure plugins auto-registered (FileHeader, Session, Course, etc.)")}addConverterForMessageType(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((T,A)=>(T.priority||100)-(A.priority||100))}addStructurePlugin(t){this.structurePlugins.push(t),this.structurePlugins.sort((_,I)=>(_.priority||100)-(I.priority||100))}async registerMessageConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Message converter plugin ${t.name} already exists`);t.supportedMessageTypes.forEach(I=>{this.addConverterForMessageType(I,t)}),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F4E6} Registered FIT message converter: ${t.name}${_}, supported message types: ${t.supportedMessageTypes.join(", ")}`),t.supportedMessageTypes.forEach(I=>{let A=(this.converterPlugins.get(I)||[]).map(n=>`${n.name}(${n.priority||100})`);b(` \u{1F4CB} Message type "${I}" converter priority: ${A.join(" > ")}`)})}async registerStructurePlugin(t){if(this.registeredPlugins.has(t.name))throw new Error(`Structure plugin ${t.name} already exists`);this.addStructurePlugin(t),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F3D7}\uFE0F Registered FIT structure plugin: ${t.name}${_}`)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(T=>T.name===t.name);_!==-1?(this.middlewarePlugins[_]=t,b(`\u{1F504} Updated FIT middleware: ${t.name}`)):(this.middlewarePlugins.push(t),this.middlewarePlugins.sort((T,A)=>(T.priority||100)-(A.priority||100)),b(`\u{1F50C} Registered FIT middleware: ${t.name}`));let I=[];t.onParse&&I.push("onParse"),t.onExtractMessages&&I.push("onExtractMessages"),t.onStructure&&I.push("onStructure"),t.onComplete&&I.push("onComplete"),t.onError&&I.push("onError"),I.length>0&&b(` \u{1F3A3} Supported hooks: ${I.join(", ")}`)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getConverters(t){return this.converterPlugins.get(t)||[]}unregisterPlugin(t){if(!this.registeredPlugins.has(t))return!1;for(let[T,A]of this.converterPlugins){let n=A.findIndex(L=>L.name===t);n!==-1&&(A.splice(n,1),A.length===0&&this.converterPlugins.delete(T))}let _=this.structurePlugins.findIndex(T=>T.name===t);_!==-1&&this.structurePlugins.splice(_,1);let I=this.middlewarePlugins.findIndex(T=>T.name===t);return I!==-1&&this.middlewarePlugins.splice(I,1),this.registeredPlugins.delete(t),b(`\u{1F5D1}\uFE0F Removed FIT plugin: ${t}`),!0}async initialize(){if(this.initialized)return;await this.registerDefaultPlugins();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let T=_;for(let A of this.middlewarePlugins){let n=A[t];if(n)try{T=await n.call(A,T,I)||T}catch(L){I.errors.push(L),await A.onError?.(L,I)}}return T}async parseByBuffer(t,_={}){await this.initialize();let I=this.createContext();I.rawData=t,I.userData=_.userData,I.metadata.set("decoder",this);try{for(let T of this.processors)try{switch(T.stage==="parse"&&I.rawData&&(I.rawData=await this.executeMiddlewareHook("onParse",I.rawData,I)),I=await T.process(I),T.stage){case"parse":break;case"extract":I.rawMessages&&(I.rawMessages=await this.executeMiddlewareHook("onExtractMessages",I.rawMessages,I));break;case"structure":I.result&&(I.result=await this.executeMiddlewareHook("onStructure",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(A){I.errors.push(A);for(let n of this.middlewarePlugins)await n.onError?.(A,I);throw new Error(`FIT pipeline stage "${T.stage}" failed: ${A.message}`)}return b("\u{1F389} FIT parsing completed",I.result),I.result}catch(T){throw T}}};var lI={file:{course:6,device:1,settings:2,sport:3,activity:4,workout:5,schedules:7,weight:9,totals:10,goals:11,blood_pressure:14,monitoring_a:15,activity_summary:20,monitoring_daily:28,monitoring_b:32,segment_list:35,exd_configuration:40,invalid:0},sport:{generic:0,running:1,cycling:2,transition:3,fitness_equipment:4,swimming:5,basketball:6,soccer:7,tennis:8,american_football:9,training:10,walking:11,cross_country_skiing:12,alpine_skiing:13,snowboarding:14,rowing:15,mountaineering:16,hiking:17,multisport:18,paddling:19,invalid:254},event:{timer:0,workout:3,workout_step:4,power_down:5,power_up:6,off_course:7,session:8,lap:9,course_point:10,battery:11,virtual_partner_pace:12,hr_high_alert:13,hr_low_alert:14,speed_high_alert:15,speed_low_alert:16,cad_high_alert:17,cad_low_alert:18,power_high_alert:19,power_low_alert:20,recovery_hr:21,battery_low:22,time_duration_alert:23,distance_duration_alert:24,calorie_duration_alert:25,activity:26,fitness_equipment:27,length:28,user_marker:32,sport_point:33,calibration:36,front_gear_change:42,rear_gear_change:43,rider_position_change:44,elev_high_alert:45,elev_low_alert:46,comm_timeout:47,invalid:255},event_type:{start:0,stop:1,consecutive_depreciated:2,marker:3,stop_all:4,begin_depreciated:5,end_depreciated:6,end_all_depreciated:7,stop_disable:8,stop_disable_all:9,invalid:255},course_point:{generic:0,summit:1,valley:2,water:3,food:4,danger:5,left:6,right:7,straight:8,first_aid:9,fourth_category:10,third_category:11,second_category:12,first_category:13,hors_category:14,sprint:15,left_fork:16,right_fork:17,middle_fork:18,slight_left:19,sharp_left:20,slight_right:21,sharp_right:22,u_turn:23,segment_start:24,segment_end:25,invalid:255}},r=R=>{let t=lI[R];return{size:1,baseType:0,mapValue:_=>typeof _=="string"?t[_]??255:_,setValue:function(_,I){this.setUint8(_,I)}}},Ut={enum_file:r("file"),enum_activity:r("sport"),enum_sport:r("sport"),enum_sub_sport:r("sport"),enum_event:r("event"),enum_event_type:r("event_type"),enum_course_point:r("course_point"),uint8:{size:1,baseType:2,setValue:DataView.prototype.setUint8},sint8:{size:1,baseType:1,setValue:DataView.prototype.setInt8},uint16:{size:2,baseType:132,setValue:DataView.prototype.setUint16},sint16:{size:2,baseType:131,setValue:DataView.prototype.setInt16},uint32:{size:4,baseType:134,setValue:DataView.prototype.setUint32},sint32:{size:4,baseType:133,setValue:DataView.prototype.setInt32},string:{size:0,baseType:7,mapValue:R=>Array.from(Jt(R)),setValue:WI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round(R*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round((R+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>{let t;return R instanceof Date?(t=Math.floor(R.getTime()/1e3),t-631065600):typeof R=="string"?(t=Math.floor(new Date(R).getTime()/1e3),t-631065600):R<631065600?Math.floor(R):(R>9999999999?t=Math.floor(R/1e3):t=Math.floor(R),t-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:R=>Math.round(R/180*2147483648)}};function Qt(R){return Array.from(Jt(R)).length+1}function*Jt(R){for(let t of sI(R))t<128?yield t:t<2048?(yield 192|t>>6,yield 128|t&63):t<65536?(yield 224|t>>12,yield 128|t>>6&63,yield 128|t&63):(yield 240|t>>18,yield 128|t>>12&63,yield 128|t>>6&63,yield 128|t&63);yield 0}function*sI(R){for(let t=0;t<R.length;){let _=R.codePointAt(t);if(_===void 0)break;yield _,t+=_>65535?2:1}}function WI(R,t){for(let _=0;_<t.length;_++)this.setUint8(R+_,t[_])}var BI={file_id:{mesgNum:0,fieldDefns:[{name:"type",number:0,type:"enum_file"},{name:"time_created",number:4,type:"date_time"}]},session:{mesgNum:18,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_calories",number:11,type:"uint16"},{name:"avg_heart_rate",number:16,type:"uint8"},{name:"max_heart_rate",number:17,type:"uint8"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"},{name:"sport",number:5,type:"enum_sport"},{name:"sub_sport",number:6,type:"enum_sub_sport"},{name:"first_lap_index",number:25,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"end_position_lat",number:5,type:"semicircles"},{name:"end_position_long",number:6,type:"semicircles"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_calories",number:11,type:"uint16"},{name:"avg_heart_rate",number:15,type:"uint8"},{name:"max_heart_rate",number:16,type:"uint8"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"}]},record:{mesgNum:20,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"position_lat",number:0,type:"semicircles"},{name:"position_long",number:1,type:"semicircles"},{name:"altitude",number:2,type:"altitude"},{name:"distance",number:5,type:"distance"},{name:"heart_rate",number:3,type:"uint8"},{name:"cadence",number:4,type:"uint8"},{name:"speed",number:6,type:"speed"},{name:"power",number:7,type:"uint16"}]},event:{mesgNum:21,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"event",number:0,type:"enum_event"},{name:"event_type",number:1,type:"enum_event_type"},{name:"event_group",number:4,type:"uint8"}]},course:{mesgNum:31,fieldDefns:[{name:"name",number:5,type:"string"},{name:"sport",number:4,type:"enum_sport"},{name:"sub_sport",number:7,type:"enum_sub_sport"}]},activity:{mesgNum:34,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"total_timer_time",number:0,type:"seconds"},{name:"num_sessions",number:1,type:"uint16"},{name:"type",number:2,type:"enum_activity"},{name:"event",number:3,type:"enum_event"},{name:"event_type",number:4,type:"enum_event_type"},{name:"local_timestamp",number:5,type:"date_time"},{name:"event_group",number:6,type:"uint8"}]},course_point:{mesgNum:32,fieldDefns:[{name:"timestamp",number:1,type:"date_time"},{name:"position_lat",number:2,type:"semicircles"},{name:"position_long",number:3,type:"semicircles"},{name:"distance",number:4,type:"distance"},{name:"type",number:5,type:"enum_course_point"}]}},VI=(R,t)=>R.map(_=>({..._,value:t[_.name]})).filter(({value:_})=>_!==void 0),d_=class R{static check(t,_,I,T){if(_===void 0)throw new Error(`Message '${t}' not known`);if(I===void 0)throw new Error(`Message '${t}' has no field definitions`);let A=I.map(L=>L.name),n=Object.keys(T).filter(L=>!A.includes(L));if(n.length)throw new Error(`Message '${t}' has no field definitions named '${n}'`)}constructor(t,_,I){let T=BI[_];if(!T)throw new Error(`Unknown message type: ${_}`);let{mesgNum:A,fieldDefns:n}=T;R.check(_,A,n,I),this.localNum=t,this.mesgNum=A,this.fields=VI(n,I)}get mesgDefn(){let t=this.fields.map(({number:_,type:I,value:T})=>{let A=Ut[I];if(!A)throw new Error(`Unknown type: ${I}`);let{size:n,baseType:L}=A;return I==="string"?{number:_,size:Qt(T),baseType:L}:{number:_,size:n,baseType:L}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:t}}isSameDefn(t){let _=(L,E)=>L.number===E.number&&L.size===E.size&&L.baseType===E.baseType,I=(L,E)=>L.length===E.length&&L.every((f,F)=>_(f,E[F])),{localNum:T,mesgNum:A,fieldDefns:n}=this.mesgDefn;return A===t.mesgNum&&T===t.localNum&&I(n,t.fieldDefns)}get defnRecord(){let{localNum:t,mesgNum:_,fieldDefns:I}=this.mesgDefn,T=6+3*I.length,A=new DataView(new ArrayBuffer(T));A.setUint8(0,64|t),A.setUint8(2,1),A.setUint16(3,_),A.setUint8(5,I.length);let n=6;for(let L of I)A.setUint8(n++,L.number),A.setUint8(n++,L.size),A.setUint8(n++,L.baseType);return A.buffer}get dataRecord(){let{fieldDefns:t}=this.mesgDefn,_=1+t.reduce((A,{size:n})=>A+n,0),I=new DataView(new ArrayBuffer(_));I.setUint8(0,this.localNum);let T=1;for(let{number:A,type:n,value:L}of this.fields){let E=Ut[n];if(!E)throw new Error(`Unknown type: ${n}`);let{size:f,setValue:F}=E,U;"mapValue"in E?U=E.mapValue(L):U=L,F&&F.call(I,T,U),T+=f}return I.buffer}};var pI=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],zt=(R,t)=>(R>>>4^pI[R&15^t])&65535,hI=(R,t,_)=>zt(zt(R,t),_),KI=(R,t)=>hI(R,t&15,t>>>4);function Ft(R,t=0){let _=t,I=R instanceof ArrayBuffer?new Uint8Array(R):R;for(let T=0;T<I.length;T++)_=KI(_,I[T]);return _}import wI from"dayjs";var jt=14,vI=16,XI=2078,PI=776358228,U_=class{constructor(t={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:t.compact??!0,defaultActivity:t.defaultActivity??"cycling",defaultSubActivity:t.defaultSubActivity??"generic"}}async encode(t){return this.reset(),this.buildFITContent(t,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(t){return this.reset(),this.buildFITContent(t,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(t,_="activity"){return this.reset(),this.buildFITContent(t,_),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(t,_){this.buildFileId(t,_),_==="course"?this.buildCourseContent(t):this.buildActivityContent(t)}buildActivityContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Activity file must contain at least one Session");let I=[],T=[],A=0;for(let[n,L]of _.entries()){let E=(L.lapMesgs??[]).map((F,U)=>({...F,messageIndex:A+U})),f={...L,messageIndex:n,firstLapIndex:A,numLaps:E.length,lapMesgs:E};E.length>0&&this.buildEventsFromLaps(E,I);for(let F of E)F.recordMesgs&&this.buildRecords(F.recordMesgs);E.length>0&&this.buildLaps(E),this.buildSession(f),this.buildActivityFromSession(f,T),A+=E.length}I.forEach(n=>this.buildEvent(n)),T.forEach(n=>this.buildActivity(n))}buildCourseContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Course file must contain track data");let I=_[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),I.lapMesgs){let T=[];for(let L of I.lapMesgs)L.recordMesgs&&T.push(...L.recordMesgs);T.sort((L,E)=>L.timestamp&&E.timestamp?new Date(L.timestamp).getTime()-new Date(E.timestamp).getTime():(L.distance||0)-(E.distance||0));let A=T[0],n=T[T.length-1];if(I.startTime&&this.buildEvent({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:0}),T.forEach(L=>this.buildRecord(L)),n.timestamp&&this.buildEvent({timestamp:n.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),I.lapMesgs)for(let L=0;L<I.lapMesgs.length;L++)this.buildLap(I.lapMesgs[L])}}buildFileId(t,_){let I=t.fileIdMesgs?.[0]||{};this.writeMesg("file_id",{type:_,time_created:I.timeCreated?this.parseTimestamp(I.timeCreated):Date.now(),manufacturer:I.manufacturer,product:I.product,serial_number:I.serialNumber})}buildSession(t){this.writeMesg("session",{message_index:t.messageIndex,timestamp:t.timestamp?t.timestamp:void 0,start_time:t.startTime?t.startTime:void 0,total_elapsed_time:t.totalElapsedTime,total_timer_time:t.totalTimerTime,total_calories:t.totalCalories,avg_heart_rate:t.avgHeartRate,max_heart_rate:t.maxHeartRate,start_position_lat:t.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,total_distance:t.totalDistance,total_ascent:t.totalAscent,total_descent:t.totalDescent,sport:t.sport||this.options.defaultActivity,sub_sport:t.subSport||this.options.defaultSubActivity,first_lap_index:t.firstLapIndex??0,num_laps:t.numLaps??t.lapMesgs?.length??0})}buildLaps(t){t.forEach(_=>this.buildLap(_))}buildLap(t){this.writeMesg("lap",{message_index:t.messageIndex,timestamp:t?.timestamp?t.timestamp:void 0,start_time:t?.startTime?t.startTime:void 0,start_position_lat:t?.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t?.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,end_position_lat:t?.endPositionLat!=null&&Number.isFinite(t.endPositionLat)?t.endPositionLat:void 0,end_position_long:t?.endPositionLong!=null&&Number.isFinite(t.endPositionLong)?t.endPositionLong:void 0,total_elapsed_time:t?.totalElapsedTime,total_timer_time:t?.totalTimerTime,total_calories:t?.totalCalories,avg_heart_rate:t?.avgHeartRate,max_heart_rate:t?.maxHeartRate,total_distance:t?.totalDistance,total_ascent:t?.totalAscent,total_descent:t?.totalDescent})}buildRecords(t){t.forEach(_=>this.buildRecord(_))}buildRecord(t){this.writeMesg("record",{timestamp:t.timestamp,position_lat:t?.positionLat!=null&&Number.isFinite(t.positionLat)?t.positionLat:void 0,position_long:t?.positionLong!=null&&Number.isFinite(t.positionLong)?t.positionLong:void 0,altitude:t?.altitude,enhancedAltitude:t?.enhancedAltitude,distance:t?.distance,heart_rate:t?.heartRate,cadence:t?.cadence,speed:t?.speed,enhancedSpeed:t?.enhancedSpeed,power:t?.power})}buildEvent(t){this.writeMesg("event",{timestamp:t.timestamp?t.timestamp:void 0,event:t.event,event_type:t.eventType,event_group:t.eventGroup})}buildActivity(t){this.writeMesg("activity",{timestamp:t.timestamp?t.timestamp:void 0,total_timer_time:t.totalTimerTime,num_sessions:t.numSessions,type:t.type,event:t.event,event_type:t.eventType,local_timestamp:t.localTimestamp?this.parseTimestamp(t.localTimestamp):void 0,event_group:t.eventGroup})}buildCourse(t){this.writeMesg("course",{name:t.name,sport:t.sport})}buildEventsFromLaps(t,_){t.forEach((I,T)=>{I.startTime&&_.push({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:T}),I.timestamp&&_.push({timestamp:I.timestamp,event:"timer",eventType:T===t.length-1?"stop_all":"stop",eventGroup:T})})}buildActivityFromSession(t,_){_.push({timestamp:t.timestamp,totalTimerTime:t.totalTimerTime,numSessions:1,type:t.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(t){return typeof t=="number"?t:wI(t).valueOf()}validateRequiredFields(t){if(!t.sessionMesgs||t.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(t,_){let I=Object.fromEntries(Object.entries(_).filter(([L,E])=>E!==void 0));if(Object.keys(I).length===0)return;let T=this.localNum[t];T===void 0&&(T=this.localNum[t]=Object.keys(this.localNum).length);let A=new d_(T,t,I),n=this.mesgDefn[T];(!n||!A.isSameDefn(n))&&(this.messages.push(A.defnRecord),this.mesgDefn[T]=A.mesgDefn),this.messages.push(A.dataRecord)}get blob(){let t=[this.header,...this.messages,this.trailer];return new Blob(t,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((t,_)=>t+_.byteLength,0)}get dataCrc(){return this.messages.reduce((t,_)=>Ft(_,t),0)}get header(){let t=new DataView(new ArrayBuffer(jt));return t.setUint8(0,jt),t.setUint8(1,vI),t.setUint16(2,XI,!0),t.setUint32(4,this.dataLen,!0),t.setUint32(8,PI),t.setUint16(12,Ft(t.buffer.slice(0,12)),!0),t.buffer}get trailer(){let t=new DataView(new ArrayBuffer(2));return t.setUint16(0,this.dataCrc,!0),t.buffer}async encoder(t){return this.encode(t)}};import{Encoder as YI}from"@garmin/fitsdk";var bI="development",NI=1,$I=1;function kI(R,t){if(!Number.isFinite(R))throw new Error(`${t} must be a finite number.`)}function F_(R,t){return kI(R,t),Math.abs(R)<=180?Math.round(R*2147483648/180):Math.round(R)}function QI(R){if(!R.name||R.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(R.records)||R.records.length===0)throw new Error("Course must contain at least one record point.");let t=R.records.map((I,T)=>{if(I==null)throw new Error(`Course record #${T+1} is missing.`);if(I.timestamp==null)throw new Error(`Course record #${T+1} is missing timestamp.`);return{...I,positionLat:F_(I.latitude,`records[${T}].latitude`),positionLong:F_(I.longitude,`records[${T}].longitude`)}}),_=(R.coursePoints??[]).map((I,T)=>{if(I==null)throw new Error(`Course point #${T+1} is missing.`);if(I.timestamp==null)throw new Error(`Course point #${T+1} is missing timestamp.`);return{...I,type:I.type??0,positionLat:F_(I.latitude,`coursePoints[${T}].latitude`),positionLong:F_(I.longitude,`coursePoints[${T}].longitude`)}});return{...R,sport:R.sport??2,subSport:R.subSport??0,records:t,coursePoints:_,manufacturer:R.manufacturer??bI,product:R.product??NI,serialNumber:R.serialNumber??$I,timeCreated:R.timeCreated??t[0].timestamp}}function JI(R){let t=QI(R),_=t.records[0],I=t.records[t.records.length-1],T=_.timestamp,A=I.timestamp,n=[{mesgNum:0,data:{type:6,manufacturer:t.manufacturer,product:t.product,serialNumber:t.serialNumber,timeCreated:t.timeCreated}},{mesgNum:31,data:{name:t.name,sport:t.sport,subSport:t.subSport}},{mesgNum:19,data:{startTime:T,timestamp:A,startPositionLat:_.positionLat,startPositionLong:_.positionLong,endPositionLat:I.positionLat,endPositionLong:I.positionLong,totalDistance:I.distance}},{mesgNum:21,data:{timestamp:T,event:0,eventType:0}}];return t.records.forEach(L=>{n.push({mesgNum:20,data:{timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,altitude:L.altitude,speed:L.speed}})}),t.coursePoints.forEach((L,E)=>{n.push({mesgNum:32,data:{messageIndex:E,timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,type:L.type,name:L.name,favorite:L.favorite}})}),n.push({mesgNum:21,data:{timestamp:A,event:0,eventType:4}}),n}function yt(R){let t=new YI;return JI(R).forEach(I=>{t.onMesg(I.mesgNum,I.data)}),t.close()}var q=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}parseFloat(t){if(!(typeof t>"u"))return typeof t=="number"?t:typeof t=="string"&&parseFloat(t)||0}parseInt(t){return typeof t=="number"?Math.floor(t):typeof t=="string"&&parseInt(t,10)||0}parseString(t){return String(t||"")}parseBoolean(t){return typeof t=="boolean"?t:typeof t=="string"?t.toLowerCase()==="true":!1}parseDate(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}hasRequiredAttributes(t,_){return _.every(I=>t.attributes?.[I])}extractAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([T,A])=>{let n=I[T];n&&(_[n]=String(A??""))})}processChildren(t,_,I){t.children?.forEach(T=>{let A=I[T.tag];A&&A(T,_)})}getChildValue(t,_){let I=t.children?.find(T=>T.tag===_);return I?.value?String(I.value):void 0}getChildByTag(t,_){return t.children?.find(I=>I.tag===_)}getChildrenByTag(t,_){return t.children?.filter(I=>I.tag===_)||[]}convertExtensions(t){let _={};return t.children?.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}convertExtensionContent(t){if(t.children?.length){let _={};return t.children.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}else return t.value}};var J=class extends q{parseCoordinate(t){let _=this.parseFloat(t);return _===0?void 0:_}parseGPXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}extractNumericAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([T,A])=>{let n=I[T];n&&n in _&&typeof A<"u"&&(_[n]=this.parseFloat(A))})}};var G_=class extends J{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(_,I){if(!this.hasRequiredAttributes(_,["lat","lon"])){I.warnings.push(`${this.name}: point without latitude or longitude was ignored`);return}let T={lat:this.parseFloat(_.attributes?.lat),lon:this.parseFloat(_.attributes?.lon)};return this.processChildren(_,T,{ele:(A,n)=>n.ele=this.parseFloat(A.value),time:(A,n)=>n.time=new Date(this.parseString(A.value)),speed:(A,n)=>n.speed=this.parseFloat(A.value),power:(A,n)=>n.power=this.parseFloat(A.value),cadence:(A,n)=>n.cadence=this.parseFloat(A.value),heartRate:(A,n)=>n.heartRate=this.parseFloat(A.value),course:(A,n)=>n.course=this.parseFloat(A.value),name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),sym:(A,n)=>n.sym=this.parseString(A.value),type:(A,n)=>n.type=this.parseString(A.value),fix:(A,n)=>n.fix=this.parseString(A.value),sat:(A,n)=>n.sat=this.parseFloat(A.value),hdop:(A,n)=>n.hdop=this.parseFloat(A.value),vdop:(A,n)=>n.vdop=this.parseFloat(A.value),pdop:(A,n)=>n.pdop=this.parseFloat(A.value),ageofdgpsdata:(A,n)=>n.ageofdgpsdata=this.parseFloat(A.value),geoidheight:(A,n)=>n.geoidheight=this.parseFloat(A.value),magvar:(A,n)=>n.magvar=this.parseFloat(A.value),dgpsid:(A,n)=>n.dgpsid=this.parseFloat(A.value),extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");if(E){let f=E.convert(A,I);f&&(this.mapExtensionsToPoint(f,n),n.extensions=f)}},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}mapExtensionsToPoint(_,I){Object.entries(_).forEach(([T,A])=>{if(A!==void 0&&(typeof A=="string"||typeof A=="number")){let n=L=>(Array.isArray(L)?L:[L]).some(f=>{let F=T.toLowerCase(),U=f.toLowerCase();return F===U||F.endsWith(`:${U}`)});n("speed")?I.speed=this.parseFloat(A):n("hr")?I.heartRate=this.parseFloat(A):n(["cad","cadence"])?I.cadence=this.parseFloat(A):n(["PowerInWatts","power"])&&(I.power=this.parseFloat(A))}})}},g_=class extends J{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(_,I){let T={rtept:[]};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),number:(A,n)=>n.number=this.parseFloat(A.value),type:(A,n)=>n.type=this.parseString(A.value),rtept:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(A,I);E&&n.rtept&&n.rtept.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},l_=class extends J{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(_,I){let T={trkseg:[]};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),number:(A,n)=>n.number=this.parseFloat(A.value),type:(A,n)=>n.type=this.parseString(A.value),trkseg:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("trkseg")?.convert(A,I);E&&n.trkseg&&n.trkseg.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},s_=class extends J{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(_,I){let T={trkpt:[]};return this.processChildren(_,T,{trkpt:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(A,I);E&&n.trkpt&&n.trkpt.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))}}),T}},W_=class extends J{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(_,I){let T={};return _.attributes?.href&&(T.href=_.attributes.href),this.processChildren(_,T,{text:(A,n)=>n.text=this.parseString(A.value),type:(A,n)=>n.type=this.parseString(A.value)}),T}},M_=class extends J{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(_,I){let T={};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),keywords:(A,n)=>n.keywords=this.parseString(A.value),time:(A,n)=>n.time=new Date(this.parseString(A.value)),author:(A,n)=>{let L=I.metadata.get("decoder");n.author=L?.getConverter("author")?.convert(A,I)},copyright:(A,n)=>{let L=I.metadata.get("decoder");n.copyright=L?.getConverter("copyright")?.convert(A,I)},bounds:(A,n)=>{let L=I.metadata.get("decoder");n.bounds=L?.getConverter("bounds")?.convert(A,I)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},B_=class extends J{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(_,I){let T={};return _.value&&!_.children?.length?(T.name=this.parseString(_.value),T):(this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),email:(A,n)=>{let L=I.metadata.get("decoder");n.email=L?.getConverter("email")?.convert(A,I)},link:(A,n)=>{let L=I.metadata.get("decoder");n.link=L?.getConverter("link")?.convert(A,I)}}),T)}},V_=class extends J{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(_,I){return{id:_.attributes?.id,domain:_.attributes?.domain}}},p_=class extends J{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(_,I){let T={};return _.attributes?.author&&(T.author=_.attributes.author),this.processChildren(_,T,{year:(A,n)=>n.year=this.parseString(A.value),license:(A,n)=>n.license=this.parseString(A.value)}),T}},h_=class extends J{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(_,I){let T={};return this.extractAttributes(_,T,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),T}},K_=class extends J{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(_,I){let T={};return _.children?.forEach(A=>{this.flattenExtensionElement(A,T)}),T}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(T=>{this.flattenExtensionElement(T,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),T=parseFloat(I);return!isNaN(T)&&isFinite(T)?T:I}};import{Parser as zI}from"htmlparser2";var w_=class{constructor(){this.stage="tokenize"}async process(t){let _=Date.now();if(!t.xmlContent)throw new Error("XML content cannot be empty");let I=[],T=new zI({onopentag(A,n){I.push({type:"open",tag:A,attributes:n})},ontext(A){let n=A.replace(/\n/g,"").trim();n&&I.push({type:"text",tag:"text",value:n})},onclosetag(A){I.push({type:"close",tag:A})}},{xmlMode:!0});return T.write(t.xmlContent),T.end(),t.tokens=I,t.performance.tokenizeTime=Date.now()-_,t}},v_=class{constructor(){this.stage="ast_generate"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],T,A=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};T?A&&A.children?.push(L):T=L,I.push(L),A=L}else n.type==="text"&&A?A.value=n.value:n.type==="close"&&(I.pop(),A=I[I.length-1]||null);return t.ast=T,t.performance.astTime=Date.now()-_,t}},X_=class{constructor(t){this.getConverter=t;this.stage="convert"}async process(t){let _=Date.now();if(!t.ast)throw new Error("AST cannot be empty");if(t.ast.tag!=="gpx")throw new Error(`Not a valid GPX document: expected <gpx>, received <${t.ast.tag}>`);let I={};return t.ast.attributes&&Object.entries(t.ast.attributes).forEach(([T,A])=>{T.startsWith("xmlns:")?I[T]=A.replace(/'/g,"'"):T==="xsi:schemaLocation"?I[T]=A.replace(/'/g,"'"):I[T]=A}),t.ast.children?.forEach(T=>{let A=this.getConverter(T.tag);if(!A){t.warnings.push(`Unsupported GPX element "${T.tag}" was ignored`);return}try{let n=A.convert(T,t);n&&this.assignResult(I,T.tag,n)}catch(n){throw t.errors.push(n),new Error(`GPX converter "${A.name}" failed for ${T.tag}: ${n.message}`)}}),t.result=I,t.performance.convertTime=Date.now()-_,t}assignResult(t,_,I){switch(_){case"metadata":t.metadata=I;break;case"wpt":t.wpt||(t.wpt=[]),t.wpt.push(I);break;case"rte":t.rte||(t.rte=[]),t.rte.push(I);break;case"trk":t.trk||(t.trk=[]),t.trk.push(I);break;case"extensions":t.extensions=I;break}}},P_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,tokenizeTime:t.performance.tokenizeTime,astTime:t.performance.astTime,convertTime:t.performance.convertTime}),t}};var Y_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new w_,new v_,new X_(t=>this.getConverter(t)),new P_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new G_,new g_,new l_,new s_,new W_,new M_,new B_,new V_,new p_,new h_,new K_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((T,A)=>(T.priority||100)-(A.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,T]of this.converterPlugins){let A=T.findIndex(n=>n.name===t);A!==-1&&(_=T[A],T.splice(A,1),T.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(t=>t.name)}listProcessors(){return this.processors.map(t=>t.constructor.name)}getConverterDetails(t){let _={};if(t){let I=this.converterPlugins.get(t);I&&(_[t]=I.map(T=>({name:T.name,priority:T.priority||100})))}else for(let[I,T]of this.converterPlugins)_[I]=T.map(A=>({name:A.name,priority:A.priority||100}));return _}getMiddlewareDetails(){return this.middlewarePlugins.map(t=>{let _=[];return t.onTokenize&&_.push("onTokenize"),t.onAstGenerate&&_.push("onAstGenerate"),t.onConvert&&_.push("onConvert"),t.onComplete&&_.push("onComplete"),t.onError&&_.push("onError"),{name:t.name,hooks:_}})}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let T=_;for(let A of this.middlewarePlugins){let n=A[t];if(n)try{T=await n.call(A,T,I)||T}catch(L){I.errors.push(L),await A.onError?.(L,I)}}return T}async parserByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast_generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(T){_.errors.push(T);for(let A of this.middlewarePlugins)await A.onError?.(T,_);throw new Error(`GPX pipeline stage "${I.stage}" failed: ${T.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:T,value:A}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(A!==void 0)return A;return _}};import qt from"dayjs";import jI from"dayjs/plugin/utc.js";var Gt={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var gt={temperature:"Temperature",Depth:"Depth"};qt.extend(jI);var b_=class{constructor(t={}){this.formatElevation=t=>{let _=parseFloat(t);return isNaN(_)?t:this.roundTo(_,2).toString()};this.compact=t.compact??!0}async encode(t){let _=this.buildGPXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildGPXXML(t)}buildGPXXML(t){let _=this.buildXMLHeader(t),I=this.buildGPXContent(t),A=`${_}${I}
|
|
1
|
+
var Q=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapError",this.code=t,this.format=I.format,this.cause=I.cause}};function t_(R,t,_,I){if(R instanceof Q)return R;let T=R instanceof Error?R.message:String(R);return new Q(t,`${_}: ${T}`,{format:I,cause:R})}var y=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}};var n_="trackswap-health-ir-v1",Ct=new Set(["timestampCorrelationMesgs","monitoringInfoMesgs","monitoringMesgs","monitoringHrDataMesgs","stressLevelMesgs","respirationRateMesgs","spo2DataMesgs","hrvStatusSummaryMesgs","hrvValueMesgs","sleepLevelMesgs","sleepAssessmentMesgs","napEventMesgs","hsaStepDataMesgs","hsaSpo2DataMesgs","hsaStressDataMesgs","hsaRespirationDataMesgs","hsaHeartRateDataMesgs","hsaBodyBatteryDataMesgs","hsaWristTemperatureDataMesgs","skinTempOvernightMesgs","sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"]),TI=new Set([...Ct].filter(R=>R!=="timestampCorrelationMesgs")),AI=new Set(["fileIdMesgs","fileCreatorMesgs","deviceInfoMesgs","deviceSettingsMesgs","softwareMesgs","ohrSettingsMesgs","eventMesgs","activityMesgs","sessionMesgs","lapMesgs","recordMesgs","lengthMesgs","courseMesgs","coursePointMesgs","workoutMesgs","workoutStepMesgs","trainingFileMesgs"]),nI=[{field:"steps",metric:"steps",unit:"count",rolloverModulus:2**32,rolloverBits:32},{field:"distance",metric:"distance_m",unit:"m",rolloverModulus:2**32/100,rolloverBits:32},{field:"activeTime",metric:"active_time_s",unit:"s",rolloverModulus:2**32/1e3,rolloverBits:32},{field:"activeCalories",metric:"active_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16},{field:"calories",metric:"total_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16}],RI=[{field:"ascent",metric:"ascent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"descent",metric:"descent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"moderateActivityMinutes",metric:"moderate_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"},{field:"vigorousActivityMinutes",metric:"vigorous_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"}],ft=631065600,I_=2**16,Kt=18*60*60,LI=new Set([65519,65518]),EI=5;function X(R){return R&&typeof R=="object"?R:{}}function K(R){if(typeof R=="number")return Number.isFinite(R)?R:void 0;if(typeof R!="string"||R.trim()==="")return;let t=Number(R);return Number.isFinite(t)?t:void 0}function P(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R!="string"&&typeof R!="number"||typeof R=="string"&&R.trim()==="")return;let t=new Date(R);return Number.isFinite(t.valueOf())?t:void 0}function Dt(R){return vt(R)?.toISOString().replace(/Z$/,"")}function vt(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R=="string"&&!/^\s*[-+]?\d+(?:\.\d+)?\s*$/.test(R))return P(R);let t=K(R);if(!(t===void 0||t<0))return new Date((t+ft)*1e3)}function w(R,t,_){return{messageName:R,messageIndex:t,fieldName:_}}function Ht(R,t){return Object.fromEntries(t.map(_=>[_,R[_]]).filter(([,_])=>typeof _=="number"?Number.isFinite(_):["string","boolean"].includes(typeof _)))}function Xt(R){return Object.fromEntries(Object.entries(R).filter(([,t])=>Array.isArray(t)&&t.length>0).map(([t,_])=>[t,_?.length??0]))}function Pt(R){let t=[];return((R.activityMesgs?.length??0)>0||(R.sessionMesgs?.length??0)>0)&&t.push("activity"),[...TI].some(_=>(R[_]?.length??0)>0)&&t.push("health"),((R.workoutMesgs?.length??0)>0||(R.workoutStepMesgs?.length??0)>0)&&t.push("workout"),(R.courseMesgs?.length??0)>0&&t.push("course"),t.length===0&&((R.deviceInfoMesgs?.length??0)>0||(R.fileIdMesgs?.length??0)>0)&&t.push("device"),t.length>0?t:["unknown"]}function OI(R){let t=String(R??"").trim().toLowerCase().replace(/[_\s-]+/g,"");return t.includes("awake")?"awake":t.includes("deep")?"deep":t.includes("light")?"light":t.includes("rem")?"rem":t.includes("unmeasurable")?"unmeasurable":t.includes("sleep")?"sleeping":`vendor:${t||"unknown"}`}function SI(R,t=0){return new Date(R.valueOf()+t*1e3).toISOString().slice(0,10)}function wt(R,t,_=0){return SI(new Date(Math.max(R.valueOf(),t.valueOf()-1)),_)}function dt(R){let t=K(R);return t===void 0?void 0:t*60}function oI(R,t){let _=[],I=(n,L,E,f,F)=>{let U=P(E.timestamp),p=vt(E.localTimestamp);if(!U||!p)return;let W=Math.round((p.valueOf()-U.valueOf())/1e3),l=w(n,L,"localTimestamp");if(Math.abs(W)>Kt){t(l);return}_.push({at:U,offsetSeconds:W,priority:f,strategy:F,source:l})};(R.timestampCorrelationMesgs??[]).forEach((n,L)=>{I("timestampCorrelationMesgs",L,X(n),3,"timestamp_correlation")});for(let n of["monitoringInfoMesgs","monitoringMesgs","skinTempOvernightMesgs"])(R[n]??[]).forEach((L,E)=>{I(n,E,X(L),1,"inferred")});(R.napEventMesgs??[]).forEach((n,L)=>{let E=X(n);for(let[f,F]of[["startTime","startTimezoneOffset"],["endTime","endTimezoneOffset"]]){let U=P(E[f]),p=dt(E[F]);if(!U||p===void 0)continue;let W=w("napEventMesgs",L,F);if(Math.abs(p)>Kt){t(W);continue}_.push({at:U,offsetSeconds:p,priority:2,strategy:"explicit_offset",source:W})}}),_.sort((n,L)=>n.at.valueOf()-L.at.valueOf()||L.priority-n.priority);let T=_.filter((n,L)=>L===0||n.at.valueOf()!==_[L-1].at.valueOf()).map(({at:n,offsetSeconds:L})=>({at:n,offsetSeconds:L})),A=_.find(({strategy:n})=>n==="timestamp_correlation")?.strategy??_.find(({strategy:n})=>n==="explicit_offset")?.strategy??_.find(({strategy:n})=>n==="inferred")?.strategy??"unknown";return{offsets:T,strategy:A}}function DI(R,t){let _=K(R);if(!t||!Number.isInteger(_)||_<0||_>=I_)return;let I=Math.floor(t.valueOf()/1e3)-ft,T=Math.floor(I/I_)*I_+_;return T<I&&(T+=I_),new Date((T+ft)*1e3)}function HI(R){let t,_,I,T,A,n;return(R.monitoringMesgs??[]).map(L=>{let E=X(L),F=P(E.timestamp)??DI(E.timestamp16,t);F&&(t=F),F&&(!_||F>_)&&(I=_,_=F);let U=I;E.activityType!==void 0&&(T=E.activityType),E.deviceIndex!==void 0&&(n=E.deviceIndex);let p=E.intensity??E.activityLevel;return p!==void 0&&(A=p),{message:E,timestamp:F,intervalStartTime:U,deviceIndex:n,activityType:T,intensity:A}})}function Z(R,t){let _;for(let I of R){if(I.at>t)break;_=I.offsetSeconds}return _??R[0]?.offsetSeconds}function T_(R,t){if(t!==void 0)return new Date(R.valueOf()+t*1e3).toISOString().replace(/Z$/,"")}function CI(R,t,_,I){return t>=R?{value:t-R}:R>=_*.75&&R<_&&t>=0&&t<=_*.25?{value:_-R+t,rolloverBits:I}:null}function Yt(R){return R>=1&&R<=100?"valid":R===-1?"off_wrist":R===-2?"motion":R===-3?"not_enough_data":R===-4?"recovering":R===-5?"unidentified":R===-16?"gap":R===0||R>100?"invalid":"unknown"}function fI(R){return R>=0&&R<=100?"valid":Yt(R)}function dI(R){return R===255?"invalid":R===254?"motion":R===253?"off_wrist":R===252?"not_enough_data":R===2.4?"gap":R>=1&&R<=100?"valid":"invalid"}function i(R,t,_){return new Date(R.valueOf()+t*_*1e3)}function UI(R){let t=new Map,_={};R.warnings.forEach(I=>{_[I.code]=(_[I.code]??0)+1;let T=t.get(I.code)??[];T.length<EI&&(T.push(I),t.set(I.code,T))}),R.warningCounts=_,R.warnings=[...t.values()].flat()}function FI(R){return R===-1?"off_wrist":R===-2?"motion":R===-3?"invalid":R>0&&R<=100?"valid":"invalid"}function bt(R,t={},_={}){let I=Xt(R),T=Object.fromEntries(Object.entries(I).filter(([D])=>Ct.has(D))),A=Object.fromEntries(Object.entries(I).filter(([D])=>!Ct.has(D)&&!AI.has(D))),n={sdkProfileVersion:_.sdkProfileVersion,parserVersion:n_,messageCounts:I,recognizedMessageCounts:T,unknownMessageCounts:A,invalidValueCounts:{},warningCounts:{},warnings:[]};t.includeUnknownMessages&&(n.unknownMessages=Object.fromEntries(Object.keys(A).map(D=>[D,R[D]??[]])));let L=[],E=[],f=[],F=[],U=[],p=oI(R,D=>{n.warnings.push({code:"GARMIN_HEALTH_INVALID_TIMEZONE_OFFSET",message:"Ignored an implausible FIT timezone offset",source:D})}),{offsets:W}=p,l=D=>{let d=D.offsetSeconds??Z(W,D.timestamp);if(D.offsetSeconds=d,D.localTimestamp??=T_(D.timestamp,d),L.push(D),U.push(D.timestamp),D.status!=="valid"){let o=`${D.metric}:${D.status}`;n.invalidValueCounts[o]=(n.invalidValueCounts[o]??0)+1}},$=new Map;HI(R).forEach(({message:D,timestamp:d,intervalStartTime:o,deviceIndex:C,activityType:H,intensity:g},s)=>{if(!d){n.warnings.push({code:"GARMIN_HEALTH_NO_TIMESTAMP",message:"Monitoring message has no valid timestamp",source:w("monitoringMesgs",s)});return}U.push(d);let B=K(D.heartRate);if(B!==void 0){let G=B>0?"valid":"gap";l({metric:"heart_rate_bpm",timestamp:d,localTimestamp:Dt(D.localTimestamp),value:G==="valid"?B:void 0,unit:"bpm",status:G,aggregation:"instant",source:w("monitoringMesgs",s,"heartRate"),attributes:G==="valid"?void 0:{rawValue:B}})}let M=K(D.temperature);M!==void 0&&l({metric:"temperature_c",timestamp:d,localTimestamp:Dt(D.localTimestamp),value:M,unit:"degC",status:"valid",aggregation:"mean",source:w("monitoringMesgs",s,"temperature")});for(let G of nI){let v=K(D[G.field]);if(v===void 0)continue;let N=[C??"device",H??"activity",G.field].join(":"),V=$.get(N);if(V&&d>V.timestamp){let h=CI(V.value,v,G.rolloverModulus,G.rolloverBits);if(h){h.rolloverBits&&n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_ROLLOVER",message:`${G.field} accumulator rolled over at ${h.rolloverBits} bits`,source:w("monitoringMesgs",s,G.field)});let m=Z(W,V.timestamp);E.push({metric:G.metric,startTime:V.timestamp,endTime:d,localStartTime:T_(V.timestamp,m),offsetSeconds:m,value:h.value,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",s,G.field),attributes:t.health?.retainCumulativeValues===!1?void 0:{rawCumulativeValue:v}})}else n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_RESET",message:`${G.field} accumulator decreased; a new accumulation window was started`,source:w("monitoringMesgs",s,G.field)})}$.set(N,{timestamp:d,value:v})}for(let G of RI){let v=K(D[G.field]);if(v===void 0||v<0)continue;let N=v*(G.multiplier??1),V=G.intervalStrategy==="value_duration"?new Date(d.valueOf()-N*1e3):o;if(!V||V>=d)continue;let h=Z(W,V);U.push(V),E.push({metric:G.metric,startTime:V,endTime:d,localStartTime:T_(V,h),offsetSeconds:h,value:N,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",s,G.field)})}}),(R.monitoringHrDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);if(!C)return;[{field:"currentDayRestingHeartRate",metric:"resting_heart_rate_bpm"},{field:"restingHeartRate",metric:"resting_heart_rate_7_day_bpm"}].forEach(({field:g,metric:s})=>{let B=K(o[g]);if(B===void 0)return;let M=B>0?"valid":"invalid";l({metric:s,timestamp:C,value:M==="valid"?B:void 0,unit:"bpm",status:M,aggregation:"latest",source:w("monitoringHrDataMesgs",d,g),attributes:M==="valid"?void 0:{rawValue:B}})})}),(R.stressLevelMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.stressLevelTime),H=K(o.stressLevelValue);if(!C||H===void 0)return;let g=Yt(H);l({metric:"stress_level",timestamp:C,value:g==="valid"?H:void 0,unit:"score",status:g,aggregation:"instant",source:w("stressLevelMesgs",d,"stressLevelValue"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.respirationRateMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.respirationRate);if(!C||H===void 0)return;let g=FI(H);l({metric:"respiration_rate_bpm",timestamp:C,value:g==="valid"?H:void 0,unit:"breaths/min",status:g,aggregation:"instant",source:w("respirationRateMesgs",d,"respirationRate"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.spo2DataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.readingSpo2);if(!C||H===void 0)return;let g=K(o.readingConfidence),s=H<=0||H>100?"invalid":g!==void 0&&g<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:C,value:s==="invalid"?void 0:H,unit:"percent",status:s,quality:g,aggregation:"instant",source:w("spo2DataMesgs",d,"readingSpo2"),attributes:{measurementMode:o.mode===void 0?null:String(o.mode),...s==="invalid"?{rawValue:H}:{}}})}),(R.hrvValueMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.value);if(!C||H===void 0)return;let g=H>0?"valid":"invalid";l({metric:"hrv_rmssd_ms",timestamp:C,value:g==="valid"?H:void 0,unit:"ms",status:g,aggregation:"mean",source:w("hrvValueMesgs",d,"value"),attributes:{windowSeconds:300,...g==="valid"?{}:{rawValue:H}}})}),(R.hrvStatusSummaryMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);f.push({summaryType:"hrv_status",externalId:`fit:hrv-status:${C?.toISOString()??d}`,startTime:C,metrics:Ht(o,["weeklyAverage","lastNightAverage","lastNight5MinHigh","baselineLowUpper","baselineBalancedLower","baselineBalancedUpper","status"]),source:w("hrvStatusSummaryMesgs",d)}),C&&U.push(C)}),(R.monitoringInfoMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);f.push({summaryType:"device",externalId:`fit:monitoring-info:${C?.toISOString()??d}`,startTime:C,offsetSeconds:C?Z(W,C):void 0,metrics:Ht(o,["restingMetabolicRate","activityType","cyclesToDistance","cyclesToCalories"]),source:w("monitoringInfoMesgs",d)}),C&&U.push(C)}),(R.skinTempOvernightMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp);if(!C)return;[{field:"averageDeviation",metric:"skin_temperature_deviation_c"},{field:"average7DayDeviation",metric:"skin_temperature_7_day_deviation_c"},{field:"nightlyValue",metric:"skin_temperature_nightly_c"}].forEach(({field:g,metric:s})=>{let B=K(o[g]);B!==void 0&&l({metric:s,timestamp:C,localTimestamp:Dt(o.localTimestamp),value:B,unit:"degC",status:"valid",aggregation:"mean",source:w("skinTempOvernightMesgs",d,g)})})});let Y=(R.sleepLevelMesgs??[]).map((D,d)=>({message:X(D),messageIndex:d,timestamp:P(X(D).timestamp)})).filter(D=>D.timestamp!==void 0).sort((D,d)=>D.timestamp.valueOf()-d.timestamp.valueOf());if(Y.length>=2){let D=X(R.sleepAssessmentMesgs?.[0]),d=[];for(let g=0;g<Y.length-1;g+=1){let s=Y[g],B=Y[g+1];if(B.timestamp<=s.timestamp)continue;let M={segmentType:OI(s.message.sleepLevel),startTime:s.timestamp,endTime:B.timestamp,status:"valid",source:w("sleepLevelMesgs",s.messageIndex,"sleepLevel")},G=d.at(-1);G&&G.segmentType===M.segmentType&&G.endTime.valueOf()===M.startTime.valueOf()?G.endTime=M.endTime:d.push(M)}let o=Y[0].timestamp,C=Y.at(-1).timestamp;U.push(o,C);let H=Z(W,C);F.push({sessionType:"sleep",externalId:`fit:sleep:${o.toISOString()}:${C.toISOString()}`,startTime:o,endTime:C,startOffsetSeconds:Z(W,o),endOffsetSeconds:H,calendarDate:wt(o,C,H),segments:d,metrics:Ht(D,["combinedAwakeScore","awakeTimeScore","awakeningsCountScore","deepSleepScore","sleepDurationScore","lightSleepScore","overallSleepScore","sleepQualityScore","sleepRecoveryScore","remSleepScore","sleepRestlessnessScore","awakeningsCount","interruptionsScore","averageStressDuringSleep"]),source:w("sleepLevelMesgs",Y[0].messageIndex),attributes:{calendarDateStrategy:H===void 0?"sleep_end_utc_fallback_date":"sleep_end_local_date"}})}else Y.length>0&&n.warnings.push({code:"GARMIN_HEALTH_SLEEP_BOUNDARY_INCOMPLETE",message:"Sleep level data does not contain enough boundaries",source:w("sleepLevelMesgs",Y[0].messageIndex)});for(let D of["sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"])(R[D]??[]).forEach((d,o)=>{let C=X(d),H=P(C.timestamp);!H||C.severity===void 0||(U.push(H),f.push({summaryType:"sleep",externalId:`fit:${D}:${C.messageIndex??o}:${H.toISOString()}`,startTime:H,offsetSeconds:Z(W,H),metrics:{severity:String(C.severity)},source:w(D,o,"severity")}))});return(R.napEventMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.startTime),H=P(o.endTime),g=o.isDeleted===!0;if(!C||!H||H<C||!g&&H.valueOf()===C.valueOf())return;let s=dt(o.startTimezoneOffset),B=dt(o.endTimezoneOffset);U.push(C,H),F.push({sessionType:"nap",externalId:`fit:nap:${o.messageIndex??d}:${C.toISOString()}`,startTime:C,endTime:H,startOffsetSeconds:s,endOffsetSeconds:B,calendarDate:wt(C,H,B??s),deleted:g,segments:[],metrics:{},source:w("napEventMesgs",d),attributes:{source:o.source===void 0?null:String(o.source),feedback:o.feedback===void 0?null:String(o.feedback),updateTimestamp:P(o.updateTimestamp)?.toISOString()??null}})}),(R.hsaStepDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.steps)?o.steps:[];!C||!H||H<=0||LI.has(H)||g.forEach((s,B)=>{let M=K(s);if(M===void 0||M<0)return;let G=i(C,H,B),v=new Date(G.valueOf()+H*1e3),N=Z(W,G);U.push(G,v),E.push({metric:"steps",startTime:G,endTime:v,localStartTime:T_(G,N),offsetSeconds:N,value:M,unit:"count",status:"valid",source:w("hsaStepDataMesgs",d,"steps"),attributes:{sequenceIndex:B,intervalSeconds:H}})})}),(R.hsaSpo2DataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.readingSpo2)?o.readingSpo2:[],s=Array.isArray(o.confidence)?o.confidence:[];!C||!H||H<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let v=K(s[M]),N=G<70||G>100||G===240?"invalid":v!==void 0&&v<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:i(C,H,M),value:N==="invalid"?void 0:G,unit:"percent",status:N,quality:v,aggregation:"instant",source:w("hsaSpo2DataMesgs",d,"readingSpo2"),attributes:{sequenceIndex:M,intervalSeconds:H,...N==="invalid"?{rawValue:G}:{}}})})}),(R.hsaStressDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.stressLevel)?o.stressLevel:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);if(M===void 0)return;let G=fI(M);l({metric:"stress_level",timestamp:i(C,H,B),value:G==="valid"?M:void 0,unit:"score",status:G,aggregation:"instant",source:w("hsaStressDataMesgs",d,"stressLevel"),attributes:{sequenceIndex:B,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaRespirationDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.respirationRate)?o.respirationRate:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);if(M===void 0)return;let G=dI(M);l({metric:"respiration_rate_bpm",timestamp:i(C,H,B),value:G==="valid"?M:void 0,unit:"breaths/min",status:G,aggregation:"instant",source:w("hsaRespirationDataMesgs",d,"respirationRate"),attributes:{sequenceIndex:B,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaHeartRateDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.heartRate)?o.heartRate:[],s=K(o.status);!C||!H||H<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let v=G===0?"gap":s===1?"valid":s===0?"low_confidence":"unknown";l({metric:"heart_rate_bpm",timestamp:i(C,H,M),value:v==="gap"?void 0:G,unit:"bpm",status:v,aggregation:"instant",source:w("hsaHeartRateDataMesgs",d,"heartRate"),attributes:{sequenceIndex:M,intervalSeconds:H,measurementStatus:s??null,...v==="gap"?{rawValue:G}:{}}})})}),(R.hsaWristTemperatureDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval),g=Array.isArray(o.value)?o.value:[];!C||!H||H<=0||g.forEach((s,B)=>{let M=K(s);M!==void 0&&l({metric:"wrist_temperature_c",timestamp:i(C,H,B),value:M,unit:"degC",status:"valid",aggregation:"instant",source:w("hsaWristTemperatureDataMesgs",d,"value"),attributes:{sequenceIndex:B,intervalSeconds:H}})})}),(R.hsaBodyBatteryDataMesgs??[]).forEach((D,d)=>{let o=X(D),C=P(o.timestamp),H=K(o.processingInterval)??0;if(!C||H<=0)return;[{field:"level",metric:"body_battery_level",unit:"score"},{field:"charged",metric:"body_battery_charged",unit:"score"},{field:"uncharged",metric:"body_battery_drained",unit:"score"}].forEach(({field:s,metric:B,unit:M})=>{(Array.isArray(o[s])?o[s]:[]).forEach((v,N)=>{let V=K(v);if(V===void 0)return;let h=s==="level"&&V===-16?"gap":s==="level"&&(V<0||V>100)?"invalid":"valid";l({metric:B,timestamp:i(C,H,N),value:h==="valid"?V:void 0,unit:M,status:h,aggregation:"instant",source:w("hsaBodyBatteryDataMesgs",d,s),attributes:{sequenceIndex:N,intervalSeconds:H,...h==="valid"?{}:{rawValue:V}}})})})}),L.sort((D,d)=>D.timestamp.valueOf()-d.timestamp.valueOf()),E.sort((D,d)=>D.startTime.valueOf()-d.startTime.valueOf()),F.sort((D,d)=>D.startTime.valueOf()-d.startTime.valueOf()),U.sort((D,d)=>D.valueOf()-d.valueOf()),UI(n),{schemaVersion:"1",observedStart:U[0],observedEnd:U.at(-1),timezone:{strategy:p.strategy,offsets:W},points:L,intervals:t.health?.reconstructIntervals===!1?[]:E,summaries:f,sessions:F,diagnostics:n}}var A_=class extends y{constructor(){super(...arguments);this.name="HealthStructurePlugin";this.priority=20}structureData(_,I){let T=I.userData?.fitDocumentOptions??{},A=Pt(_);return{healthDocument:A.includes("health")?bt(_,T,{sdkProfileVersion:I.metadata.get("fit-sdk-profile-version")}):void 0,fitDocumentMetadata:{detectedKinds:A,messageCounts:Xt(_)}}}};var R_=(S=>(S[S.GENERIC=0]="GENERIC",S[S.RUNNING=1]="RUNNING",S[S.CYCLING=2]="CYCLING",S[S.TRANSITION=3]="TRANSITION",S[S.FITNESS_EQUIPMENT=4]="FITNESS_EQUIPMENT",S[S.SWIMMING=5]="SWIMMING",S[S.BASKETBALL=6]="BASKETBALL",S[S.SOCCER=7]="SOCCER",S[S.TENNIS=8]="TENNIS",S[S.AMERICAN_FOOTBALL=9]="AMERICAN_FOOTBALL",S[S.TRAINING=10]="TRAINING",S[S.WALKING=11]="WALKING",S[S.CROSS_COUNTRY_SKIING=12]="CROSS_COUNTRY_SKIING",S[S.ALPINE_SKIING=13]="ALPINE_SKIING",S[S.SNOWBOARDING=14]="SNOWBOARDING",S[S.ROWING=15]="ROWING",S[S.MOUNTAINEERING=16]="MOUNTAINEERING",S[S.HIKING=17]="HIKING",S[S.MULTISPORT=18]="MULTISPORT",S[S.PADDLING=19]="PADDLING",S[S.FLYING=20]="FLYING",S[S.E_BIKING=21]="E_BIKING",S[S.MOTORCYCLING=22]="MOTORCYCLING",S[S.BOATING=23]="BOATING",S[S.DRIVING=24]="DRIVING",S[S.GOLF=25]="GOLF",S[S.HANG_GLIDING=26]="HANG_GLIDING",S[S.HORSEBACK_RIDING=27]="HORSEBACK_RIDING",S[S.HUNTING=28]="HUNTING",S[S.FISHING=29]="FISHING",S[S.INLINE_SKATING=30]="INLINE_SKATING",S[S.ROCK_CLIMBING=31]="ROCK_CLIMBING",S[S.SAILING=32]="SAILING",S[S.ICE_SKATING=33]="ICE_SKATING",S[S.SKY_DIVING=34]="SKY_DIVING",S[S.SNOWSHOEING=35]="SNOWSHOEING",S[S.SNOWMOBILING=36]="SNOWMOBILING",S[S.STAND_UP_PADDLEBOARDING=37]="STAND_UP_PADDLEBOARDING",S[S.SURFING=38]="SURFING",S[S.WAKEBOARDING=39]="WAKEBOARDING",S[S.WATER_SKIING=40]="WATER_SKIING",S[S.KAYAKING=41]="KAYAKING",S[S.RAFTING=42]="RAFTING",S[S.WINDSURFING=43]="WINDSURFING",S[S.KITESURFING=44]="KITESURFING",S[S.TACTICAL=45]="TACTICAL",S[S.JUMPMASTER=46]="JUMPMASTER",S[S.BOXING=47]="BOXING",S[S.FLOOR_CLIMBING=48]="FLOOR_CLIMBING",S[S.BASEBALL=49]="BASEBALL",S[S.DIVING=53]="DIVING",S[S.HIIT=62]="HIIT",S[S.RACKET=64]="RACKET",S[S.WHEELCHAIR_PUSH_WALK=65]="WHEELCHAIR_PUSH_WALK",S[S.WHEELCHAIR_PUSH_RUN=66]="WHEELCHAIR_PUSH_RUN",S[S.MEDITATION=67]="MEDITATION",S[S.DISC_GOLF=69]="DISC_GOLF",S[S.CRICKET=71]="CRICKET",S[S.RUGBY=72]="RUGBY",S[S.HOCKEY=73]="HOCKEY",S[S.LACROSSE=74]="LACROSSE",S[S.VOLLEYBALL=75]="VOLLEYBALL",S[S.WATER_TUBING=76]="WATER_TUBING",S[S.WAKESURFING=77]="WAKESURFING",S[S.MIXED_MARTIAL_ARTS=80]="MIXED_MARTIAL_ARTS",S[S.SNORKELING=82]="SNORKELING",S[S.DANCE=83]="DANCE",S[S.JUMP_ROPE=84]="JUMP_ROPE",S[S.ALL=254]="ALL",S))(R_||{});var L_=(O=>(O[O.GENERIC=0]="GENERIC",O[O.TREADMILL=1]="TREADMILL",O[O.STREET=2]="STREET",O[O.TRAIL=3]="TRAIL",O[O.TRACK=4]="TRACK",O[O.SPIN=5]="SPIN",O[O.INDOOR_CYCLING=6]="INDOOR_CYCLING",O[O.ROAD=7]="ROAD",O[O.MOUNTAIN=8]="MOUNTAIN",O[O.DOWNHILL=9]="DOWNHILL",O[O.RECUMBENT=10]="RECUMBENT",O[O.CYCLOCROSS=11]="CYCLOCROSS",O[O.HAND_CYCLING=12]="HAND_CYCLING",O[O.TRACK_CYCLING=13]="TRACK_CYCLING",O[O.INDOOR_ROWING=14]="INDOOR_ROWING",O[O.ELLIPTICAL=15]="ELLIPTICAL",O[O.STAIR_CLIMBING=16]="STAIR_CLIMBING",O[O.LAP_SWIMMING=17]="LAP_SWIMMING",O[O.OPEN_WATER=18]="OPEN_WATER",O[O.FLEXIBILITY_TRAINING=19]="FLEXIBILITY_TRAINING",O[O.STRENGTH_TRAINING=20]="STRENGTH_TRAINING",O[O.WARM_UP=21]="WARM_UP",O[O.MATCH=22]="MATCH",O[O.EXERCISE=23]="EXERCISE",O[O.CHALLENGE=24]="CHALLENGE",O[O.INDOOR_SKIING=25]="INDOOR_SKIING",O[O.CARDIO_TRAINING=26]="CARDIO_TRAINING",O[O.INDOOR_WALKING=27]="INDOOR_WALKING",O[O.E_BIKE_FITNESS=28]="E_BIKE_FITNESS",O[O.BMX=29]="BMX",O[O.CASUAL_WALKING=30]="CASUAL_WALKING",O[O.SPEED_WALKING=31]="SPEED_WALKING",O[O.BIKE_TO_RUN_TRANSITION=32]="BIKE_TO_RUN_TRANSITION",O[O.RUN_TO_BIKE_TRANSITION=33]="RUN_TO_BIKE_TRANSITION",O[O.SWIM_TO_BIKE_TRANSITION=34]="SWIM_TO_BIKE_TRANSITION",O[O.ATV=35]="ATV",O[O.MOTOCROSS=36]="MOTOCROSS",O[O.BACKCOUNTRY=37]="BACKCOUNTRY",O[O.RESORT=38]="RESORT",O[O.RC_DRONE=39]="RC_DRONE",O[O.WINGSUIT=40]="WINGSUIT",O[O.WHITEWATER=41]="WHITEWATER",O[O.SKATE_SKIING=42]="SKATE_SKIING",O[O.YOGA=43]="YOGA",O[O.PILATES=44]="PILATES",O[O.INDOOR_RUNNING=45]="INDOOR_RUNNING",O[O.GRAVEL_CYCLING=46]="GRAVEL_CYCLING",O[O.E_BIKE_MOUNTAIN=47]="E_BIKE_MOUNTAIN",O[O.COMMUTING=48]="COMMUTING",O[O.MIXED_SURFACE=49]="MIXED_SURFACE",O[O.NAVIGATE=50]="NAVIGATE",O[O.TRACK_ME=51]="TRACK_ME",O[O.MAP=52]="MAP",O[O.SINGLE_GAS_DIVING=53]="SINGLE_GAS_DIVING",O[O.MULTI_GAS_DIVING=54]="MULTI_GAS_DIVING",O[O.GAUGE_DIVING=55]="GAUGE_DIVING",O[O.APNEA_DIVING=56]="APNEA_DIVING",O[O.APNEA_HUNTING=57]="APNEA_HUNTING",O[O.VIRTUAL_ACTIVITY=58]="VIRTUAL_ACTIVITY",O[O.OBSTACLE=59]="OBSTACLE",O[O.BREATHING=62]="BREATHING",O[O.SAIL_RACE=65]="SAIL_RACE",O[O.ULTRA=67]="ULTRA",O[O.INDOOR_CLIMBING=68]="INDOOR_CLIMBING",O[O.BOULDERING=69]="BOULDERING",O[O.HIIT=70]="HIIT",O[O.AMRAP=73]="AMRAP",O[O.EMOM=74]="EMOM",O[O.TABATA=75]="TABATA",O[O.PICKLEBALL=84]="PICKLEBALL",O[O.PADEL=85]="PADEL",O[O.INDOOR_WHEELCHAIR_WALK=86]="INDOOR_WHEELCHAIR_WALK",O[O.INDOOR_WHEELCHAIR_RUN=87]="INDOOR_WHEELCHAIR_RUN",O[O.INDOOR_HAND_CYCLING=88]="INDOOR_HAND_CYCLING",O[O.SQUASH=94]="SQUASH",O[O.BADMINTON=95]="BADMINTON",O[O.RACQUETBALL=96]="RACQUETBALL",O[O.TABLE_TENNIS=97]="TABLE_TENNIS",O[O.FLY_CANOPY=110]="FLY_CANOPY",O[O.FLY_PARAGLIDE=111]="FLY_PARAGLIDE",O[O.FLY_PARAMOTOR=112]="FLY_PARAMOTOR",O[O.FLY_PRESSURIZED=113]="FLY_PRESSURIZED",O[O.FLY_NAVIGATE=114]="FLY_NAVIGATE",O[O.FLY_TIMER=115]="FLY_TIMER",O[O.FLY_ALTIMETER=116]="FLY_ALTIMETER",O[O.FLY_WX=117]="FLY_WX",O[O.FLY_VFR=118]="FLY_VFR",O[O.FLY_IFR=119]="FLY_IFR",O[O.ALL=254]="ALL",O))(L_||{});function Nt(R,t){if(!t)return;let _=t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let I of Object.keys(R)){if(!Number.isNaN(Number(I))||I.toUpperCase()!==_)continue;let T=R[I];return typeof T=="number"?T:void 0}}function GI(R){let t=R.metadata?.fileName?.trim();if(t)return t;let _=R.metadata?.originType;return _?`${_.toLowerCase()}-course`:"course"}function $t(R){let t=R.activities?.[0],I=[...(R.activities?.flatMap(T=>T.laps??[])??[]).flatMap(T=>T.records??[]),...R.routes?.flatMap(T=>T.records??[])??[],...R.points??[]].filter(T=>T.timestamp!=null&&T.positionLat!=null&&T.positionLong!=null).sort((T,A)=>new Date(T.timestamp).getTime()-new Date(A.timestamp).getTime()).map(T=>({timestamp:T.timestamp,latitude:T.positionLat,longitude:T.positionLong,distance:T.distance,altitude:T.enhancedAltitude??T.altitude,speed:T.enhancedSpeed??T.speed}));if(I.length===0)throw new Error("Cannot build a FIT course without timestamped coordinates");return{name:GI(R),sport:Nt(R_,t?.sport)??2,subSport:Nt(L_,t?.subSport)??0,records:I,timeCreated:I[0].timestamp}}function kt(){return process.env.TRACKSWAP_FIT_DEBUG==="1"||process.env.TRACKSWAP_DEBUG==="1"}function b(...R){kt()}function a(...R){kt()}var E_=class{constructor(){this.stage="parse"}async process(t){let _=Date.now();if(!t.rawData)throw new Error("FIT data cannot be empty");try{let I=await this.parseWithFitSDK(t.rawData,t);return t.rawMessages=I,b("\u{1F389} FIT parsing raw messages:",I),t.performance.parseTime=Date.now()-_,b(`\u{1F527} FIT parsing completed, contains message types: ${Object.keys(I).join(", ")}`),t}catch(I){throw new Error(`FIT parsing failed: ${I.message}`)}}async parseWithFitSDK(t,_){let{Decoder:I,Profile:T,Stream:A}=await import("@garmin/fitsdk"),n=[T.version?.major,T.version?.minor,T.version?.patch].filter(U=>U!==void 0);n.length>0&&_.metadata.set("fit-sdk-profile-version",n.join("."));let L=A.fromBuffer(t);if(!I.isFIT(L))throw new Error("Not a valid FIT file");let E=new I(L),{messages:f,errors:F}=E.read();return F&&F.length>0&&a("FIT parsing warnings:",F),f}};function gI(R){let t={...R};return t.position_lat!=null&&t.positionLat==null&&(t.positionLat=t.position_lat),t.position_long!=null&&t.positionLong==null&&(t.positionLong=t.position_long),t}var O_=class{constructor(t){this.getConverters=t;this.stage="extract"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Raw messages cannot be empty");let I={};for(let[T,A]of Object.entries(t.rawMessages)){if(!Array.isArray(A)||A.length===0){I[T]=A;continue}let n=this.getConverters(T);if(n.length===0)I[T]=T==="recordMesgs"?A.map(L=>gI(L)):A,b(`\u{1F4CB} Message type "${T}" has no converter, using raw data`);else{let L=n[0];try{let E=L.convertMessages(A,t);I[T]=E,b(`\u2705 Message type "${T}" using converter ${L.name}`)}catch(E){t.errors.push(E),I[T]=A,a(`FIT converter "${L.name}" failed for ${T}; raw messages were retained`,E)}}}return t.rawMessages=I,t.performance.extractTime=Date.now()-_,t}},S_=class{constructor(t){this.getStructurePlugins=t;this.stage="structure"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Message data cannot be empty");let I={...t.rawMessages},T=this.getStructurePlugins();for(let A of T)try{let n=A.structureData(t.rawMessages,t);I={...I,...n},b(`\u{1F527} Structure plugin ${A.name} processing completed`)}catch(n){throw t.errors.push(n),new Error(`FIT structure plugin "${A.name}" failed: ${n.message}`)}return t.result=I,t.performance.structureTime=Date.now()-_,t}},o_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,parseTime:t.performance.parseTime,extractTime:t.performance.extractTime,structureTime:t.performance.structureTime}),t.stats&&(t.stats.endTime=Date.now(),t.rawMessages&&(t.stats.processedTokens=this.countTotalMessages(t.rawMessages))),b(`\u2705 FIT processing completed, total time: ${_}ms`),t}countTotalMessages(t){let _=0;return Object.values(t).forEach(I=>{Array.isArray(I)&&(_+=I.length)}),_}};import k from"dayjs";var D_=class extends y{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(_,I){let{sessionMesgs:T,lapMesgs:A,recordMesgs:n,lengthMesgs:L,setMesgs:E}=_;if(!T?.length)return a("No structured session found, data structure is incomplete"),{};let f=T.map((p,W)=>{let l=k(p.startTime).valueOf(),$=l+(p.totalElapsedTime??0)*1e3,Y=k(p.timestamp).valueOf(),D=Math.max(Number.isFinite($)?$:Number.NEGATIVE_INFINITY,Number.isFinite(Y)?Y:Number.NEGATIVE_INFINITY),d=T[W+1],o=d?k(d.startTime).valueOf():Number.NaN,C=Number.isFinite(o)&&o>=l,H=p.firstLapIndex,g=p.numLaps,s=typeof H=="number"&&typeof g=="number"?(A??[]).filter(V=>{let h=V.messageIndex;return typeof h=="number"&&h>=H&&h<H+g}):[],B=(s.length===g&&s.length>0?s:(A??[]).filter(V=>{let h=k(V.startTime).valueOf();return Number.isFinite(h)&&h>=l&&h<=D+2e3})).sort((V,h)=>k(V.startTime).valueOf()-k(h.startTime).valueOf()),M=T.length===1?[...n??[]]:(n??[]).filter(V=>{let h=k(V.timestamp).valueOf();return Number.isFinite(h)?(W===0||h>=l)&&(!C||h<o):W===0}),G=(E??[]).filter(V=>{let h=k(V.startTime??V.timestamp).valueOf();return Number.isFinite(h)?h<l?!1:C?h<o:h<=D+2e3:T.length===1}),v=B.length>0?B:M.length>0?[{...p,messageIndex:typeof p.firstLapIndex=="number"?p.firstLapIndex:W,recordMesgs:M}]:[];if(B.length===0&&v.length===1){let V=Number(I.metadata.get("fit-synthetic-lap-count")??0);I.metadata.set("fit-synthetic-lap-count",V+1)}let N=v.map((V,h)=>{let m=k(V.startTime).valueOf(),Bt=v[h+1]?.startTime,Ot=Bt==null?Number.NaN:k(Bt).valueOf(),_I=m+(V.totalElapsedTime??0)*1e3,Vt=Number.isFinite(Ot)&&Ot>=m,tI=Vt?Ot:Math.max(_I,D),II=B.length===0?M:M.filter(ot=>{let c=k(ot.timestamp).valueOf();return Number.isFinite(c)?(h===0||c>=m)&&(!Vt||c<tI):h===0}),St=V.firstLengthIndex??void 0,pt=V.numLengths??void 0,ht=[];if(St!==void 0&&pt!==void 0){let ot=St+pt;ht=L?.filter(c=>c.messageIndex>=St&&c.messageIndex<ot)||[]}return{...V,recordMesgs:II,lengthMesgs:ht,messageIndex:V.messageIndex!==void 0?V.messageIndex:0}});return{...p,lapMesgs:N,setMesgs:G}}),F=new Set;for(let p of f)for(let W of p.lapMesgs??[])for(let l of W.recordMesgs??[])l?.timestamp!=null&&F.add(k(l.timestamp).valueOf());let U=0;for(let p of n??[]){if(p?.timestamp==null)continue;let W=k(p.timestamp).valueOf();F.has(W)||U++}return U>0&&(I.metadata.set("fit-unassigned-record-count",U),a(`SessionStructurePlugin: ${U} record(s) did not fall into any lap time window`)),{sessionMesgs:f}}},H_=class extends y{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(_,I){let{courseMesgs:T,lapMesgs:A,recordMesgs:n}=_;if(!T?.length)return{};let L=2e3;return{courseMesgs:T.map(f=>{let F=A?.map(U=>{let p=k(U.startTime).valueOf(),W=k(U.timestamp).valueOf(),l=n?.filter($=>{let Y=k($.timestamp).valueOf();return Y>=p-L&&Y<=W+L})||[];return{...U,recordMesgs:l}})||[];return{...f,lapMesgs:F}})}}},C_=class extends y{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(_,I){let{fileIdMesgs:T,fileCreatorMesgs:A,deviceInfoMesgs:n}=_;if(T?.length&&T[0]){let L=T[0];I.fileHeader={type:L.type,manufacturer:L.manufacturer,product:L.product}}return{fileIdMesgs:T,fileCreatorMesgs:A,deviceInfoMesgs:n}}};var f_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.structurePlugins=[];this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultPluginsRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new E_,new O_(t=>this.getConverters(t)),new S_(()=>this.structurePlugins),new o_],b("\u{1F527} FIT core pipeline processors initialized (fixed and not modifiable)")}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let t=[new C_,new D_,new H_,new A_];for(let _ of t)this.addStructurePlugin(_),this.registeredPlugins.add(_.name);this.defaultPluginsRegistered=!0,b("\u2705 Default FIT structure plugins auto-registered (FileHeader, Session, Course, etc.)")}addConverterForMessageType(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((T,A)=>(T.priority||100)-(A.priority||100))}addStructurePlugin(t){this.structurePlugins.push(t),this.structurePlugins.sort((_,I)=>(_.priority||100)-(I.priority||100))}async registerMessageConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Message converter plugin ${t.name} already exists`);t.supportedMessageTypes.forEach(I=>{this.addConverterForMessageType(I,t)}),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F4E6} Registered FIT message converter: ${t.name}${_}, supported message types: ${t.supportedMessageTypes.join(", ")}`),t.supportedMessageTypes.forEach(I=>{let A=(this.converterPlugins.get(I)||[]).map(n=>`${n.name}(${n.priority||100})`);b(` \u{1F4CB} Message type "${I}" converter priority: ${A.join(" > ")}`)})}async registerStructurePlugin(t){if(this.registeredPlugins.has(t.name))throw new Error(`Structure plugin ${t.name} already exists`);this.addStructurePlugin(t),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F3D7}\uFE0F Registered FIT structure plugin: ${t.name}${_}`)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(T=>T.name===t.name);_!==-1?(this.middlewarePlugins[_]=t,b(`\u{1F504} Updated FIT middleware: ${t.name}`)):(this.middlewarePlugins.push(t),this.middlewarePlugins.sort((T,A)=>(T.priority||100)-(A.priority||100)),b(`\u{1F50C} Registered FIT middleware: ${t.name}`));let I=[];t.onParse&&I.push("onParse"),t.onExtractMessages&&I.push("onExtractMessages"),t.onStructure&&I.push("onStructure"),t.onComplete&&I.push("onComplete"),t.onError&&I.push("onError"),I.length>0&&b(` \u{1F3A3} Supported hooks: ${I.join(", ")}`)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getConverters(t){return this.converterPlugins.get(t)||[]}unregisterPlugin(t){if(!this.registeredPlugins.has(t))return!1;for(let[T,A]of this.converterPlugins){let n=A.findIndex(L=>L.name===t);n!==-1&&(A.splice(n,1),A.length===0&&this.converterPlugins.delete(T))}let _=this.structurePlugins.findIndex(T=>T.name===t);_!==-1&&this.structurePlugins.splice(_,1);let I=this.middlewarePlugins.findIndex(T=>T.name===t);return I!==-1&&this.middlewarePlugins.splice(I,1),this.registeredPlugins.delete(t),b(`\u{1F5D1}\uFE0F Removed FIT plugin: ${t}`),!0}async initialize(){if(this.initialized)return;await this.registerDefaultPlugins();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let T=_;for(let A of this.middlewarePlugins){let n=A[t];if(n)try{T=await n.call(A,T,I)||T}catch(L){I.errors.push(L),await A.onError?.(L,I)}}return T}async parseByBuffer(t,_={}){await this.initialize();let I=this.createContext();I.rawData=t,I.userData=_.userData,I.metadata.set("decoder",this);try{for(let T of this.processors)try{switch(T.stage==="parse"&&I.rawData&&(I.rawData=await this.executeMiddlewareHook("onParse",I.rawData,I)),I=await T.process(I),T.stage){case"parse":break;case"extract":I.rawMessages&&(I.rawMessages=await this.executeMiddlewareHook("onExtractMessages",I.rawMessages,I));break;case"structure":I.result&&(I.result=await this.executeMiddlewareHook("onStructure",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(A){I.errors.push(A);for(let n of this.middlewarePlugins)await n.onError?.(A,I);throw new Error(`FIT pipeline stage "${T.stage}" failed: ${A.message}`)}return b("\u{1F389} FIT parsing completed",I.result),I.result}catch(T){throw T}}};var lI={file:{course:6,device:1,settings:2,sport:3,activity:4,workout:5,schedules:7,weight:9,totals:10,goals:11,blood_pressure:14,monitoring_a:15,activity_summary:20,monitoring_daily:28,monitoring_b:32,segment_list:35,exd_configuration:40,invalid:0},sport:{generic:0,running:1,cycling:2,transition:3,fitness_equipment:4,swimming:5,basketball:6,soccer:7,tennis:8,american_football:9,training:10,walking:11,cross_country_skiing:12,alpine_skiing:13,snowboarding:14,rowing:15,mountaineering:16,hiking:17,multisport:18,paddling:19,invalid:254},event:{timer:0,workout:3,workout_step:4,power_down:5,power_up:6,off_course:7,session:8,lap:9,course_point:10,battery:11,virtual_partner_pace:12,hr_high_alert:13,hr_low_alert:14,speed_high_alert:15,speed_low_alert:16,cad_high_alert:17,cad_low_alert:18,power_high_alert:19,power_low_alert:20,recovery_hr:21,battery_low:22,time_duration_alert:23,distance_duration_alert:24,calorie_duration_alert:25,activity:26,fitness_equipment:27,length:28,user_marker:32,sport_point:33,calibration:36,front_gear_change:42,rear_gear_change:43,rider_position_change:44,elev_high_alert:45,elev_low_alert:46,comm_timeout:47,invalid:255},event_type:{start:0,stop:1,consecutive_depreciated:2,marker:3,stop_all:4,begin_depreciated:5,end_depreciated:6,end_all_depreciated:7,stop_disable:8,stop_disable_all:9,invalid:255},course_point:{generic:0,summit:1,valley:2,water:3,food:4,danger:5,left:6,right:7,straight:8,first_aid:9,fourth_category:10,third_category:11,second_category:12,first_category:13,hors_category:14,sprint:15,left_fork:16,right_fork:17,middle_fork:18,slight_left:19,sharp_left:20,slight_right:21,sharp_right:22,u_turn:23,segment_start:24,segment_end:25,invalid:255}},r=R=>{let t=lI[R];return{size:1,baseType:0,mapValue:_=>typeof _=="string"?t[_]??255:_,setValue:function(_,I){this.setUint8(_,I)}}},Ut={enum_file:r("file"),enum_activity:r("sport"),enum_sport:r("sport"),enum_sub_sport:r("sport"),enum_event:r("event"),enum_event_type:r("event_type"),enum_course_point:r("course_point"),uint8:{size:1,baseType:2,setValue:DataView.prototype.setUint8},sint8:{size:1,baseType:1,setValue:DataView.prototype.setInt8},uint16:{size:2,baseType:132,setValue:DataView.prototype.setUint16},sint16:{size:2,baseType:131,setValue:DataView.prototype.setInt16},uint32:{size:4,baseType:134,setValue:DataView.prototype.setUint32},sint32:{size:4,baseType:133,setValue:DataView.prototype.setInt32},string:{size:0,baseType:7,mapValue:R=>Array.from(Jt(R)),setValue:WI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*100)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round(R*1e3)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round((R+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>{let t;return R instanceof Date?(t=Math.floor(R.getTime()/1e3),t-631065600):typeof R=="string"?(t=Math.floor(new Date(R).getTime()/1e3),t-631065600):R<631065600?Math.floor(R):(R>9999999999?t=Math.floor(R/1e3):t=Math.floor(R),t-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:R=>Math.round(R/180*2147483648)}};function Qt(R){return Array.from(Jt(R)).length+1}function*Jt(R){for(let t of sI(R))t<128?yield t:t<2048?(yield 192|t>>6,yield 128|t&63):t<65536?(yield 224|t>>12,yield 128|t>>6&63,yield 128|t&63):(yield 240|t>>18,yield 128|t>>12&63,yield 128|t>>6&63,yield 128|t&63);yield 0}function*sI(R){for(let t=0;t<R.length;){let _=R.codePointAt(t);if(_===void 0)break;yield _,t+=_>65535?2:1}}function WI(R,t){for(let _=0;_<t.length;_++)this.setUint8(R+_,t[_])}var BI={file_id:{mesgNum:0,fieldDefns:[{name:"type",number:0,type:"enum_file"},{name:"time_created",number:4,type:"date_time"}]},session:{mesgNum:18,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_calories",number:11,type:"uint16"},{name:"avg_heart_rate",number:16,type:"uint8"},{name:"max_heart_rate",number:17,type:"uint8"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"},{name:"sport",number:5,type:"enum_sport"},{name:"sub_sport",number:6,type:"enum_sub_sport"},{name:"first_lap_index",number:25,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"end_position_lat",number:5,type:"semicircles"},{name:"end_position_long",number:6,type:"semicircles"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_calories",number:11,type:"uint16"},{name:"avg_heart_rate",number:15,type:"uint8"},{name:"max_heart_rate",number:16,type:"uint8"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"}]},record:{mesgNum:20,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"position_lat",number:0,type:"semicircles"},{name:"position_long",number:1,type:"semicircles"},{name:"altitude",number:2,type:"altitude"},{name:"distance",number:5,type:"distance"},{name:"heart_rate",number:3,type:"uint8"},{name:"cadence",number:4,type:"uint8"},{name:"speed",number:6,type:"speed"},{name:"power",number:7,type:"uint16"}]},event:{mesgNum:21,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"event",number:0,type:"enum_event"},{name:"event_type",number:1,type:"enum_event_type"},{name:"event_group",number:4,type:"uint8"}]},course:{mesgNum:31,fieldDefns:[{name:"name",number:5,type:"string"},{name:"sport",number:4,type:"enum_sport"},{name:"sub_sport",number:7,type:"enum_sub_sport"}]},activity:{mesgNum:34,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"total_timer_time",number:0,type:"seconds"},{name:"num_sessions",number:1,type:"uint16"},{name:"type",number:2,type:"enum_activity"},{name:"event",number:3,type:"enum_event"},{name:"event_type",number:4,type:"enum_event_type"},{name:"local_timestamp",number:5,type:"date_time"},{name:"event_group",number:6,type:"uint8"}]},course_point:{mesgNum:32,fieldDefns:[{name:"timestamp",number:1,type:"date_time"},{name:"position_lat",number:2,type:"semicircles"},{name:"position_long",number:3,type:"semicircles"},{name:"distance",number:4,type:"distance"},{name:"type",number:5,type:"enum_course_point"}]}},VI=(R,t)=>R.map(_=>({..._,value:t[_.name]})).filter(({value:_})=>_!==void 0),d_=class R{static check(t,_,I,T){if(_===void 0)throw new Error(`Message '${t}' not known`);if(I===void 0)throw new Error(`Message '${t}' has no field definitions`);let A=I.map(L=>L.name),n=Object.keys(T).filter(L=>!A.includes(L));if(n.length)throw new Error(`Message '${t}' has no field definitions named '${n}'`)}constructor(t,_,I){let T=BI[_];if(!T)throw new Error(`Unknown message type: ${_}`);let{mesgNum:A,fieldDefns:n}=T;R.check(_,A,n,I),this.localNum=t,this.mesgNum=A,this.fields=VI(n,I)}get mesgDefn(){let t=this.fields.map(({number:_,type:I,value:T})=>{let A=Ut[I];if(!A)throw new Error(`Unknown type: ${I}`);let{size:n,baseType:L}=A;return I==="string"?{number:_,size:Qt(T),baseType:L}:{number:_,size:n,baseType:L}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:t}}isSameDefn(t){let _=(L,E)=>L.number===E.number&&L.size===E.size&&L.baseType===E.baseType,I=(L,E)=>L.length===E.length&&L.every((f,F)=>_(f,E[F])),{localNum:T,mesgNum:A,fieldDefns:n}=this.mesgDefn;return A===t.mesgNum&&T===t.localNum&&I(n,t.fieldDefns)}get defnRecord(){let{localNum:t,mesgNum:_,fieldDefns:I}=this.mesgDefn,T=6+3*I.length,A=new DataView(new ArrayBuffer(T));A.setUint8(0,64|t),A.setUint8(2,1),A.setUint16(3,_),A.setUint8(5,I.length);let n=6;for(let L of I)A.setUint8(n++,L.number),A.setUint8(n++,L.size),A.setUint8(n++,L.baseType);return A.buffer}get dataRecord(){let{fieldDefns:t}=this.mesgDefn,_=1+t.reduce((A,{size:n})=>A+n,0),I=new DataView(new ArrayBuffer(_));I.setUint8(0,this.localNum);let T=1;for(let{number:A,type:n,value:L}of this.fields){let E=Ut[n];if(!E)throw new Error(`Unknown type: ${n}`);let{size:f,setValue:F}=E,U;"mapValue"in E?U=E.mapValue(L):U=L,F&&F.call(I,T,U),T+=f}return I.buffer}};var pI=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],zt=(R,t)=>(R>>>4^pI[R&15^t])&65535,hI=(R,t,_)=>zt(zt(R,t),_),KI=(R,t)=>hI(R,t&15,t>>>4);function Ft(R,t=0){let _=t,I=R instanceof ArrayBuffer?new Uint8Array(R):R;for(let T=0;T<I.length;T++)_=KI(_,I[T]);return _}import wI from"dayjs";var jt=14,vI=16,XI=2078,PI=776358228,U_=class{constructor(t={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:t.compact??!0,defaultActivity:t.defaultActivity??"cycling",defaultSubActivity:t.defaultSubActivity??"generic"}}async encode(t){return this.reset(),this.buildFITContent(t,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(t){return this.reset(),this.buildFITContent(t,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(t,_="activity"){return this.reset(),this.buildFITContent(t,_),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(t,_){this.buildFileId(t,_),_==="course"?this.buildCourseContent(t):this.buildActivityContent(t)}buildActivityContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Activity file must contain at least one Session");let I=[],T=[],A=0;for(let[n,L]of _.entries()){let E=(L.lapMesgs??[]).map((F,U)=>({...F,messageIndex:A+U})),f={...L,messageIndex:n,firstLapIndex:A,numLaps:E.length,lapMesgs:E};E.length>0&&this.buildEventsFromLaps(E,I);for(let F of E)F.recordMesgs&&this.buildRecords(F.recordMesgs);E.length>0&&this.buildLaps(E),this.buildSession(f),this.buildActivityFromSession(f,T),A+=E.length}I.forEach(n=>this.buildEvent(n)),T.forEach(n=>this.buildActivity(n))}buildCourseContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Course file must contain track data");let I=_[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),I.lapMesgs){let T=[];for(let L of I.lapMesgs)L.recordMesgs&&T.push(...L.recordMesgs);T.sort((L,E)=>L.timestamp&&E.timestamp?new Date(L.timestamp).getTime()-new Date(E.timestamp).getTime():(L.distance||0)-(E.distance||0));let A=T[0],n=T[T.length-1];if(I.startTime&&this.buildEvent({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:0}),T.forEach(L=>this.buildRecord(L)),n.timestamp&&this.buildEvent({timestamp:n.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),I.lapMesgs)for(let L=0;L<I.lapMesgs.length;L++)this.buildLap(I.lapMesgs[L])}}buildFileId(t,_){let I=t.fileIdMesgs?.[0]||{};this.writeMesg("file_id",{type:_,time_created:I.timeCreated?this.parseTimestamp(I.timeCreated):Date.now(),manufacturer:I.manufacturer,product:I.product,serial_number:I.serialNumber})}buildSession(t){this.writeMesg("session",{message_index:t.messageIndex,timestamp:t.timestamp?t.timestamp:void 0,start_time:t.startTime?t.startTime:void 0,total_elapsed_time:t.totalElapsedTime,total_timer_time:t.totalTimerTime,total_calories:t.totalCalories,avg_heart_rate:t.avgHeartRate,max_heart_rate:t.maxHeartRate,start_position_lat:t.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,total_distance:t.totalDistance,total_ascent:t.totalAscent,total_descent:t.totalDescent,sport:t.sport||this.options.defaultActivity,sub_sport:t.subSport||this.options.defaultSubActivity,first_lap_index:t.firstLapIndex??0,num_laps:t.numLaps??t.lapMesgs?.length??0})}buildLaps(t){t.forEach(_=>this.buildLap(_))}buildLap(t){this.writeMesg("lap",{message_index:t.messageIndex,timestamp:t?.timestamp?t.timestamp:void 0,start_time:t?.startTime?t.startTime:void 0,start_position_lat:t?.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t?.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,end_position_lat:t?.endPositionLat!=null&&Number.isFinite(t.endPositionLat)?t.endPositionLat:void 0,end_position_long:t?.endPositionLong!=null&&Number.isFinite(t.endPositionLong)?t.endPositionLong:void 0,total_elapsed_time:t?.totalElapsedTime,total_timer_time:t?.totalTimerTime,total_calories:t?.totalCalories,avg_heart_rate:t?.avgHeartRate,max_heart_rate:t?.maxHeartRate,total_distance:t?.totalDistance,total_ascent:t?.totalAscent,total_descent:t?.totalDescent})}buildRecords(t){t.forEach(_=>this.buildRecord(_))}buildRecord(t){this.writeMesg("record",{timestamp:t.timestamp,position_lat:t?.positionLat!=null&&Number.isFinite(t.positionLat)?t.positionLat:void 0,position_long:t?.positionLong!=null&&Number.isFinite(t.positionLong)?t.positionLong:void 0,altitude:t?.altitude,enhancedAltitude:t?.enhancedAltitude,distance:t?.distance,heart_rate:t?.heartRate,cadence:t?.cadence,speed:t?.speed,enhancedSpeed:t?.enhancedSpeed,power:t?.power})}buildEvent(t){this.writeMesg("event",{timestamp:t.timestamp?t.timestamp:void 0,event:t.event,event_type:t.eventType,event_group:t.eventGroup})}buildActivity(t){this.writeMesg("activity",{timestamp:t.timestamp?t.timestamp:void 0,total_timer_time:t.totalTimerTime,num_sessions:t.numSessions,type:t.type,event:t.event,event_type:t.eventType,local_timestamp:t.localTimestamp?this.parseTimestamp(t.localTimestamp):void 0,event_group:t.eventGroup})}buildCourse(t){this.writeMesg("course",{name:t.name,sport:t.sport})}buildEventsFromLaps(t,_){t.forEach((I,T)=>{I.startTime&&_.push({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:T}),I.timestamp&&_.push({timestamp:I.timestamp,event:"timer",eventType:T===t.length-1?"stop_all":"stop",eventGroup:T})})}buildActivityFromSession(t,_){_.push({timestamp:t.timestamp,totalTimerTime:t.totalTimerTime,numSessions:1,type:t.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(t){return typeof t=="number"?t:wI(t).valueOf()}validateRequiredFields(t){if(!t.sessionMesgs||t.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(t,_){let I=Object.fromEntries(Object.entries(_).filter(([L,E])=>E!==void 0));if(Object.keys(I).length===0)return;let T=this.localNum[t];T===void 0&&(T=this.localNum[t]=Object.keys(this.localNum).length);let A=new d_(T,t,I),n=this.mesgDefn[T];(!n||!A.isSameDefn(n))&&(this.messages.push(A.defnRecord),this.mesgDefn[T]=A.mesgDefn),this.messages.push(A.dataRecord)}get blob(){let t=[this.header,...this.messages,this.trailer];return new Blob(t,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((t,_)=>t+_.byteLength,0)}get dataCrc(){return this.messages.reduce((t,_)=>Ft(_,t),0)}get header(){let t=new DataView(new ArrayBuffer(jt));return t.setUint8(0,jt),t.setUint8(1,vI),t.setUint16(2,XI,!0),t.setUint32(4,this.dataLen,!0),t.setUint32(8,PI),t.setUint16(12,Ft(t.buffer.slice(0,12)),!0),t.buffer}get trailer(){let t=new DataView(new ArrayBuffer(2));return t.setUint16(0,this.dataCrc,!0),t.buffer}async encoder(t){return this.encode(t)}};import{Encoder as YI}from"@garmin/fitsdk";var bI="development",NI=1,$I=1;function kI(R,t){if(!Number.isFinite(R))throw new Error(`${t} must be a finite number.`)}function F_(R,t){return kI(R,t),Math.abs(R)<=180?Math.round(R*2147483648/180):Math.round(R)}function QI(R){if(!R.name||R.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(R.records)||R.records.length===0)throw new Error("Course must contain at least one record point.");let t=R.records.map((I,T)=>{if(I==null)throw new Error(`Course record #${T+1} is missing.`);if(I.timestamp==null)throw new Error(`Course record #${T+1} is missing timestamp.`);return{...I,positionLat:F_(I.latitude,`records[${T}].latitude`),positionLong:F_(I.longitude,`records[${T}].longitude`)}}),_=(R.coursePoints??[]).map((I,T)=>{if(I==null)throw new Error(`Course point #${T+1} is missing.`);if(I.timestamp==null)throw new Error(`Course point #${T+1} is missing timestamp.`);return{...I,type:I.type??0,positionLat:F_(I.latitude,`coursePoints[${T}].latitude`),positionLong:F_(I.longitude,`coursePoints[${T}].longitude`)}});return{...R,sport:R.sport??2,subSport:R.subSport??0,records:t,coursePoints:_,manufacturer:R.manufacturer??bI,product:R.product??NI,serialNumber:R.serialNumber??$I,timeCreated:R.timeCreated??t[0].timestamp}}function JI(R){let t=QI(R),_=t.records[0],I=t.records[t.records.length-1],T=_.timestamp,A=I.timestamp,n=[{mesgNum:0,data:{type:6,manufacturer:t.manufacturer,product:t.product,serialNumber:t.serialNumber,timeCreated:t.timeCreated}},{mesgNum:31,data:{name:t.name,sport:t.sport,subSport:t.subSport}},{mesgNum:19,data:{startTime:T,timestamp:A,startPositionLat:_.positionLat,startPositionLong:_.positionLong,endPositionLat:I.positionLat,endPositionLong:I.positionLong,totalDistance:I.distance}},{mesgNum:21,data:{timestamp:T,event:0,eventType:0}}];return t.records.forEach(L=>{n.push({mesgNum:20,data:{timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,altitude:L.altitude,speed:L.speed}})}),t.coursePoints.forEach((L,E)=>{n.push({mesgNum:32,data:{messageIndex:E,timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,type:L.type,name:L.name,favorite:L.favorite}})}),n.push({mesgNum:21,data:{timestamp:A,event:0,eventType:4}}),n}function yt(R){let t=new YI;return JI(R).forEach(I=>{t.onMesg(I.mesgNum,I.data)}),t.close()}var q=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}parseFloat(t){if(!(typeof t>"u"))return typeof t=="number"?t:typeof t=="string"&&parseFloat(t)||0}parseInt(t){return typeof t=="number"?Math.floor(t):typeof t=="string"&&parseInt(t,10)||0}parseString(t){return String(t||"")}parseBoolean(t){return typeof t=="boolean"?t:typeof t=="string"?t.toLowerCase()==="true":!1}parseDate(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}hasRequiredAttributes(t,_){return _.every(I=>t.attributes?.[I])}extractAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([T,A])=>{let n=I[T];n&&(_[n]=String(A??""))})}processChildren(t,_,I){t.children?.forEach(T=>{let A=I[T.tag];A&&A(T,_)})}getChildValue(t,_){let I=t.children?.find(T=>T.tag===_);return I?.value?String(I.value):void 0}getChildByTag(t,_){return t.children?.find(I=>I.tag===_)}getChildrenByTag(t,_){return t.children?.filter(I=>I.tag===_)||[]}convertExtensions(t){let _={};return t.children?.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}convertExtensionContent(t){if(t.children?.length){let _={};return t.children.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}else return t.value}};var J=class extends q{parseCoordinate(t){let _=this.parseFloat(t);return _===0?void 0:_}parseGPXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}extractNumericAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([T,A])=>{let n=I[T];n&&n in _&&typeof A<"u"&&(_[n]=this.parseFloat(A))})}};var G_=class extends J{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(_,I){if(!this.hasRequiredAttributes(_,["lat","lon"])){I.warnings.push(`${this.name}: point without latitude or longitude was ignored`);return}let T={lat:this.parseFloat(_.attributes?.lat),lon:this.parseFloat(_.attributes?.lon)};return this.processChildren(_,T,{ele:(A,n)=>n.ele=this.parseFloat(A.value),time:(A,n)=>n.time=new Date(this.parseString(A.value)),speed:(A,n)=>n.speed=this.parseFloat(A.value),power:(A,n)=>n.power=this.parseFloat(A.value),cadence:(A,n)=>n.cadence=this.parseFloat(A.value),heartRate:(A,n)=>n.heartRate=this.parseFloat(A.value),course:(A,n)=>n.course=this.parseFloat(A.value),name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),sym:(A,n)=>n.sym=this.parseString(A.value),type:(A,n)=>n.type=this.parseString(A.value),fix:(A,n)=>n.fix=this.parseString(A.value),sat:(A,n)=>n.sat=this.parseFloat(A.value),hdop:(A,n)=>n.hdop=this.parseFloat(A.value),vdop:(A,n)=>n.vdop=this.parseFloat(A.value),pdop:(A,n)=>n.pdop=this.parseFloat(A.value),ageofdgpsdata:(A,n)=>n.ageofdgpsdata=this.parseFloat(A.value),geoidheight:(A,n)=>n.geoidheight=this.parseFloat(A.value),magvar:(A,n)=>n.magvar=this.parseFloat(A.value),dgpsid:(A,n)=>n.dgpsid=this.parseFloat(A.value),extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");if(E){let f=E.convert(A,I);f&&(this.mapExtensionsToPoint(f,n),n.extensions=f)}},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}mapExtensionsToPoint(_,I){Object.entries(_).forEach(([T,A])=>{if(A!==void 0&&(typeof A=="string"||typeof A=="number")){let n=L=>(Array.isArray(L)?L:[L]).some(f=>{let F=T.toLowerCase(),U=f.toLowerCase();return F===U||F.endsWith(`:${U}`)});n("speed")?I.speed=this.parseFloat(A):n("hr")?I.heartRate=this.parseFloat(A):n(["cad","cadence"])?I.cadence=this.parseFloat(A):n(["PowerInWatts","power"])&&(I.power=this.parseFloat(A))}})}},g_=class extends J{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(_,I){let T={rtept:[]};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),number:(A,n)=>n.number=this.parseFloat(A.value),type:(A,n)=>n.type=this.parseString(A.value),rtept:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(A,I);E&&n.rtept&&n.rtept.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},l_=class extends J{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(_,I){let T={trkseg:[]};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),cmt:(A,n)=>n.cmt=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),src:(A,n)=>n.src=this.parseString(A.value),number:(A,n)=>n.number=this.parseFloat(A.value),type:(A,n)=>n.type=this.parseString(A.value),trkseg:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("trkseg")?.convert(A,I);E&&n.trkseg&&n.trkseg.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},s_=class extends J{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(_,I){let T={trkpt:[]};return this.processChildren(_,T,{trkpt:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(A,I);E&&n.trkpt&&n.trkpt.push(E)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))}}),T}},W_=class extends J{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(_,I){let T={};return _.attributes?.href&&(T.href=_.attributes.href),this.processChildren(_,T,{text:(A,n)=>n.text=this.parseString(A.value),type:(A,n)=>n.type=this.parseString(A.value)}),T}},M_=class extends J{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(_,I){let T={};return this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),desc:(A,n)=>n.desc=this.parseString(A.value),keywords:(A,n)=>n.keywords=this.parseString(A.value),time:(A,n)=>n.time=new Date(this.parseString(A.value)),author:(A,n)=>{let L=I.metadata.get("decoder");n.author=L?.getConverter("author")?.convert(A,I)},copyright:(A,n)=>{let L=I.metadata.get("decoder");n.copyright=L?.getConverter("copyright")?.convert(A,I)},bounds:(A,n)=>{let L=I.metadata.get("decoder");n.bounds=L?.getConverter("bounds")?.convert(A,I)},extensions:(A,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(A,I))},link:(A,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(A,I);E&&n.link&&n.link.push(E)}}),T}},B_=class extends J{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(_,I){let T={};return _.value&&!_.children?.length?(T.name=this.parseString(_.value),T):(this.processChildren(_,T,{name:(A,n)=>n.name=this.parseString(A.value),email:(A,n)=>{let L=I.metadata.get("decoder");n.email=L?.getConverter("email")?.convert(A,I)},link:(A,n)=>{let L=I.metadata.get("decoder");n.link=L?.getConverter("link")?.convert(A,I)}}),T)}},V_=class extends J{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(_,I){return{id:_.attributes?.id,domain:_.attributes?.domain}}},p_=class extends J{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(_,I){let T={};return _.attributes?.author&&(T.author=_.attributes.author),this.processChildren(_,T,{year:(A,n)=>n.year=this.parseString(A.value),license:(A,n)=>n.license=this.parseString(A.value)}),T}},h_=class extends J{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(_,I){let T={};return this.extractAttributes(_,T,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),T}},K_=class extends J{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(_,I){let T={};return _.children?.forEach(A=>{this.flattenExtensionElement(A,T)}),T}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(T=>{this.flattenExtensionElement(T,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),T=parseFloat(I);return!isNaN(T)&&isFinite(T)?T:I}};import{Parser as zI}from"htmlparser2";var w_=class{constructor(){this.stage="tokenize"}async process(t){let _=Date.now();if(!t.xmlContent)throw new Error("XML content cannot be empty");let I=[],T=new zI({onopentag(A,n){I.push({type:"open",tag:A,attributes:n})},ontext(A){let n=A.replace(/\n/g,"").trim();n&&I.push({type:"text",tag:"text",value:n})},onclosetag(A){I.push({type:"close",tag:A})}},{xmlMode:!0});return T.write(t.xmlContent),T.end(),t.tokens=I,t.performance.tokenizeTime=Date.now()-_,t}},v_=class{constructor(){this.stage="ast_generate"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],T,A=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};T?A&&A.children?.push(L):T=L,I.push(L),A=L}else n.type==="text"&&A?A.value=n.value:n.type==="close"&&(I.pop(),A=I[I.length-1]||null);return t.ast=T,t.performance.astTime=Date.now()-_,t}},X_=class{constructor(t){this.getConverter=t;this.stage="convert"}async process(t){let _=Date.now();if(!t.ast)throw new Error("AST cannot be empty");if(t.ast.tag!=="gpx")throw new Error(`Not a valid GPX document: expected <gpx>, received <${t.ast.tag}>`);let I={};return t.ast.attributes&&Object.entries(t.ast.attributes).forEach(([T,A])=>{T.startsWith("xmlns:")?I[T]=A.replace(/'/g,"'"):T==="xsi:schemaLocation"?I[T]=A.replace(/'/g,"'"):I[T]=A}),t.ast.children?.forEach(T=>{let A=this.getConverter(T.tag);if(!A){t.warnings.push(`Unsupported GPX element "${T.tag}" was ignored`);return}try{let n=A.convert(T,t);n&&this.assignResult(I,T.tag,n)}catch(n){throw t.errors.push(n),new Error(`GPX converter "${A.name}" failed for ${T.tag}: ${n.message}`)}}),t.result=I,t.performance.convertTime=Date.now()-_,t}assignResult(t,_,I){switch(_){case"metadata":t.metadata=I;break;case"wpt":t.wpt||(t.wpt=[]),t.wpt.push(I);break;case"rte":t.rte||(t.rte=[]),t.rte.push(I);break;case"trk":t.trk||(t.trk=[]),t.trk.push(I);break;case"extensions":t.extensions=I;break}}},P_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,tokenizeTime:t.performance.tokenizeTime,astTime:t.performance.astTime,convertTime:t.performance.convertTime}),t}};var Y_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new w_,new v_,new X_(t=>this.getConverter(t)),new P_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new G_,new g_,new l_,new s_,new W_,new M_,new B_,new V_,new p_,new h_,new K_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((T,A)=>(T.priority||100)-(A.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,T]of this.converterPlugins){let A=T.findIndex(n=>n.name===t);A!==-1&&(_=T[A],T.splice(A,1),T.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(t=>t.name)}listProcessors(){return this.processors.map(t=>t.constructor.name)}getConverterDetails(t){let _={};if(t){let I=this.converterPlugins.get(t);I&&(_[t]=I.map(T=>({name:T.name,priority:T.priority||100})))}else for(let[I,T]of this.converterPlugins)_[I]=T.map(A=>({name:A.name,priority:A.priority||100}));return _}getMiddlewareDetails(){return this.middlewarePlugins.map(t=>{let _=[];return t.onTokenize&&_.push("onTokenize"),t.onAstGenerate&&_.push("onAstGenerate"),t.onConvert&&_.push("onConvert"),t.onComplete&&_.push("onComplete"),t.onError&&_.push("onError"),{name:t.name,hooks:_}})}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let T=_;for(let A of this.middlewarePlugins){let n=A[t];if(n)try{T=await n.call(A,T,I)||T}catch(L){I.errors.push(L),await A.onError?.(L,I)}}return T}async parserByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast_generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(T){_.errors.push(T);for(let A of this.middlewarePlugins)await A.onError?.(T,_);throw new Error(`GPX pipeline stage "${I.stage}" failed: ${T.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:T,value:A}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(A!==void 0)return A;return _}};import qt from"dayjs";import jI from"dayjs/plugin/utc.js";var Gt={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var gt={temperature:"Temperature",Depth:"Depth"};qt.extend(jI);var b_=class{constructor(t={}){this.formatElevation=t=>{let _=parseFloat(t);return isNaN(_)?t:this.roundTo(_,2).toString()};this.compact=t.compact??!0}async encode(t){let _=this.buildGPXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildGPXXML(t)}buildGPXXML(t){let _=this.buildXMLHeader(t),I=this.buildGPXContent(t),A=`${_}${I}
|
|
2
2
|
</gpx>`;return this.compact?this.compressXML(A):A}compressXML(t){return t.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(t){let _=this.escapeXMLAttribute(t.creator||"TrackSwap"),I=this.escapeXMLAttribute(t.version||"1.1");return['<?xml version="1.0" encoding="UTF-8"?>',`<gpx creator="${_}" version="${I}"`,' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',' xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'," http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd"," http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd"," http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd",' http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"',' xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"',' xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"',' xmlns:gpxpx="http://www.garmin.com/xmlschemas/PowerExtension/v1"',' xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2"',' xmlns="http://www.topografix.com/GPX/1/1">'].join(`
|
|
3
3
|
`)}buildGPXContent(t){let{metadata:_,wpt:I=[],rte:T=[],trk:A=[],extensions:n}=t,L=[];return _&&L.push(this.buildMetadata(_)),I.forEach(E=>{L.push(this.buildWaypoint(E,"wpt"))}),T.forEach(E=>{L.push(this.buildRoute(E))}),A.forEach(E=>{L.push(this.buildTrack(E))}),n&&L.push(this.buildExtensions(n)),L.join(`
|
|
4
4
|
`)}buildMetadata(t){let _=["<metadata>"];return this.addOptionalElement(_,"name",t.name),this.addOptionalElement(_,"desc",t.desc),t.author&&_.push(this.buildAuthor(t.author)),t.copyright&&_.push(this.buildCopyright(t.copyright)),t.link&&this.addLinks(_,t.link),t.time&&_.push(this.buildTimeElement(t.time)),this.addOptionalElement(_,"keywords",t.keywords),t.bounds&&_.push(this.buildBounds(t.bounds)),t.extensions&&_.push(this.buildExtensions(t.extensions)),_.push("</metadata>"),_.join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trackswap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "A typed, adapter-based toolkit for decoding, normalizing and transcoding FIT, GPX and TCX data.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"test:fit-coords": "npm run build:dev && node scripts/verify-fit-coordinates.mjs",
|
|
43
43
|
"test:tcx-course": "npm run build:dev && node scripts/tcx-course-smoke.mjs",
|
|
44
44
|
"test:routes-fit": "npm run build:dev && node scripts/routes-only-fit-smoke.mjs",
|
|
45
|
-
"test": "npm run test:architecture && npm run test:health && npm run test:garmin-parity && npm run test:fit-structure && npm run test:tcx-activity",
|
|
45
|
+
"test": "npm run test:architecture && npm run test:health && npm run test:garmin-parity && npm run test:fit-structure && npm run test:tcx-activity && npm run test:fit-encoding",
|
|
46
|
+
"test:fit-encoding": "esbuild test/fit-encoding.test.ts --bundle --platform=node --target=node18 --format=esm --outfile=/tmp/trackswap-fit-encoding.test.mjs && node /tmp/trackswap-fit-encoding.test.mjs",
|
|
46
47
|
"test:tcx-activity": "esbuild test/tcx-activity.test.ts --bundle --platform=node --target=node18 --format=esm --outfile=/tmp/trackswap-tcx-activity.test.mjs && node /tmp/trackswap-tcx-activity.test.mjs",
|
|
47
48
|
"test:architecture": "esbuild test/architecture.test.ts --bundle --platform=node --target=node18 --format=esm --outfile=/tmp/trackswap-architecture.test.mjs && node /tmp/trackswap-architecture.test.mjs",
|
|
48
49
|
"test:health": "esbuild test/health-fit.test.ts --bundle --platform=node --target=node18 --format=esm --outfile=/tmp/trackswap-health-fit.test.mjs && node /tmp/trackswap-health-fit.test.mjs",
|