trackswap 0.0.12 → 0.0.14
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/README.md +15 -15
- package/dist/TrackSwap.d.ts +9 -12
- package/dist/index.cjs +6 -6
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -6
- package/dist/sport/base.d.ts +14 -14
- package/dist/sport/converters.d.ts +7 -7
- package/dist/sport/encoders.d.ts +4 -4
- package/dist/sport/processor.d.ts +3 -3
- package/dist/types.d.ts +9 -9
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
2
|
+
export { FITDecoder, FITEncoder } from "./FIT/index.js";
|
|
3
|
+
export { GPXDecoder, GPXEncoder, registerDefaultMiddlewares, PipelineStage, } from "./GPX/index.js";
|
|
4
|
+
export { TCXDecoder, TCXEncoder } from "./TCX/index.js";
|
|
5
5
|
export { TrackSwap } from "./TrackSwap.js";
|
|
6
6
|
import { TrackSwap } from "./TrackSwap.js";
|
|
7
7
|
export default TrackSwap;
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var G=class{constructor(){this.stage="parse"}async process(e){let t=Date.now();if(!e.rawData)throw new Error("FIT data cannot be empty");try{let r=await this.parseWithFitSDK(e.rawData);return e.rawMessages=r,e.performance.parseTime=Date.now()-t,e}catch(r){throw new Error(`FIT parsing failed: ${r.message}`)}}async parseWithFitSDK(e){let{Decoder:t,Stream:r}=await import("@garmin/fitsdk"),n=r.fromBuffer(e);if(!t.isFIT(n))throw new Error("Not a valid FIT file");let i=new t(n),{messages:s,errors:o}=i.read();return o&&o.length>0,s}},B=class{constructor(e){this.getConverters=e;this.stage="extract"}async process(e){let t=Date.now();if(!e.rawMessages)throw new Error("Raw messages cannot be empty");let r={};for(let[n,i]of Object.entries(e.rawMessages)){if(!Array.isArray(i)||i.length===0){r[n]=i;continue}let s=this.getConverters(n);if(s.length===0)r[n]=i;else{let o=s[0];try{let a=o.convertMessages(i,e);r[n]=a}catch(a){e.errors.push(a),r[n]=i}}}return e.rawMessages=r,e.performance.extractTime=Date.now()-t,e}},H=class{constructor(e){this.getStructurePlugins=e;this.stage="structure"}async process(e){let t=Date.now();if(!e.rawMessages)throw new Error("Message data cannot be empty");let r={},n=this.getStructurePlugins();for(let i of n)try{let s=i.structureData(e.rawMessages,e);r={...r,...s}}catch(s){e.errors.push(s)}return e.result=r,e.performance.structureTime=Date.now()-t,e}},V=class{constructor(){this.stage="complete"}async process(e){e.performance.endTime=Date.now();let t=e.performance.endTime-e.performance.startTime;return e.metadata.set("performance",{totalTime:t,parseTime:e.performance.parseTime,extractTime:e.performance.extractTime,structureTime:e.performance.structureTime}),e.stats&&(e.stats.endTime=Date.now(),e.rawMessages&&(e.stats.processedTokens=this.countTotalMessages(e.rawMessages))),e}countTotalMessages(e){let t=0;return Object.values(e).forEach(r=>{Array.isArray(r)&&(t+=r.length)}),t}};import h from"dayjs";var be=class{constructor(){this.version="1.0.0";this.priority=100}supports(e){return this.supportedMessageTypes.includes(e)}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}parseTimestamp(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}calculateDuration(e,t){if(!e||!t)return 0;let r=new Date(e).getTime(),n=new Date(t).getTime();return Math.max(0,(n-r)/1e3)}filterMessagesByTimeRange(e,t,r,n=2e3){let i=new Date(t).getTime(),s=new Date(r).getTime();return e.filter(o=>{if(!o.timestamp)return!1;let a=new Date(o.timestamp).getTime();return a>=i-n&&a<=s+n})}groupMessagesByLap(e,t){return t.map(r=>{let n=this.filterMessagesByTimeRange(e,r.startTime,r.timestamp);return{lap:r,records:n}})}},v=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}},Ie=class{constructor(){this.version="1.0.0";this.description="";this.priority=100}async initialize(e){}async destroy(e){}async validate(e){return!0}async onParse(e,t){return e}async onExtractMessages(e,t){return e}async onStructure(e,t){return e}async onComplete(e,t){return e}async onError(e,t){}};var F=class extends v{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(t,r){let{sessionMesgs:n,lapMesgs:i,recordMesgs:s}=t;return n!=null&&n.length?{sessionMesgs:n.map(a=>{let c=h(a.startTime).valueOf(),d=h(a.timestamp).valueOf(),u=((i==null?void 0:i.filter(T=>{let g=h(T.startTime).valueOf(),I=h(T.timestamp).valueOf();return g>=c&&I<=d}))||[]).map(T=>{let g=h(T.startTime).valueOf(),I=h(T.timestamp).valueOf(),$=(s==null?void 0:s.filter(qe=>{let Ge=h(qe.timestamp).valueOf();return Ge>=g&&Ge<=I}))||[];return{...T,recordMesgs:$}});return{...a,lapMesgs:u}})}:{}}},k=class extends v{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(t,r){let{courseMesgs:n,lapMesgs:i,recordMesgs:s}=t;if(!(n!=null&&n.length))return{};let o=2e3;return{courseMesgs:n.map(c=>{let d=(i==null?void 0:i.map(l=>{let u=h(l.startTime).valueOf(),T=h(l.timestamp).valueOf(),g=(s==null?void 0:s.filter(I=>{let $=h(I.timestamp).valueOf();return $>=u-o&&$<=T+o}))||[];return{...l,recordMesgs:g}}))||[];return{...c,lapMesgs:d}})}}},A=class extends v{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(t,r){let{fileIdMesgs:n}=t;if(n!=null&&n.length&&n[0]){let i=n[0];r.fileHeader={type:i.type,manufacturer:i.manufacturer,product:i.product}}return{}}};var P=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 G,new B(e=>this.getConverters(e)),new H(()=>this.structurePlugins),new V]}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let e=[new A,new F,new k];for(let t of e)this.addStructurePlugin(t),this.registeredPlugins.add(t.name);this.defaultPluginsRegistered=!0}addConverterForMessageType(e,t){this.converterPlugins.has(e)||this.converterPlugins.set(e,[]);let r=this.converterPlugins.get(e);r.push(t),r.sort((n,i)=>(n.priority||100)-(i.priority||100))}addStructurePlugin(e){this.structurePlugins.push(e),this.structurePlugins.sort((t,r)=>(t.priority||100)-(r.priority||100))}async registerMessageConverter(e){if(this.registeredPlugins.has(e.name))throw new Error(`Message converter plugin ${e.name} already exists`);e.supportedMessageTypes.forEach(r=>{this.addConverterForMessageType(r,e)}),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:"";e.supportedMessageTypes.forEach(r=>{let i=(this.converterPlugins.get(r)||[]).map(s=>`${s.name}(${s.priority||100})`)})}async registerStructurePlugin(e){if(this.registeredPlugins.has(e.name))throw new Error(`Structure plugin ${e.name} already exists`);this.addStructurePlugin(e),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:""}async registerMiddleware(e){let t=this.middlewarePlugins.findIndex(n=>n.name===e.name);t!==-1?this.middlewarePlugins[t]=e:(this.middlewarePlugins.push(e),this.middlewarePlugins.sort((n,i)=>(n.priority||100)-(i.priority||100)));let r=[];e.onParse&&r.push("onParse"),e.onExtractMessages&&r.push("onExtractMessages"),e.onStructure&&r.push("onStructure"),e.onComplete&&r.push("onComplete"),e.onError&&r.push("onError"),r.length>0}getConverter(e){let t=this.converterPlugins.get(e);return t&&t.length>0?t[0]:void 0}getConverters(e){return this.converterPlugins.get(e)||[]}unregisterPlugin(e){if(!this.registeredPlugins.has(e))return!1;for(let[n,i]of this.converterPlugins){let s=i.findIndex(o=>o.name===e);s!==-1&&(i.splice(s,1),i.length===0&&this.converterPlugins.delete(n))}let t=this.structurePlugins.findIndex(n=>n.name===e);t!==-1&&this.structurePlugins.splice(t,1);let r=this.middlewarePlugins.findIndex(n=>n.name===e);return r!==-1&&this.middlewarePlugins.splice(r,1),this.registeredPlugins.delete(e),!0}async initialize(){var r;if(this.initialized)return;await this.registerDefaultPlugins();let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let n of t)try{await((r=n.initialize)==null?void 0:r.call(n,e))}catch{}this.initialized=!0}async destroy(){var r;if(!this.initialized)return;let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let n of t)try{await((r=n.destroy)==null?void 0:r.call(n,e))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(e,t,r){var i;let n=t;for(let s of this.middlewarePlugins){let o=s[e];if(o)try{n=await o.call(s,n,r)||n}catch(a){r.errors.push(a),await((i=s.onError)==null?void 0:i.call(s,a,r))}}return n}async parseByBuffer(e,t={}){var n;await this.initialize();let r=this.createContext();r.rawData=e,r.userData=t.userData,r.metadata.set("decoder",this);try{for(let i of this.processors)try{switch(r=await i.process(r),i.stage){case"parse":r.rawData&&(r.rawData=await this.executeMiddlewareHook("onParse",r.rawData,r));break;case"extract":r.rawMessages&&(r.rawMessages=await this.executeMiddlewareHook("onExtractMessages",r.rawMessages,r));break;case"structure":r.result&&(r.result=await this.executeMiddlewareHook("onStructure",r.result,r));break;case"complete":r.result&&(r.result=await this.executeMiddlewareHook("onComplete",r.result,r));break}}catch(s){r.errors.push(s);for(let o of this.middlewarePlugins)await((n=o.onError)==null?void 0:n.call(o,s,r))}return r.result||{}}catch(i){throw i}}};var Je={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}},x=p=>{let e=Je[p];return{size:1,baseType:0,mapValue:t=>typeof t=="string"?e[t]??255:t,setValue:function(t,r){this.setUint8(t,r)}}},Fe={enum_file:x("file"),enum_activity:x("sport"),enum_sport:x("sport"),enum_sub_sport:x("sport"),enum_event:x("event"),enum_event_type:x("event_type"),enum_course_point:x("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:p=>Array.from(He(p)),setValue:et},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:p=>Math.round(p*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:p=>Math.round(p*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:p=>Math.round((p+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:p=>Math.round(p*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:p=>{let e;return p instanceof Date?(e=Math.floor(p.getTime()/1e3),e-631065600):typeof p=="string"?(e=Math.floor(new Date(p).getTime()/1e3),e-631065600):p<631065600?Math.floor(p):(p>9999999999?e=Math.floor(p/1e3):e=Math.floor(p),e-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:p=>Math.round(p/180*2147483648)}};function Be(p){return Array.from(He(p)).length+1}function*He(p){for(let e of Qe(p))e<128?yield e:e<2048?(yield 192|e>>6,yield 128|e&63):e<65536?(yield 224|e>>12,yield 128|e>>6&63,yield 128|e&63):(yield 240|e>>18,yield 128|e>>12&63,yield 128|e>>6&63,yield 128|e&63);yield 0}function*Qe(p){for(let e=0;e<p.length;){let t=p.codePointAt(e);if(t===void 0)break;yield t,e+=t>65535?2:1}}function et(p,e){for(let t=0;t<e.length;t++)this.setUint8(p+t,e[t])}var tt={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:"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:"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:11,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{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_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"}]}},rt=(p,e)=>p.map(t=>({...t,value:e[t.name]})).filter(({value:t})=>t!==void 0),z=class p{static check(e,t,r,n){if(t===void 0)throw new Error(`Message '${e}' not known`);if(r===void 0)throw new Error(`Message '${e}' has no field definitions`);let i=r.map(o=>o.name),s=Object.keys(n).filter(o=>!i.includes(o));if(s.length)throw new Error(`Message '${e}' has no field definitions named '${s}'`)}constructor(e,t,r){let n=tt[t];if(!n)throw new Error(`Unknown message type: ${t}`);let{mesgNum:i,fieldDefns:s}=n;p.check(t,i,s,r),this.localNum=e,this.mesgNum=i,this.fields=rt(s,r)}get mesgDefn(){let e=this.fields.map(({number:t,type:r,value:n})=>{let i=Fe[r];if(!i)throw new Error(`Unknown type: ${r}`);let{size:s,baseType:o}=i;return r==="string"?{number:t,size:Be(n),baseType:o}:{number:t,size:s,baseType:o}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:e}}isSameDefn(e){let t=(o,a)=>o.number===a.number&&o.size===a.size&&o.baseType===a.baseType,r=(o,a)=>o.length===a.length&&o.every((c,d)=>t(c,a[d])),{localNum:n,mesgNum:i,fieldDefns:s}=this.mesgDefn;return i===e.mesgNum&&n===e.localNum&&r(s,e.fieldDefns)}get defnRecord(){let{localNum:e,mesgNum:t,fieldDefns:r}=this.mesgDefn,n=6+3*r.length,i=new DataView(new ArrayBuffer(n));i.setUint8(0,64|e),i.setUint8(2,1),i.setUint16(3,t),i.setUint8(5,r.length);let s=6;for(let o of r)i.setUint8(s++,o.number),i.setUint8(s++,o.size),i.setUint8(s++,o.baseType);return i.buffer}get dataRecord(){let{fieldDefns:e}=this.mesgDefn,t=1+e.reduce((i,{size:s})=>i+s,0),r=new DataView(new ArrayBuffer(t));r.setUint8(0,this.localNum);let n=1;for(let{number:i,type:s,value:o}of this.fields){let a=Fe[s];if(!a)throw new Error(`Unknown type: ${s}`);let{size:c,setValue:d}=a,l;"mapValue"in a?l=a.mapValue(o):l=o,d&&d.call(r,n,l),n+=c}return r.buffer}};var nt=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],Ve=(p,e)=>(p>>>4^nt[p&15^e])&65535,it=(p,e,t)=>Ve(Ve(p,e),t),st=(p,e)=>it(p,e&15,e>>>4);function ke(p,e=0){let t=e,r=p instanceof ArrayBuffer?new Uint8Array(p):p;for(let n=0;n<r.length;n++)t=st(t,r[n]);return t}import ot from"dayjs";var ze=14,at=16,pt=2078,ct=776358228,w=class{constructor(e={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:e.compact??!0,defaultSport:e.defaultSport??"cycling",defaultSubSport:e.defaultSubSport??"generic"}}async encode(e){return this.reset(),this.buildFITContent(e,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(e){return this.reset(),this.buildFITContent(e,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(e,t="activity"){return this.reset(),this.buildFITContent(e,t),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(e,t){this.buildFileId(e,t),t==="course"?this.buildCourseContent(e):this.buildActivityContent(e)}buildActivityContent(e){let t=e.sessionMesgs||[];if(t.length===0)throw new Error("Activity file must contain at least one Session");let r=0,n=[],i=[];for(let s of t){if(s.lapMesgs&&this.buildEventsFromLaps(s.lapMesgs,n),s.lapMesgs)for(let o of s.lapMesgs)o.recordMesgs&&this.buildRecords(o.recordMesgs);s.lapMesgs&&this.buildLaps(s.lapMesgs),this.buildSession(s),r++,this.buildActivityFromSession(s,i)}n.forEach(s=>this.buildEvent(s)),i.forEach(s=>this.buildActivity(s))}buildCourseContent(e){let t=e.sessionMesgs||[];if(t.length===0)throw new Error("Course file must contain track data");let r=t[0];if(this.buildCourse({name:"course",sport:this.options.defaultSport}),r.lapMesgs){let n=[];for(let o of r.lapMesgs)o.recordMesgs&&n.push(...o.recordMesgs);n.sort((o,a)=>o.timestamp&&a.timestamp?new Date(o.timestamp).getTime()-new Date(a.timestamp).getTime():(o.distance||0)-(a.distance||0));let i=n[0],s=n[n.length-1];i.timestamp&&this.buildEvent({timestamp:i.timestamp,event:"timer",eventType:"start",eventGroup:0}),n.forEach(o=>this.buildRecord(o)),s.timestamp&&this.buildEvent({timestamp:s.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),r.lapMesgs[0]&&this.buildLap(r.lapMesgs[0])}}buildFileId(e,t){var n;let r=((n=e.fileIdMesgs)==null?void 0:n[0])||{};this.writeMesg("file_id",{type:t,time_created:r.timeCreated?this.parseTimestamp(r.timeCreated):Date.now(),manufacturer:r.manufacturer,product:r.product,serial_number:r.serialNumber})}buildSession(e){var t;this.writeMesg("session",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,start_time:e.startTime?this.parseTimestamp(e.startTime):void 0,total_elapsed_time:e.totalElapsedTime,total_timer_time:e.totalTimerTime,start_position_lat:this.convertToSemicircles(e.startPositionLat),start_position_long:this.convertToSemicircles(e.startPositionLong),total_distance:e.totalDistance,total_ascent:e.totalAscent,total_descent:e.totalDescent,sport:e.sport||this.options.defaultSport,sub_sport:e.subSport||this.options.defaultSubSport,first_lap_index:e.firstLapIndex||0,num_laps:e.numLaps||((t=e.lapMesgs)==null?void 0:t.length)||1})}buildLaps(e){e.forEach(t=>this.buildLap(t))}buildLap(e){this.writeMesg("lap",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,start_time:e.startTime?this.parseTimestamp(e.startTime):void 0,start_position_lat:this.convertToSemicircles(e.startPositionLat),start_position_long:this.convertToSemicircles(e.startPositionLong),end_position_lat:this.convertToSemicircles(e.endPositionLat),end_position_long:this.convertToSemicircles(e.endPositionLong),total_elapsed_time:e.totalElapsedTime,total_timer_time:e.totalTimerTime,total_distance:e.totalDistance,total_ascent:e.totalAscent,total_descent:e.totalDescent})}buildRecords(e){e.forEach(t=>this.buildRecord(t))}buildRecord(e){this.writeMesg("record",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,position_lat:this.convertToSemicircles(e.positionLat),position_long:this.convertToSemicircles(e.positionLong),altitude:e.enhancedAltitude||e.altitude,distance:e.distance,heart_rate:e.heartRate,cadence:e.cadence,speed:e.enhancedSpeed||e.speed,power:e.power})}buildEvent(e){this.writeMesg("event",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,event:e.event,event_type:e.eventType,event_group:e.eventGroup})}buildActivity(e){this.writeMesg("activity",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,total_timer_time:e.totalTimerTime,num_sessions:e.numSessions,type:e.type,event:e.event,event_type:e.eventType,local_timestamp:e.localTimestamp?this.parseTimestamp(e.localTimestamp):void 0,event_group:e.eventGroup})}buildCourse(e){this.writeMesg("course",{name:e.name,sport:e.sport})}buildEventsFromLaps(e,t){e.forEach((r,n)=>{r.startTime&&t.push({timestamp:r.startTime,event:"timer",eventType:"start",eventGroup:n}),r.timestamp&&t.push({timestamp:r.timestamp,event:"timer",eventType:n===e.length-1?"stop_all":"stop",eventGroup:n})})}buildActivityFromSession(e,t){t.push({timestamp:e.timestamp,totalTimerTime:e.totalTimerTime,numSessions:1,type:e.sport||this.options.defaultSport,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(e){return typeof e=="number"?e:ot(e).valueOf()}convertToSemicircles(e){if(e!=null)return Math.round(e*2**31/180)}validateRequiredFields(e){if(!e.sessionMesgs||e.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(e,t){let r=Object.fromEntries(Object.entries(t).filter(([o,a])=>a!==void 0));if(Object.keys(r).length===0)return;let n=this.localNum[e];n===void 0&&(n=this.localNum[e]=Object.keys(this.localNum).length);let i=new z(n,e,r),s=this.mesgDefn[n];(!s||!i.isSameDefn(s))&&(this.messages.push(i.defnRecord),this.mesgDefn[n]=i.mesgDefn),this.messages.push(i.dataRecord)}get blob(){let e=[this.header,...this.messages,this.trailer];return new Blob(e,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((e,t)=>e+t.byteLength,0)}get dataCrc(){return this.messages.reduce((e,t)=>ke(t,e),0)}get header(){let e=new DataView(new ArrayBuffer(ze));return e.setUint8(0,ze),e.setUint8(1,at),e.setUint16(2,pt,!0),e.setUint32(4,this.dataLen,!0),e.setUint32(8,ct),e.setUint16(12,ke(e.buffer.slice(0,12)),!0),e.buffer}get trailer(){let e=new DataView(new ArrayBuffer(2));return e.setUint16(0,this.dataCrc,!0),e.buffer}async encoder(e){return this.encode(e)}};var y=class{constructor(){this.version="1.0.0";this.priority=100}supports(e){return this.supportedTags.includes(e)}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}parseFloat(e){if(!(typeof e>"u"))return typeof e=="number"?e:typeof e=="string"&&parseFloat(e)||0}parseInt(e){return typeof e=="number"?Math.floor(e):typeof e=="string"&&parseInt(e,10)||0}parseString(e){return String(e||"")}parseBoolean(e){return typeof e=="boolean"?e:typeof e=="string"?e.toLowerCase()==="true":!1}parseDate(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}hasRequiredAttributes(e,t){return t.every(r=>{var n;return(n=e.attributes)==null?void 0:n[r]})}extractAttributes(e,t,r){e.attributes&&Object.entries(e.attributes).forEach(([n,i])=>{let s=r[n];s&&s in t&&(t[s]=String(i||""))})}processChildren(e,t,r){var n;(n=e.children)==null||n.forEach(i=>{let s=r[i.tag];s&&s(i,t)})}getChildValue(e,t){var n;let r=(n=e.children)==null?void 0:n.find(i=>i.tag===t);return r!=null&&r.value?String(r.value):void 0}getChildByTag(e,t){var r;return(r=e.children)==null?void 0:r.find(n=>n.tag===t)}getChildrenByTag(e,t){var r;return((r=e.children)==null?void 0:r.filter(n=>n.tag===t))||[]}convertExtensions(e){var r;let t={};return(r=e.children)==null||r.forEach(n=>{t[n.tag]=this.convertExtensionContent(n)}),t}convertExtensionContent(e){var t;if((t=e.children)!=null&&t.length){let r={};return e.children.forEach(n=>{r[n.tag]=this.convertExtensionContent(n)}),r}else return e.value}},C=class{constructor(){this.version="1.0.0";this.description=""}async initialize(e){}async destroy(e){}async validate(e){return!0}async onTokenize(e,t){return e}async onAstGenerate(e,t){return e}async onConvert(e,t){return e}async onComplete(e,t){return e}async onError(e,t){}};var m=class extends y{parseCoordinate(e){let t=this.parseFloat(e);return t===0?void 0:t}parseGPXTime(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}extractNumericAttributes(e,t,r){e.attributes&&Object.entries(e.attributes).forEach(([n,i])=>{let s=r[n];s&&s in t&&typeof i<"u"&&(t[s]=this.parseFloat(i))})}},_=class extends C{async onError(e,t){t.warnings.push(`Middleware ${this.name} error: ${e.message}`)}};var U=class extends m{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(t,r){var i,s;if(!this.hasRequiredAttributes(t,["lat","lon"]))return;let n={lat:this.parseFloat((i=t.attributes)==null?void 0:i.lat),lon:this.parseFloat((s=t.attributes)==null?void 0:s.lon)};return this.processChildren(t,n,{ele:(o,a)=>a.ele=this.parseFloat(o.value),time:(o,a)=>a.time=new Date(this.parseString(o.value)),speed:(o,a)=>a.speed=this.parseFloat(o.value),power:(o,a)=>a.power=this.parseFloat(o.value),cadence:(o,a)=>a.cadence=this.parseFloat(o.value),heartRate:(o,a)=>a.heartRate=this.parseFloat(o.value),course:(o,a)=>a.course=this.parseFloat(o.value),name:(o,a)=>a.name=this.parseString(o.value),cmt:(o,a)=>a.cmt=this.parseString(o.value),desc:(o,a)=>a.desc=this.parseString(o.value),src:(o,a)=>a.src=this.parseString(o.value),sym:(o,a)=>a.sym=this.parseString(o.value),type:(o,a)=>a.type=this.parseString(o.value),fix:(o,a)=>a.fix=this.parseString(o.value),sat:(o,a)=>a.sat=this.parseString(o.value),hdop:(o,a)=>a.hdop=this.parseFloat(o.value),vdop:(o,a)=>a.vdop=this.parseFloat(o.value),pdop:(o,a)=>a.pdop=this.parseFloat(o.value),ageofdgpsdata:(o,a)=>a.ageofdgpsdata=this.parseFloat(o.value),geoidheight:(o,a)=>a.geoidheight=this.parseFloat(o.value),magvar:(o,a)=>a.magvar=this.parseFloat(o.value),dgpsid:(o,a)=>a.dgpsid=this.parseFloat(o.value),extensions:(o,a)=>{let c=r.metadata.get("decoder"),d=c==null?void 0:c.getConverter("extensions");if(d){let l=d.convert(o,r);l&&(this.mapExtensionsToPoint(l,a),a.extensions=l)}},link:(o,a)=>{var l;a.link||(a.link=[]);let c=r.metadata.get("decoder"),d=(l=c==null?void 0:c.getConverter("link"))==null?void 0:l.convert(o,r);d&&a.link&&a.link.push(d)}}),n}mapExtensionsToPoint(t,r){Object.entries(t).forEach(([n,i])=>{if(i!==void 0&&(typeof i=="string"||typeof i=="number")){let s=o=>(Array.isArray(o)?o:[o]).some(c=>{let d=n.toLowerCase(),l=c.toLowerCase();return d===l||d.endsWith(`:${l}`)});s("speed")?r.speed=this.parseFloat(i):s("hr")?r.heartRate=this.parseFloat(i):s(["cad","cadence"])?r.cadence=this.parseFloat(i):s(["PowerInWatts","power"])&&(r.power=this.parseFloat(i))}})}},W=class extends m{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(t,r){let n={rtept:[]};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),cmt:(i,s)=>s.cmt=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),src:(i,s)=>s.src=this.parseString(i.value),number:(i,s)=>s.number=this.parseFloat(i.value),type:(i,s)=>s.type=this.parseString(i.value),rtept:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("wpt"))==null?void 0:c.convert(i,r);a&&s.rtept&&s.rtept.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var a;s.link||(s.link=[]);let o=r.metadata.get("decoder");(a=i.children)==null||a.forEach(c=>{var l;let d=(l=o==null?void 0:o.getConverter("link"))==null?void 0:l.convert(c,r);d&&s.link&&s.link.push(d)})}}),n}},j=class extends m{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(t,r){let n={trkseg:[]};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),cmt:(i,s)=>s.cmt=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),src:(i,s)=>s.src=this.parseString(i.value),number:(i,s)=>s.number=this.parseFloat(i.value),type:(i,s)=>s.type=this.parseString(i.value),trkseg:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("trkseg"))==null?void 0:c.convert(i,r);a&&s.trkseg&&s.trkseg.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var a;s.link||(s.link=[]);let o=r.metadata.get("decoder");(a=i.children)==null||a.forEach(c=>{var l;let d=(l=o==null?void 0:o.getConverter("link"))==null?void 0:l.convert(c,r);d&&s.link&&s.link.push(d)})}}),n}},K=class extends m{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(t,r){let n={trkpt:[]};return this.processChildren(t,n,{trkpt:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("wpt"))==null?void 0:c.convert(i,r);a&&s.trkpt&&s.trkpt.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))}}),n}},Y=class extends m{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(t,r){var i;let n={};return(i=t.attributes)!=null&&i.href&&(n.href=t.attributes.href),this.processChildren(t,n,{text:(s,o)=>o.text=this.parseString(s.value),type:(s,o)=>o.type=this.parseString(s.value)}),n}},N=class extends m{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(t,r){let n={};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),keywords:(i,s)=>s.keywords=this.parseString(i.value),time:(i,s)=>s.time=new Date(this.parseString(i.value)),author:(i,s)=>{var a;let o=r.metadata.get("decoder");s.author=(a=o==null?void 0:o.getConverter("author"))==null?void 0:a.convert(i,r)},copyright:(i,s)=>{var a;let o=r.metadata.get("decoder");s.copyright=(a=o==null?void 0:o.getConverter("copyright"))==null?void 0:a.convert(i,r)},bounds:(i,s)=>{var a;let o=r.metadata.get("decoder");s.bounds=(a=o==null?void 0:o.getConverter("bounds"))==null?void 0:a.convert(i,r)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var c;s.link||(s.link=[]);let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("link"))==null?void 0:c.convert(i,r);a&&s.link&&s.link.push(a)}}),n}},Z=class extends m{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(t,r){var i;let n={};return t.value&&!((i=t.children)!=null&&i.length)?(n.name=this.parseString(t.value),n):(this.processChildren(t,n,{name:(s,o)=>o.name=this.parseString(s.value),email:(s,o)=>{var c;let a=r.metadata.get("decoder");o.email=(c=a==null?void 0:a.getConverter("email"))==null?void 0:c.convert(s,r)},link:(s,o)=>{var c;let a=r.metadata.get("decoder");o.link=(c=a==null?void 0:a.getConverter("link"))==null?void 0:c.convert(s,r)}}),n)}},q=class extends m{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(t,r){let n={};return this.processChildren(t,n,{id:(i,s)=>s.id=this.parseString(i.value),domain:(i,s)=>s.domain=this.parseString(i.value)}),n}},J=class extends m{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(t,r){var i;let n={};return(i=t.attributes)!=null&&i.author&&(n.author=t.attributes.author),this.processChildren(t,n,{year:(s,o)=>o.year=this.parseString(s.value),license:(s,o)=>o.license=this.parseString(s.value)}),n}},Q=class extends m{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(t,r){let n={};return this.extractAttributes(t,n,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),n}},ee=class extends m{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(t,r){var i;let n={};return(i=t.children)==null||i.forEach(s=>{this.flattenExtensionElement(s,n)}),n}flattenExtensionElement(t,r){var n,i;if(!((n=t.children)!=null&&n.length)&&t.value!==void 0){r[t.tag]=this.parseExtensionValue(t.value);return}(i=t.children)!=null&&i.length&&t.children.forEach(s=>{this.flattenExtensionElement(s,r)})}parseExtensionValue(t){if(t===void 0)return;let r=String(t),n=parseFloat(r);return!isNaN(n)&&isFinite(n)?n:r}};import{Parser as dt}from"htmlparser2";var Ae=(n=>(n.TOKENIZE="tokenize",n.AST_GENERATE="ast_generate",n.CONVERT="convert",n.COMPLETE="complete",n))(Ae||{}),te=class{constructor(){this.stage="tokenize"}async process(e){let t=Date.now();if(!e.xmlContent)throw new Error("XML content cannot be empty");let r=[],n=new dt({onopentag(i,s){r.push({type:"open",tag:i,attributes:s})},ontext(i){let s=i.replace(/\n/g,"").trim();s&&r.push({type:"text",tag:"text",value:s})},onclosetag(i){r.push({type:"close",tag:i})}},{xmlMode:!0});return n.write(e.xmlContent),n.end(),e.tokens=r,e.performance.tokenizeTime=Date.now()-t,e}},re=class{constructor(){this.stage="ast_generate"}async process(e){var s;let t=Date.now();if(!e.tokens)throw new Error("Tokens cannot be empty");let r=[],n,i=null;for(let o of e.tokens)if(o.type==="open"){let a={tag:o.tag,attributes:o.attributes||{},children:[]};n?i&&((s=i.children)==null||s.push(a)):n=a,r.push(a),i=a}else o.type==="text"&&i?i.value=o.value:o.type==="close"&&(r.pop(),i=r[r.length-1]||null);return e.ast=n,e.performance.astTime=Date.now()-t,e}},ne=class{constructor(e){this.getConverter=e;this.stage="convert"}async process(e){var n;let t=Date.now();if(!e.ast)throw new Error("AST cannot be empty");let r={};return e.ast.attributes&&Object.entries(e.ast.attributes).forEach(([i,s])=>{i.startsWith("xmlns:")?r[i]=s.replace(/'/g,"'"):i==="xsi:schemaLocation"?r[i]=s.replace(/'/g,"'"):r[i]=s}),(n=e.ast.children)==null||n.forEach(i=>{let s=this.getConverter(i.tag);try{let o=s.convert(i,e);o&&this.assignResult(r,i.tag,o)}catch(o){e.errors.push(o)}}),e.result=r,e.performance.convertTime=Date.now()-t,e}assignResult(e,t,r){switch(t){case"metadata":e.metadata=r;break;case"wpt":e.wpt||(e.wpt=[]),e.wpt.push(r);break;case"rte":e.rte||(e.rte=[]),e.rte.push(r);break;case"trk":e.trk||(e.trk=[]),e.trk.push(r);break;case"extensions":e.extensions=r;break}}},ie=class{constructor(){this.stage="complete"}async process(e){e.performance.endTime=Date.now();let t=e.performance.endTime-e.performance.startTime;return e.metadata.set("performance",{totalTime:t,tokenizeTime:e.performance.tokenizeTime,astTime:e.performance.astTime,convertTime:e.performance.convertTime}),e}};var D=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 te,new re,new ne(e=>this.getConverter(e)),new ie]}async registerDefaultConverters(){var t;if(this.defaultConvertersRegistered)return;let e=[new U,new W,new j,new K,new Y,new N,new Z,new q,new J,new Q,new ee];for(let r of e)(t=r.supportedTags)==null||t.forEach(n=>{this.addConverterForTag(n,r)}),this.registeredPlugins.add(r.name);this.defaultConvertersRegistered=!0}addConverterForTag(e,t){this.converterPlugins.has(e)||this.converterPlugins.set(e,[]);let r=this.converterPlugins.get(e);r.push(t),r.sort((n,i)=>(n.priority||100)-(i.priority||100))}async registerConverter(e){var r,i;if(this.registeredPlugins.has(e.name))throw new Error(`Converter plugin ${e.name} already exists`);(r=e.supportedTags)==null||r.forEach(s=>{this.addConverterForTag(s,e)}),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:"";(i=e.supportedTags)==null||i.forEach(s=>{let a=(this.converterPlugins.get(s)||[]).map(c=>`${c.name}(${c.priority||100})`)})}async registerMiddleware(e){let t=this.middlewarePlugins.findIndex(n=>n.name===e.name);t!==-1?this.middlewarePlugins[t]=e:this.middlewarePlugins.push(e);let r=[];e.onTokenize&&r.push("onTokenize"),e.onAstGenerate&&r.push("onAstGenerate"),e.onConvert&&r.push("onConvert"),e.onComplete&&r.push("onComplete"),e.onError&&r.push("onError"),r.length>0}getConverter(e){let t=this.converterPlugins.get(e);return t&&t.length>0?t[0]:void 0}getAllConverters(e){return this.converterPlugins.get(e)||[]}unregisterConverter(e){let t;for(let[r,n]of this.converterPlugins){let i=n.findIndex(s=>s.name===e);i!==-1&&(t=n[i],n.splice(i,1),n.length===0&&this.converterPlugins.delete(r))}t&&this.registeredPlugins.delete(e)}unregisterMiddleware(e){let t=this.middlewarePlugins.findIndex(r=>r.name===e);t!==-1&&this.middlewarePlugins.splice(t,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(e=>e.name)}listProcessors(){return this.processors.map(e=>e.constructor.name)}getConverterDetails(e){let t={};if(e){let r=this.converterPlugins.get(e);r&&(t[e]=r.map(n=>({name:n.name,priority:n.priority||100})))}else for(let[r,n]of this.converterPlugins)t[r]=n.map(i=>({name:i.name,priority:i.priority||100}));return t}getMiddlewareDetails(){return this.middlewarePlugins.map(e=>{let t=[];return e.onTokenize&&t.push("onTokenize"),e.onAstGenerate&&t.push("onAstGenerate"),e.onConvert&&t.push("onConvert"),e.onComplete&&t.push("onComplete"),e.onError&&t.push("onError"),{name:e.name,hooks:t}})}async initialize(){var r;if(this.initialized)return;await this.registerDefaultConverters();let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.initialize)==null?void 0:r.call(n,e))}catch{}this.initialized=!0}async destroy(){var r;if(!this.initialized)return;let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.destroy)==null?void 0:r.call(n,e))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(e,t,r){var i;let n=t;for(let s of this.middlewarePlugins){let o=s[e];if(o)try{n=await o.call(s,n,r)||n}catch(a){r.errors.push(a),await((i=s.onError)==null?void 0:i.call(s,a,r))}}return n}async parserByBuffer(e){var r;await this.initialize();let t=this.createContext();t.rawData=e,t.xmlContent=e.toString("utf-8"),t.metadata.set("decoder",this);try{for(let n of this.processors)try{switch(t=await n.process(t),n.stage){case"tokenize":t.tokens&&(t.tokens=await this.executeMiddlewareHook("onTokenize",t.tokens,t));break;case"ast_generate":t.ast&&(t.ast=await this.executeMiddlewareHook("onAstGenerate",t.ast,t));break;case"convert":t.result&&(t.result=await this.executeMiddlewareHook("onConvert",t.result,t));break;case"complete":t.result&&(t.result=await this.executeMiddlewareHook("onComplete",t.result,t));break}}catch(i){t.errors.push(i);for(let s of this.middlewarePlugins)await((r=s.onError)==null?void 0:r.call(s,i,t))}return t.result}catch(n){throw n}}convertExtensions(e){var s,o;let t={},{attributes:r,tag:n,value:i}=e;if(r&&Object.entries(r).forEach(([a,c])=>{t[a]=c}),(s=e==null?void 0:e.children)!=null&&s.length)(o=e.children)==null||o.forEach(a=>{t[a.tag]=this.convertExtensions(a)});else if(i!==void 0)return i;return t}};import Ue from"dayjs";import lt from"dayjs/plugin/utc.js";var _e={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var De={temperature:"Temperature",Depth:"Depth"};Ue.extend(lt);var X=class{constructor(e={}){this.formatElevation=e=>{let t=parseFloat(e);return isNaN(t)?e:this.roundTo(t,2).toString()};this.compact=e.compact??!0}async encode(e){let t=this.buildGPXXML(e);return Buffer.from(t,"utf-8")}encodeToString(e){return this.buildGPXXML(e)}buildGPXXML(e){let t=this.buildXMLHeader(),r=this.buildGPXContent(e),i=`${t}${r}
|
|
1
|
+
var $=class{constructor(){this.stage="parse"}async process(e){let t=Date.now();if(!e.rawData)throw new Error("FIT data cannot be empty");try{let r=await this.parseWithFitSDK(e.rawData);return e.rawMessages=r,e.performance.parseTime=Date.now()-t,e}catch(r){throw new Error(`FIT parsing failed: ${r.message}`)}}async parseWithFitSDK(e){let{Decoder:t,Stream:r}=await import("@garmin/fitsdk"),n=r.fromBuffer(e);if(!t.isFIT(n))throw new Error("Not a valid FIT file");let i=new t(n),{messages:s,errors:o}=i.read();return o&&o.length>0,s}},G=class{constructor(e){this.getConverters=e;this.stage="extract"}async process(e){let t=Date.now();if(!e.rawMessages)throw new Error("Raw messages cannot be empty");let r={};for(let[n,i]of Object.entries(e.rawMessages)){if(!Array.isArray(i)||i.length===0){r[n]=i;continue}let s=this.getConverters(n);if(s.length===0)r[n]=i;else{let o=s[0];try{let a=o.convertMessages(i,e);r[n]=a}catch(a){e.errors.push(a),r[n]=i}}}return e.rawMessages=r,e.performance.extractTime=Date.now()-t,e}},B=class{constructor(e){this.getStructurePlugins=e;this.stage="structure"}async process(e){let t=Date.now();if(!e.rawMessages)throw new Error("Message data cannot be empty");let r={},n=this.getStructurePlugins();for(let i of n)try{let s=i.structureData(e.rawMessages,e);r={...r,...s}}catch(s){e.errors.push(s)}return e.result=r,e.performance.structureTime=Date.now()-t,e}},H=class{constructor(){this.stage="complete"}async process(e){e.performance.endTime=Date.now();let t=e.performance.endTime-e.performance.startTime;return e.metadata.set("performance",{totalTime:t,parseTime:e.performance.parseTime,extractTime:e.performance.extractTime,structureTime:e.performance.structureTime}),e.stats&&(e.stats.endTime=Date.now(),e.rawMessages&&(e.stats.processedTokens=this.countTotalMessages(e.rawMessages))),e}countTotalMessages(e){let t=0;return Object.values(e).forEach(r=>{Array.isArray(r)&&(t+=r.length)}),t}};import h from"dayjs";var v=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}};var _=class extends v{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(t,r){let{sessionMesgs:n,lapMesgs:i,recordMesgs:s}=t;return n!=null&&n.length?{sessionMesgs:n.map(a=>{let p=h(a.startTime).valueOf(),d=h(a.timestamp).valueOf(),u=((i==null?void 0:i.filter(T=>{let g=h(T.startTime).valueOf(),F=h(T.timestamp).valueOf();return g>=p&&F<=d}))||[]).map(T=>{let g=h(T.startTime).valueOf(),F=h(T.timestamp).valueOf(),O=(s==null?void 0:s.filter(We=>{let Xe=h(We.timestamp).valueOf();return Xe>=g&&Xe<=F}))||[];return{...T,recordMesgs:O}});return{...a,lapMesgs:u}})}:{}}},D=class extends v{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(t,r){let{courseMesgs:n,lapMesgs:i,recordMesgs:s}=t;if(!(n!=null&&n.length))return{};let o=2e3;return{courseMesgs:n.map(p=>{let d=(i==null?void 0:i.map(l=>{let u=h(l.startTime).valueOf(),T=h(l.timestamp).valueOf(),g=(s==null?void 0:s.filter(F=>{let O=h(F.timestamp).valueOf();return O>=u-o&&O<=T+o}))||[];return{...l,recordMesgs:g}}))||[];return{...p,lapMesgs:d}})}}},X=class extends v{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(t,r){let{fileIdMesgs:n}=t;if(n!=null&&n.length&&n[0]){let i=n[0];r.fileHeader={type:i.type,manufacturer:i.manufacturer,product:i.product}}return{}}};var x=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 $,new G(e=>this.getConverters(e)),new B(()=>this.structurePlugins),new H]}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let e=[new X,new _,new D];for(let t of e)this.addStructurePlugin(t),this.registeredPlugins.add(t.name);this.defaultPluginsRegistered=!0}addConverterForMessageType(e,t){this.converterPlugins.has(e)||this.converterPlugins.set(e,[]);let r=this.converterPlugins.get(e);r.push(t),r.sort((n,i)=>(n.priority||100)-(i.priority||100))}addStructurePlugin(e){this.structurePlugins.push(e),this.structurePlugins.sort((t,r)=>(t.priority||100)-(r.priority||100))}async registerMessageConverter(e){if(this.registeredPlugins.has(e.name))throw new Error(`Message converter plugin ${e.name} already exists`);e.supportedMessageTypes.forEach(r=>{this.addConverterForMessageType(r,e)}),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:"";e.supportedMessageTypes.forEach(r=>{let i=(this.converterPlugins.get(r)||[]).map(s=>`${s.name}(${s.priority||100})`)})}async registerStructurePlugin(e){if(this.registeredPlugins.has(e.name))throw new Error(`Structure plugin ${e.name} already exists`);this.addStructurePlugin(e),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:""}async registerMiddleware(e){let t=this.middlewarePlugins.findIndex(n=>n.name===e.name);t!==-1?this.middlewarePlugins[t]=e:(this.middlewarePlugins.push(e),this.middlewarePlugins.sort((n,i)=>(n.priority||100)-(i.priority||100)));let r=[];e.onParse&&r.push("onParse"),e.onExtractMessages&&r.push("onExtractMessages"),e.onStructure&&r.push("onStructure"),e.onComplete&&r.push("onComplete"),e.onError&&r.push("onError"),r.length>0}getConverter(e){let t=this.converterPlugins.get(e);return t&&t.length>0?t[0]:void 0}getConverters(e){return this.converterPlugins.get(e)||[]}unregisterPlugin(e){if(!this.registeredPlugins.has(e))return!1;for(let[n,i]of this.converterPlugins){let s=i.findIndex(o=>o.name===e);s!==-1&&(i.splice(s,1),i.length===0&&this.converterPlugins.delete(n))}let t=this.structurePlugins.findIndex(n=>n.name===e);t!==-1&&this.structurePlugins.splice(t,1);let r=this.middlewarePlugins.findIndex(n=>n.name===e);return r!==-1&&this.middlewarePlugins.splice(r,1),this.registeredPlugins.delete(e),!0}async initialize(){var r;if(this.initialized)return;await this.registerDefaultPlugins();let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let n of t)try{await((r=n.initialize)==null?void 0:r.call(n,e))}catch{}this.initialized=!0}async destroy(){var r;if(!this.initialized)return;let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let n of t)try{await((r=n.destroy)==null?void 0:r.call(n,e))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(e,t,r){var i;let n=t;for(let s of this.middlewarePlugins){let o=s[e];if(o)try{n=await o.call(s,n,r)||n}catch(a){r.errors.push(a),await((i=s.onError)==null?void 0:i.call(s,a,r))}}return n}async parseByBuffer(e,t={}){var n;await this.initialize();let r=this.createContext();r.rawData=e,r.userData=t.userData,r.metadata.set("decoder",this);try{for(let i of this.processors)try{switch(r=await i.process(r),i.stage){case"parse":r.rawData&&(r.rawData=await this.executeMiddlewareHook("onParse",r.rawData,r));break;case"extract":r.rawMessages&&(r.rawMessages=await this.executeMiddlewareHook("onExtractMessages",r.rawMessages,r));break;case"structure":r.result&&(r.result=await this.executeMiddlewareHook("onStructure",r.result,r));break;case"complete":r.result&&(r.result=await this.executeMiddlewareHook("onComplete",r.result,r));break}}catch(s){r.errors.push(s);for(let o of this.middlewarePlugins)await((n=o.onError)==null?void 0:n.call(o,s,r))}return r.result||{}}catch(i){throw i}}};var je={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}},C=c=>{let e=je[c];return{size:1,baseType:0,mapValue:t=>typeof t=="string"?e[t]??255:t,setValue:function(t,r){this.setUint8(t,r)}}},Se={enum_file:C("file"),enum_activity:C("sport"),enum_sport:C("sport"),enum_sub_sport:C("sport"),enum_event:C("event"),enum_event_type:C("event_type"),enum_course_point:C("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:c=>Array.from(Me(c)),setValue:Ye},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:c=>Math.round(c*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:c=>Math.round(c*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:c=>Math.round((c+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:c=>Math.round(c*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:c=>{let e;return c instanceof Date?(e=Math.floor(c.getTime()/1e3),e-631065600):typeof c=="string"?(e=Math.floor(new Date(c).getTime()/1e3),e-631065600):c<631065600?Math.floor(c):(c>9999999999?e=Math.floor(c/1e3):e=Math.floor(c),e-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:c=>Math.round(c/180*2147483648)}};function Re(c){return Array.from(Me(c)).length+1}function*Me(c){for(let e of Ke(c))e<128?yield e:e<2048?(yield 192|e>>6,yield 128|e&63):e<65536?(yield 224|e>>12,yield 128|e>>6&63,yield 128|e&63):(yield 240|e>>18,yield 128|e>>12&63,yield 128|e>>6&63,yield 128|e&63);yield 0}function*Ke(c){for(let e=0;e<c.length;){let t=c.codePointAt(e);if(t===void 0)break;yield t,e+=t>65535?2:1}}function Ye(c,e){for(let t=0;t<e.length;t++)this.setUint8(c+t,e[t])}var Ne={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:"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:"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:11,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{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_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"}]}},Ze=(c,e)=>c.map(t=>({...t,value:e[t.name]})).filter(({value:t})=>t!==void 0),V=class c{static check(e,t,r,n){if(t===void 0)throw new Error(`Message '${e}' not known`);if(r===void 0)throw new Error(`Message '${e}' has no field definitions`);let i=r.map(o=>o.name),s=Object.keys(n).filter(o=>!i.includes(o));if(s.length)throw new Error(`Message '${e}' has no field definitions named '${s}'`)}constructor(e,t,r){let n=Ne[t];if(!n)throw new Error(`Unknown message type: ${t}`);let{mesgNum:i,fieldDefns:s}=n;c.check(t,i,s,r),this.localNum=e,this.mesgNum=i,this.fields=Ze(s,r)}get mesgDefn(){let e=this.fields.map(({number:t,type:r,value:n})=>{let i=Se[r];if(!i)throw new Error(`Unknown type: ${r}`);let{size:s,baseType:o}=i;return r==="string"?{number:t,size:Re(n),baseType:o}:{number:t,size:s,baseType:o}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:e}}isSameDefn(e){let t=(o,a)=>o.number===a.number&&o.size===a.size&&o.baseType===a.baseType,r=(o,a)=>o.length===a.length&&o.every((p,d)=>t(p,a[d])),{localNum:n,mesgNum:i,fieldDefns:s}=this.mesgDefn;return i===e.mesgNum&&n===e.localNum&&r(s,e.fieldDefns)}get defnRecord(){let{localNum:e,mesgNum:t,fieldDefns:r}=this.mesgDefn,n=6+3*r.length,i=new DataView(new ArrayBuffer(n));i.setUint8(0,64|e),i.setUint8(2,1),i.setUint16(3,t),i.setUint8(5,r.length);let s=6;for(let o of r)i.setUint8(s++,o.number),i.setUint8(s++,o.size),i.setUint8(s++,o.baseType);return i.buffer}get dataRecord(){let{fieldDefns:e}=this.mesgDefn,t=1+e.reduce((i,{size:s})=>i+s,0),r=new DataView(new ArrayBuffer(t));r.setUint8(0,this.localNum);let n=1;for(let{number:i,type:s,value:o}of this.fields){let a=Se[s];if(!a)throw new Error(`Unknown type: ${s}`);let{size:p,setValue:d}=a,l;"mapValue"in a?l=a.mapValue(o):l=o,d&&d.call(r,n,l),n+=p}return r.buffer}};var qe=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],Le=(c,e)=>(c>>>4^qe[c&15^e])&65535,Je=(c,e,t)=>Le(Le(c,e),t),Qe=(c,e)=>Je(c,e&15,e>>>4);function Ie(c,e=0){let t=e,r=c instanceof ArrayBuffer?new Uint8Array(c):c;for(let n=0;n<r.length;n++)t=Qe(t,r[n]);return t}import et from"dayjs";var Oe=14,tt=16,rt=2078,nt=776358228,P=class{constructor(e={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:e.compact??!0,defaultSport:e.defaultSport??"cycling",defaultSubSport:e.defaultSubSport??"generic"}}async encode(e){return this.reset(),this.buildFITContent(e,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(e){return this.reset(),this.buildFITContent(e,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(e,t="activity"){return this.reset(),this.buildFITContent(e,t),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(e,t){this.buildFileId(e,t),t==="course"?this.buildCourseContent(e):this.buildActivityContent(e)}buildActivityContent(e){let t=e.sessionMesgs||[];if(t.length===0)throw new Error("Activity file must contain at least one Session");let r=0,n=[],i=[];for(let s of t){if(s.lapMesgs&&this.buildEventsFromLaps(s.lapMesgs,n),s.lapMesgs)for(let o of s.lapMesgs)o.recordMesgs&&this.buildRecords(o.recordMesgs);s.lapMesgs&&this.buildLaps(s.lapMesgs),this.buildSession(s),r++,this.buildActivityFromSession(s,i)}n.forEach(s=>this.buildEvent(s)),i.forEach(s=>this.buildActivity(s))}buildCourseContent(e){let t=e.sessionMesgs||[];if(t.length===0)throw new Error("Course file must contain track data");let r=t[0];if(this.buildCourse({name:"course",sport:this.options.defaultSport}),r.lapMesgs){let n=[];for(let o of r.lapMesgs)o.recordMesgs&&n.push(...o.recordMesgs);n.sort((o,a)=>o.timestamp&&a.timestamp?new Date(o.timestamp).getTime()-new Date(a.timestamp).getTime():(o.distance||0)-(a.distance||0));let i=n[0],s=n[n.length-1];i.timestamp&&this.buildEvent({timestamp:i.timestamp,event:"timer",eventType:"start",eventGroup:0}),n.forEach(o=>this.buildRecord(o)),s.timestamp&&this.buildEvent({timestamp:s.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),r.lapMesgs[0]&&this.buildLap(r.lapMesgs[0])}}buildFileId(e,t){var n;let r=((n=e.fileIdMesgs)==null?void 0:n[0])||{};this.writeMesg("file_id",{type:t,time_created:r.timeCreated?this.parseTimestamp(r.timeCreated):Date.now(),manufacturer:r.manufacturer,product:r.product,serial_number:r.serialNumber})}buildSession(e){var t;this.writeMesg("session",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,start_time:e.startTime?this.parseTimestamp(e.startTime):void 0,total_elapsed_time:e.totalElapsedTime,total_timer_time:e.totalTimerTime,start_position_lat:this.convertToSemicircles(e.startPositionLat),start_position_long:this.convertToSemicircles(e.startPositionLong),total_distance:e.totalDistance,total_ascent:e.totalAscent,total_descent:e.totalDescent,sport:e.sport||this.options.defaultSport,sub_sport:e.subSport||this.options.defaultSubSport,first_lap_index:e.firstLapIndex||0,num_laps:e.numLaps||((t=e.lapMesgs)==null?void 0:t.length)||1})}buildLaps(e){e.forEach(t=>this.buildLap(t))}buildLap(e){this.writeMesg("lap",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,start_time:e.startTime?this.parseTimestamp(e.startTime):void 0,start_position_lat:this.convertToSemicircles(e.startPositionLat),start_position_long:this.convertToSemicircles(e.startPositionLong),end_position_lat:this.convertToSemicircles(e.endPositionLat),end_position_long:this.convertToSemicircles(e.endPositionLong),total_elapsed_time:e.totalElapsedTime,total_timer_time:e.totalTimerTime,total_distance:e.totalDistance,total_ascent:e.totalAscent,total_descent:e.totalDescent})}buildRecords(e){e.forEach(t=>this.buildRecord(t))}buildRecord(e){this.writeMesg("record",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,position_lat:this.convertToSemicircles(e.positionLat),position_long:this.convertToSemicircles(e.positionLong),altitude:e.enhancedAltitude||e.altitude,distance:e.distance,heart_rate:e.heartRate,cadence:e.cadence,speed:e.enhancedSpeed||e.speed,power:e.power})}buildEvent(e){this.writeMesg("event",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,event:e.event,event_type:e.eventType,event_group:e.eventGroup})}buildActivity(e){this.writeMesg("activity",{timestamp:e.timestamp?this.parseTimestamp(e.timestamp):void 0,total_timer_time:e.totalTimerTime,num_sessions:e.numSessions,type:e.type,event:e.event,event_type:e.eventType,local_timestamp:e.localTimestamp?this.parseTimestamp(e.localTimestamp):void 0,event_group:e.eventGroup})}buildCourse(e){this.writeMesg("course",{name:e.name,sport:e.sport})}buildEventsFromLaps(e,t){e.forEach((r,n)=>{r.startTime&&t.push({timestamp:r.startTime,event:"timer",eventType:"start",eventGroup:n}),r.timestamp&&t.push({timestamp:r.timestamp,event:"timer",eventType:n===e.length-1?"stop_all":"stop",eventGroup:n})})}buildActivityFromSession(e,t){t.push({timestamp:e.timestamp,totalTimerTime:e.totalTimerTime,numSessions:1,type:e.sport||this.options.defaultSport,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(e){return typeof e=="number"?e:et(e).valueOf()}convertToSemicircles(e){if(e!=null)return Math.round(e*2**31/180)}validateRequiredFields(e){if(!e.sessionMesgs||e.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(e,t){let r=Object.fromEntries(Object.entries(t).filter(([o,a])=>a!==void 0));if(Object.keys(r).length===0)return;let n=this.localNum[e];n===void 0&&(n=this.localNum[e]=Object.keys(this.localNum).length);let i=new V(n,e,r),s=this.mesgDefn[n];(!s||!i.isSameDefn(s))&&(this.messages.push(i.defnRecord),this.mesgDefn[n]=i.mesgDefn),this.messages.push(i.dataRecord)}get blob(){let e=[this.header,...this.messages,this.trailer];return new Blob(e,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((e,t)=>e+t.byteLength,0)}get dataCrc(){return this.messages.reduce((e,t)=>Ie(t,e),0)}get header(){let e=new DataView(new ArrayBuffer(Oe));return e.setUint8(0,Oe),e.setUint8(1,tt),e.setUint16(2,rt,!0),e.setUint32(4,this.dataLen,!0),e.setUint32(8,nt),e.setUint16(12,Ie(e.buffer.slice(0,12)),!0),e.buffer}get trailer(){let e=new DataView(new ArrayBuffer(2));return e.setUint16(0,this.dataCrc,!0),e.buffer}async encoder(e){return this.encode(e)}};var y=class{constructor(){this.version="1.0.0";this.priority=100}supports(e){return this.supportedTags.includes(e)}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}parseFloat(e){if(!(typeof e>"u"))return typeof e=="number"?e:typeof e=="string"&&parseFloat(e)||0}parseInt(e){return typeof e=="number"?Math.floor(e):typeof e=="string"&&parseInt(e,10)||0}parseString(e){return String(e||"")}parseBoolean(e){return typeof e=="boolean"?e:typeof e=="string"?e.toLowerCase()==="true":!1}parseDate(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}hasRequiredAttributes(e,t){return t.every(r=>{var n;return(n=e.attributes)==null?void 0:n[r]})}extractAttributes(e,t,r){e.attributes&&Object.entries(e.attributes).forEach(([n,i])=>{let s=r[n];s&&s in t&&(t[s]=String(i||""))})}processChildren(e,t,r){var n;(n=e.children)==null||n.forEach(i=>{let s=r[i.tag];s&&s(i,t)})}getChildValue(e,t){var n;let r=(n=e.children)==null?void 0:n.find(i=>i.tag===t);return r!=null&&r.value?String(r.value):void 0}getChildByTag(e,t){var r;return(r=e.children)==null?void 0:r.find(n=>n.tag===t)}getChildrenByTag(e,t){var r;return((r=e.children)==null?void 0:r.filter(n=>n.tag===t))||[]}convertExtensions(e){var r;let t={};return(r=e.children)==null||r.forEach(n=>{t[n.tag]=this.convertExtensionContent(n)}),t}convertExtensionContent(e){var t;if((t=e.children)!=null&&t.length){let r={};return e.children.forEach(n=>{r[n.tag]=this.convertExtensionContent(n)}),r}else return e.value}},w=class{constructor(){this.version="1.0.0";this.description=""}async initialize(e){}async destroy(e){}async validate(e){return!0}async onTokenize(e,t){return e}async onAstGenerate(e,t){return e}async onConvert(e,t){return e}async onComplete(e,t){return e}async onError(e,t){}};var m=class extends y{parseCoordinate(e){let t=this.parseFloat(e);return t===0?void 0:t}parseGPXTime(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}extractNumericAttributes(e,t,r){e.attributes&&Object.entries(e.attributes).forEach(([n,i])=>{let s=r[n];s&&s in t&&typeof i<"u"&&(t[s]=this.parseFloat(i))})}},R=class extends w{async onError(e,t){t.warnings.push(`Middleware ${this.name} error: ${e.message}`)}};var z=class extends m{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(t,r){var i,s;if(!this.hasRequiredAttributes(t,["lat","lon"]))return;let n={lat:this.parseFloat((i=t.attributes)==null?void 0:i.lat),lon:this.parseFloat((s=t.attributes)==null?void 0:s.lon)};return this.processChildren(t,n,{ele:(o,a)=>a.ele=this.parseFloat(o.value),time:(o,a)=>a.time=new Date(this.parseString(o.value)),speed:(o,a)=>a.speed=this.parseFloat(o.value),power:(o,a)=>a.power=this.parseFloat(o.value),cadence:(o,a)=>a.cadence=this.parseFloat(o.value),heartRate:(o,a)=>a.heartRate=this.parseFloat(o.value),course:(o,a)=>a.course=this.parseFloat(o.value),name:(o,a)=>a.name=this.parseString(o.value),cmt:(o,a)=>a.cmt=this.parseString(o.value),desc:(o,a)=>a.desc=this.parseString(o.value),src:(o,a)=>a.src=this.parseString(o.value),sym:(o,a)=>a.sym=this.parseString(o.value),type:(o,a)=>a.type=this.parseString(o.value),fix:(o,a)=>a.fix=this.parseString(o.value),sat:(o,a)=>a.sat=this.parseString(o.value),hdop:(o,a)=>a.hdop=this.parseFloat(o.value),vdop:(o,a)=>a.vdop=this.parseFloat(o.value),pdop:(o,a)=>a.pdop=this.parseFloat(o.value),ageofdgpsdata:(o,a)=>a.ageofdgpsdata=this.parseFloat(o.value),geoidheight:(o,a)=>a.geoidheight=this.parseFloat(o.value),magvar:(o,a)=>a.magvar=this.parseFloat(o.value),dgpsid:(o,a)=>a.dgpsid=this.parseFloat(o.value),extensions:(o,a)=>{let p=r.metadata.get("decoder"),d=p==null?void 0:p.getConverter("extensions");if(d){let l=d.convert(o,r);l&&(this.mapExtensionsToPoint(l,a),a.extensions=l)}},link:(o,a)=>{var l;a.link||(a.link=[]);let p=r.metadata.get("decoder"),d=(l=p==null?void 0:p.getConverter("link"))==null?void 0:l.convert(o,r);d&&a.link&&a.link.push(d)}}),n}mapExtensionsToPoint(t,r){Object.entries(t).forEach(([n,i])=>{if(i!==void 0&&(typeof i=="string"||typeof i=="number")){let s=o=>(Array.isArray(o)?o:[o]).some(p=>{let d=n.toLowerCase(),l=p.toLowerCase();return d===l||d.endsWith(`:${l}`)});s("speed")?r.speed=this.parseFloat(i):s("hr")?r.heartRate=this.parseFloat(i):s(["cad","cadence"])?r.cadence=this.parseFloat(i):s(["PowerInWatts","power"])&&(r.power=this.parseFloat(i))}})}},U=class extends m{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(t,r){let n={rtept:[]};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),cmt:(i,s)=>s.cmt=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),src:(i,s)=>s.src=this.parseString(i.value),number:(i,s)=>s.number=this.parseFloat(i.value),type:(i,s)=>s.type=this.parseString(i.value),rtept:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("wpt"))==null?void 0:p.convert(i,r);a&&s.rtept&&s.rtept.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var a;s.link||(s.link=[]);let o=r.metadata.get("decoder");(a=i.children)==null||a.forEach(p=>{var l;let d=(l=o==null?void 0:o.getConverter("link"))==null?void 0:l.convert(p,r);d&&s.link&&s.link.push(d)})}}),n}},W=class extends m{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(t,r){let n={trkseg:[]};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),cmt:(i,s)=>s.cmt=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),src:(i,s)=>s.src=this.parseString(i.value),number:(i,s)=>s.number=this.parseFloat(i.value),type:(i,s)=>s.type=this.parseString(i.value),trkseg:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("trkseg"))==null?void 0:p.convert(i,r);a&&s.trkseg&&s.trkseg.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var a;s.link||(s.link=[]);let o=r.metadata.get("decoder");(a=i.children)==null||a.forEach(p=>{var l;let d=(l=o==null?void 0:o.getConverter("link"))==null?void 0:l.convert(p,r);d&&s.link&&s.link.push(d)})}}),n}},j=class extends m{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(t,r){let n={trkpt:[]};return this.processChildren(t,n,{trkpt:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("wpt"))==null?void 0:p.convert(i,r);a&&s.trkpt&&s.trkpt.push(a)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))}}),n}},K=class extends m{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(t,r){var i;let n={};return(i=t.attributes)!=null&&i.href&&(n.href=t.attributes.href),this.processChildren(t,n,{text:(s,o)=>o.text=this.parseString(s.value),type:(s,o)=>o.type=this.parseString(s.value)}),n}},Y=class extends m{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(t,r){let n={};return this.processChildren(t,n,{name:(i,s)=>s.name=this.parseString(i.value),desc:(i,s)=>s.desc=this.parseString(i.value),keywords:(i,s)=>s.keywords=this.parseString(i.value),time:(i,s)=>s.time=new Date(this.parseString(i.value)),author:(i,s)=>{var a;let o=r.metadata.get("decoder");s.author=(a=o==null?void 0:o.getConverter("author"))==null?void 0:a.convert(i,r)},copyright:(i,s)=>{var a;let o=r.metadata.get("decoder");s.copyright=(a=o==null?void 0:o.getConverter("copyright"))==null?void 0:a.convert(i,r)},bounds:(i,s)=>{var a;let o=r.metadata.get("decoder");s.bounds=(a=o==null?void 0:o.getConverter("bounds"))==null?void 0:a.convert(i,r)},extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("extensions");a&&(s.extensions=a.convert(i,r))},link:(i,s)=>{var p;s.link||(s.link=[]);let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("link"))==null?void 0:p.convert(i,r);a&&s.link&&s.link.push(a)}}),n}},N=class extends m{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(t,r){var i;let n={};return t.value&&!((i=t.children)!=null&&i.length)?(n.name=this.parseString(t.value),n):(this.processChildren(t,n,{name:(s,o)=>o.name=this.parseString(s.value),email:(s,o)=>{var p;let a=r.metadata.get("decoder");o.email=(p=a==null?void 0:a.getConverter("email"))==null?void 0:p.convert(s,r)},link:(s,o)=>{var p;let a=r.metadata.get("decoder");o.link=(p=a==null?void 0:a.getConverter("link"))==null?void 0:p.convert(s,r)}}),n)}},Z=class extends m{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(t,r){let n={};return this.processChildren(t,n,{id:(i,s)=>s.id=this.parseString(i.value),domain:(i,s)=>s.domain=this.parseString(i.value)}),n}},q=class extends m{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(t,r){var i;let n={};return(i=t.attributes)!=null&&i.author&&(n.author=t.attributes.author),this.processChildren(t,n,{year:(s,o)=>o.year=this.parseString(s.value),license:(s,o)=>o.license=this.parseString(s.value)}),n}},J=class extends m{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(t,r){let n={};return this.extractAttributes(t,n,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),n}},Q=class extends m{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(t,r){var i;let n={};return(i=t.children)==null||i.forEach(s=>{this.flattenExtensionElement(s,n)}),n}flattenExtensionElement(t,r){var n,i;if(!((n=t.children)!=null&&n.length)&&t.value!==void 0){r[t.tag]=this.parseExtensionValue(t.value);return}(i=t.children)!=null&&i.length&&t.children.forEach(s=>{this.flattenExtensionElement(s,r)})}parseExtensionValue(t){if(t===void 0)return;let r=String(t),n=parseFloat(r);return!isNaN(n)&&isFinite(n)?n:r}};import{Parser as it}from"htmlparser2";var ie=(n=>(n.TOKENIZE="tokenize",n.AST_GENERATE="ast_generate",n.CONVERT="convert",n.COMPLETE="complete",n))(ie||{}),ee=class{constructor(){this.stage="tokenize"}async process(e){let t=Date.now();if(!e.xmlContent)throw new Error("XML content cannot be empty");let r=[],n=new it({onopentag(i,s){r.push({type:"open",tag:i,attributes:s})},ontext(i){let s=i.replace(/\n/g,"").trim();s&&r.push({type:"text",tag:"text",value:s})},onclosetag(i){r.push({type:"close",tag:i})}},{xmlMode:!0});return n.write(e.xmlContent),n.end(),e.tokens=r,e.performance.tokenizeTime=Date.now()-t,e}},te=class{constructor(){this.stage="ast_generate"}async process(e){var s;let t=Date.now();if(!e.tokens)throw new Error("Tokens cannot be empty");let r=[],n,i=null;for(let o of e.tokens)if(o.type==="open"){let a={tag:o.tag,attributes:o.attributes||{},children:[]};n?i&&((s=i.children)==null||s.push(a)):n=a,r.push(a),i=a}else o.type==="text"&&i?i.value=o.value:o.type==="close"&&(r.pop(),i=r[r.length-1]||null);return e.ast=n,e.performance.astTime=Date.now()-t,e}},re=class{constructor(e){this.getConverter=e;this.stage="convert"}async process(e){var n;let t=Date.now();if(!e.ast)throw new Error("AST cannot be empty");let r={};return e.ast.attributes&&Object.entries(e.ast.attributes).forEach(([i,s])=>{i.startsWith("xmlns:")?r[i]=s.replace(/'/g,"'"):i==="xsi:schemaLocation"?r[i]=s.replace(/'/g,"'"):r[i]=s}),(n=e.ast.children)==null||n.forEach(i=>{let s=this.getConverter(i.tag);try{let o=s.convert(i,e);o&&this.assignResult(r,i.tag,o)}catch(o){e.errors.push(o)}}),e.result=r,e.performance.convertTime=Date.now()-t,e}assignResult(e,t,r){switch(t){case"metadata":e.metadata=r;break;case"wpt":e.wpt||(e.wpt=[]),e.wpt.push(r);break;case"rte":e.rte||(e.rte=[]),e.rte.push(r);break;case"trk":e.trk||(e.trk=[]),e.trk.push(r);break;case"extensions":e.extensions=r;break}}},ne=class{constructor(){this.stage="complete"}async process(e){e.performance.endTime=Date.now();let t=e.performance.endTime-e.performance.startTime;return e.metadata.set("performance",{totalTime:t,tokenizeTime:e.performance.tokenizeTime,astTime:e.performance.astTime,convertTime:e.performance.convertTime}),e}};var E=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 ee,new te,new re(e=>this.getConverter(e)),new ne]}async registerDefaultConverters(){var t;if(this.defaultConvertersRegistered)return;let e=[new z,new U,new W,new j,new K,new Y,new N,new Z,new q,new J,new Q];for(let r of e)(t=r.supportedTags)==null||t.forEach(n=>{this.addConverterForTag(n,r)}),this.registeredPlugins.add(r.name);this.defaultConvertersRegistered=!0}addConverterForTag(e,t){this.converterPlugins.has(e)||this.converterPlugins.set(e,[]);let r=this.converterPlugins.get(e);r.push(t),r.sort((n,i)=>(n.priority||100)-(i.priority||100))}async registerConverter(e){var r,i;if(this.registeredPlugins.has(e.name))throw new Error(`Converter plugin ${e.name} already exists`);(r=e.supportedTags)==null||r.forEach(s=>{this.addConverterForTag(s,e)}),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:"";(i=e.supportedTags)==null||i.forEach(s=>{let a=(this.converterPlugins.get(s)||[]).map(p=>`${p.name}(${p.priority||100})`)})}async registerMiddleware(e){let t=this.middlewarePlugins.findIndex(n=>n.name===e.name);t!==-1?this.middlewarePlugins[t]=e:this.middlewarePlugins.push(e);let r=[];e.onTokenize&&r.push("onTokenize"),e.onAstGenerate&&r.push("onAstGenerate"),e.onConvert&&r.push("onConvert"),e.onComplete&&r.push("onComplete"),e.onError&&r.push("onError"),r.length>0}getConverter(e){let t=this.converterPlugins.get(e);return t&&t.length>0?t[0]:void 0}getAllConverters(e){return this.converterPlugins.get(e)||[]}unregisterConverter(e){let t;for(let[r,n]of this.converterPlugins){let i=n.findIndex(s=>s.name===e);i!==-1&&(t=n[i],n.splice(i,1),n.length===0&&this.converterPlugins.delete(r))}t&&this.registeredPlugins.delete(e)}unregisterMiddleware(e){let t=this.middlewarePlugins.findIndex(r=>r.name===e);t!==-1&&this.middlewarePlugins.splice(t,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(e=>e.name)}listProcessors(){return this.processors.map(e=>e.constructor.name)}getConverterDetails(e){let t={};if(e){let r=this.converterPlugins.get(e);r&&(t[e]=r.map(n=>({name:n.name,priority:n.priority||100})))}else for(let[r,n]of this.converterPlugins)t[r]=n.map(i=>({name:i.name,priority:i.priority||100}));return t}getMiddlewareDetails(){return this.middlewarePlugins.map(e=>{let t=[];return e.onTokenize&&t.push("onTokenize"),e.onAstGenerate&&t.push("onAstGenerate"),e.onConvert&&t.push("onConvert"),e.onComplete&&t.push("onComplete"),e.onError&&t.push("onError"),{name:e.name,hooks:t}})}async initialize(){var r;if(this.initialized)return;await this.registerDefaultConverters();let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.initialize)==null?void 0:r.call(n,e))}catch{}this.initialized=!0}async destroy(){var r;if(!this.initialized)return;let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.destroy)==null?void 0:r.call(n,e))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(e,t,r){var i;let n=t;for(let s of this.middlewarePlugins){let o=s[e];if(o)try{n=await o.call(s,n,r)||n}catch(a){r.errors.push(a),await((i=s.onError)==null?void 0:i.call(s,a,r))}}return n}async parserByBuffer(e){var r;await this.initialize();let t=this.createContext();t.rawData=e,t.xmlContent=e.toString("utf-8"),t.metadata.set("decoder",this);try{for(let n of this.processors)try{switch(t=await n.process(t),n.stage){case"tokenize":t.tokens&&(t.tokens=await this.executeMiddlewareHook("onTokenize",t.tokens,t));break;case"ast_generate":t.ast&&(t.ast=await this.executeMiddlewareHook("onAstGenerate",t.ast,t));break;case"convert":t.result&&(t.result=await this.executeMiddlewareHook("onConvert",t.result,t));break;case"complete":t.result&&(t.result=await this.executeMiddlewareHook("onComplete",t.result,t));break}}catch(i){t.errors.push(i);for(let s of this.middlewarePlugins)await((r=s.onError)==null?void 0:r.call(s,i,t))}return t.result}catch(n){throw n}}convertExtensions(e){var s,o;let t={},{attributes:r,tag:n,value:i}=e;if(r&&Object.entries(r).forEach(([a,p])=>{t[a]=p}),(s=e==null?void 0:e.children)!=null&&s.length)(o=e.children)==null||o.forEach(a=>{t[a.tag]=this.convertExtensions(a)});else if(i!==void 0)return i;return t}};import $e from"dayjs";import st from"dayjs/plugin/utc.js";var Ae={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var ke={temperature:"Temperature",Depth:"Depth"};$e.extend(st);var b=class{constructor(e={}){this.formatElevation=e=>{let t=parseFloat(e);return isNaN(t)?e:this.roundTo(t,2).toString()};this.compact=e.compact??!0}async encode(e){let t=this.buildGPXXML(e);return Buffer.from(t,"utf-8")}encodeToString(e){return this.buildGPXXML(e)}buildGPXXML(e){let t=this.buildXMLHeader(),r=this.buildGPXContent(e),i=`${t}${r}
|
|
2
2
|
</gpx>`;return this.compact?this.compressXML(i):i}compressXML(e){return e.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(){return['<?xml version="1.0" encoding="UTF-8"?>','<gpx creator="https://gpxonline.net" version="1.1"',' 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(e){let{metadata:t,wpt:r=[],rte:n=[],trk:i=[]}=e,s=[];return t&&s.push(this.buildMetadata(t)),r.forEach(o=>{s.push(this.buildWaypoint(o,"wpt"))}),n.forEach(o=>{s.push(this.buildRoute(o))}),i.forEach(o=>{s.push(this.buildTrack(o))}),s.join(`
|
|
4
4
|
`)}buildMetadata(e){let t=["<metadata>"];return this.addOptionalElement(t,"name",e.name),this.addOptionalElement(t,"desc",e.desc),e.author&&t.push(this.buildAuthor(e.author)),e.copyright&&t.push(this.buildCopyright(e.copyright)),e.link&&this.addLinks(t,e.link),e.time&&t.push(this.buildTimeElement(e.time)),this.addOptionalElement(t,"keywords",e.keywords),e.bounds&&t.push(this.buildBounds(e.bounds)),e.extensions&&t.push(this.buildExtensions(e.extensions)),t.push("</metadata>"),t.join(`
|
|
5
5
|
`)}buildAuthor(e){let t=["<author>"];return this.addOptionalElement(t,"name",e.name),e.email&&t.push(`<email id="${this.escapeXML(e.email.id||"")}" domain="${this.escapeXML(e.email.domain||"")}"/>`),e.link&&t.push(this.buildLink(e.link)),t.push("</author>"),t.join(`
|
|
6
6
|
`)}buildCopyright(e){let t=[`<copyright author="${this.escapeXML(e.author||"")}">`];return this.addOptionalElement(t,"year",e.year),this.addOptionalElement(t,"license",e.license),t.push("</copyright>"),t.join(`
|
|
7
7
|
`)}buildBounds(e){let t=this.escapeXMLAttribute((e.minlat||0).toString()),r=this.escapeXMLAttribute((e.minlon||0).toString()),n=this.escapeXMLAttribute((e.maxlat||0).toString()),i=this.escapeXMLAttribute((e.maxlon||0).toString());return`<bounds minlat="${t}" minlon="${r}" maxlat="${n}" maxlon="${i}"/>`}buildWaypoint(e,t){var n,i,s;if(!this.isValidCoordinate(e.lat,e.lon))return"";let r=[`<${t} lat="${this.escapeXMLAttribute(this.formatCoordinate(e.lat))}" lon="${this.escapeXMLAttribute(this.formatCoordinate(e.lon))}">`];if(this.addOptionalElement(r,"ele",(n=e.ele)==null?void 0:n.toString(),this.formatElevation),e.time&&r.push(this.buildTimeElement(e.time)),this.addOptionalElement(r,"speed",(i=e.speed)==null?void 0:i.toString()),this.addOptionalElement(r,"course",(s=e.course)==null?void 0:s.toString()),this.addStandardWaypointElements(r,e),e.extensions){let o=this.processPointExtensions(e,e.extensions);Object.keys(o).length>0&&r.push(this.buildExtensions(o))}return r.push(`</${t}>`),r.join(`
|
|
8
|
-
`)}addStandardWaypointElements(e,t){var r,n,i,s,o,a,
|
|
8
|
+
`)}addStandardWaypointElements(e,t){var r,n,i,s,o,a,p;this.addOptionalElement(e,"magvar",(r=t.magvar)==null?void 0:r.toString()),this.addOptionalElement(e,"geoidheight",(n=t.geoidheight)==null?void 0:n.toString()),this.addOptionalElement(e,"name",t.name),this.addOptionalElement(e,"cmt",t.cmt),this.addOptionalElement(e,"desc",t.desc),this.addOptionalElement(e,"src",t.src),t.link&&this.addLinks(e,t.link),this.addOptionalElement(e,"sym",t.sym),this.addOptionalElement(e,"type",t.type),this.addOptionalElement(e,"fix",t.fix),this.addOptionalElement(e,"sat",t.sat),this.addOptionalElement(e,"hdop",(i=t.hdop)==null?void 0:i.toString()),this.addOptionalElement(e,"vdop",(s=t.vdop)==null?void 0:s.toString()),this.addOptionalElement(e,"pdop",(o=t.pdop)==null?void 0:o.toString()),this.addOptionalElement(e,"ageofdgpsdata",(a=t.ageofdgpsdata)==null?void 0:a.toString()),this.addOptionalElement(e,"dgpsid",(p=t.dgpsid)==null?void 0:p.toString())}buildRoute(e){var r;let t=["<rte>"];return this.addRouteTrackCommonElements(t,e),e.rtept&&((r=e.rtept)==null||r.forEach(n=>{t.push(this.buildWaypoint(n,"rtept"))})),e.extensions&&t.push(this.buildExtensions(e.extensions)),t.push("</rte>"),t.join(`
|
|
9
9
|
`)}buildTrack(e){let t=["<trk>"];return this.addRouteTrackCommonElements(t,e),e.trkseg&&e.trkseg.forEach(r=>{t.push(this.buildTrackSegment(r))}),e.extensions&&t.push(this.buildExtensions(e.extensions)),t.push("</trk>"),t.join(`
|
|
10
10
|
`)}buildTrackSegment(e){let t=["<trkseg>"];return e.trkpt&&e.trkpt.forEach(r=>{t.push(this.buildWaypoint(r,"trkpt"))}),e.extensions&&t.push(this.buildExtensions(e.extensions)),t.push("</trkseg>"),t.join(`
|
|
11
|
-
`)}addRouteTrackCommonElements(e,t){var r;this.addOptionalElement(e,"name",t.name),this.addOptionalElement(e,"cmt",t.cmt),this.addOptionalElement(e,"desc",t.desc),this.addOptionalElement(e,"src",t.src),t.link&&this.addLinks(e,t.link),this.addOptionalElement(e,"number",(r=t.number)==null?void 0:r.toString()),this.addOptionalElement(e,"type",t.type)}processPointExtensions(e,t){let r={};return Object.entries({"gpxtpx:TrackPointExtension":{"gpxtpx:hr":"heartRate","gpxtpx:cad":"cadence","gpxtpx:speed":"speed","gpxtpx:atemp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:temp":"temperature"},"gpxpx:PowerExtension":{"gpxpx:PowerInWatts":"power"},"gpxx:GpxExtensions":{"gpxx:Temperature":"temperature","gpxx:Depth":"depth"}}).forEach(([i,s])=>{let o={},a=!1;Object.entries(s).forEach(([c,d])=>{let l;if(e[d]!==void 0)l=e[d];else if(t)if(t[c]!==void 0)l=t[c];else{let u=c.split(":").pop();Object.entries(t).forEach(([T,g])=>{T.endsWith(`:${u}`)&&g!==void 0&&(l=g)})}l!==void 0&&(o[c]=l,a=!0)}),a&&(r[i]=o)}),r}buildTrackPointExtension(e,t){let r=this.deepClone(t["gpxtpx:TrackPointExtension"]||{}),n=Object.keys(_e);return Object.keys(e).filter(i=>n.includes(i)).forEach(i=>{let s=_e[i];s&&e[i]!==void 0&&(r[`gpxtpx:${s}`]=e[i])}),r}buildPowerExtension(e,t){return this.deepClone(t["gpxpx:PowerExtension"]||{})}buildGpxExtensions(e,t){let r=this.deepClone(t["gpxx:GpxExtensions"]||{}),n=Object.keys(De);return Object.keys(e).filter(i=>n.includes(i)).forEach(i=>{let s=De[i];s&&e[i]!==void 0&&(r[`gpxx:${s}`]=e[i])}),r}buildExtensions(e){let t=this.buildExtensionContent(e);return t?`<extensions>${t}</extensions>`:""}buildExtensionContent(e){return Object.entries(e).filter(([t])=>!t.startsWith("xmlns")).map(([t,r])=>{if(r&&typeof r=="object"){let n=this.buildExtensionContent(r);return`<${t}>${n}</${t}>`}else if(r!=null)return`<${t}>${this.escapeXML(String(r))}</${t}>`;return""}).filter(t=>t).join("")}buildLink(e){let t=[`<link href="${this.escapeXMLAttribute(e.href||"")}">`];return this.addOptionalElement(t,"text",e.text),this.addOptionalElement(t,"type",e.type),t.push("</link>"),t.join("")}addLinks(e,t){(Array.isArray(t)?t:[t]).forEach(n=>{e.push(this.buildLink(n))})}buildTimeElement(e){return typeof e=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(e)?`<time>${e}</time>`:`<time>${Ue(e).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(e,t,r,n){if(r!=null&&r!==""){let i=n?n(r):this.escapeXML(r);e.push(`<${t}>${i}</${t}>`)}}isValidCoordinate(e,t){return e!=null&&t!==void 0&&t!==null&&!isNaN(e)&&!isNaN(t)}formatCoordinate(e){return this.roundTo(e,6).toString()}roundTo(e,t){let r=Math.pow(10,t);return Math.round(e*r)/r}escapeXML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}escapeXMLAttribute(e){return typeof e!="string"?String(e||""):e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/\r/g," ").replace(/\n/g," ").replace(/\t/g,"	")}deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(r=>this.deepClone(r));let t={};for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=this.deepClone(e[r]));return t}encoder(e){return this.encode(e)}};var Xe=class extends _{constructor(){super(...arguments);this.name="performance-middleware";this.description="Monitor parsing performance"}async onTokenize(t,r){return t}async onAstGenerate(t,r){let n=this.countNodes(t);return t}async onComplete(t,r){let n=r.metadata.get("performance");return t}countNodes(t){let r=1;if(t.children)for(let n of t.children)r+=this.countNodes(n);return r}},Re=class extends _{constructor(){super(...arguments);this.name="validation-middleware";this.description="Validate GPX data integrity"}async onComplete(t,r){let n=this.validateGPX(t);return n.length>0&&r.metadata.set("validation-errors",n),t}validateGPX(t){let r=[];if(t.version||r.push("Missing GPX version information"),t.creator||r.push("Missing GPX creator information"),t.trk){for(let n of t.trk)if(n.trkseg){for(let i of n.trkseg)if(i.trkpt)for(let s of i.trkpt)(typeof s.lat!="number"||typeof s.lon!="number")&&r.push("Invalid track point coordinates")}}return r}};async function ut(p){let e=[new Xe,new Re];for(let t of e)await p.registerMiddleware(t)}var f=class extends y{parseHeartRate(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>0&&t<300?t:void 0}parseTCXTime(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}parseDistance(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>0?t:void 0}parseSpeed(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>=0?t:void 0}parseAltitude(e){return this.parseFloat(e)}parseCoordinate(e){let t=this.parseFloat(e);return t!==0?t:void 0}},E=class extends C{async onError(e,t){t.warnings.push(`Middleware ${this.name} error: ${e.message}`)}};var se=class extends f{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(t,r){let n={};return this.processChildren(t,n,{LatitudeDegrees:(i,s)=>s.LatitudeDegrees=this.parseString(i.value),LongitudeDegrees:(i,s)=>s.LongitudeDegrees=this.parseString(i.value)}),n}},oe=class extends f{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(t,r){let n={};return this.processChildren(t,n,{Time:(i,s)=>s.Time=this.parseString(i.value),Position:(i,s)=>{var a;let o=r.metadata.get("decoder");s.Position=(a=o==null?void 0:o.getConverter("Position"))==null?void 0:a.convert(i,r)},AltitudeMeters:(i,s)=>s.AltitudeMeters=this.parseFloat(i.value),DistanceMeters:(i,s)=>s.DistanceMeters=this.parseFloat(i.value),HeartRateBpm:(i,s)=>{if(i.value)s.HeartRateBpm=this.parseFloat(i.value);else{let o=this.getChildByTag(i,"Value");o!=null&&o.value&&(s.HeartRateBpm=this.parseFloat(o.value))}},Cadence:(i,s)=>{let o={Low:0,High:0};this.processChildren(i,o,{Low:(a,c)=>c.Low=this.parseFloat(a.value)||0,High:(a,c)=>c.High=this.parseFloat(a.value)||0}),s.Cadence=o},SensorState:(i,s)=>s.SensorState=i.value,Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}},ae=class extends f{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(t,r){let n={Trackpoint:[]};return this.processChildren(t,n,{Trackpoint:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("Trackpoint"))==null?void 0:c.convert(i,r);a&&s.Trackpoint&&s.Trackpoint.push(a)}}),n}},pe=class extends f{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(t,r){let n={};return this.extractAttributes(t,n,{StartTime:"Id"}),this.processChildren(t,n,{TotalTimeSeconds:(i,s)=>s.TotalTimeSeconds=this.parseFloat(i.value),DistanceMeters:(i,s)=>s.DistanceMeters=this.parseFloat(i.value),MaximumSpeed:(i,s)=>s.MaximumSpeed=this.parseFloat(i.value),Calories:(i,s)=>s.Calories=this.parseFloat(i.value),AverageHeartRateBpm:(i,s)=>s.AverageHeartRateBpm=this.parseFloat(i.value),MaximumHeartRateBpm:(i,s)=>s.MaximumHeartRateBpm=this.parseFloat(i.value),Intensity:(i,s)=>s.Intensity=i.value,TriggerMethod:(i,s)=>s.TriggerMethod=i.value,Track:(i,s)=>{var c;s.Track||(s.Track=[]);let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("Track"))==null?void 0:c.convert(i,r);a&&s.Track.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value),Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}},ce=class extends f{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(t,r){let n={Id:"",Lap:[]};return this.extractAttributes(t,n,{Sport:"Sport"}),this.processChildren(t,n,{Id:(i,s)=>s.Id=this.parseString(i.value),Lap:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("Lap"))==null?void 0:c.convert(i,r);a&&s.Lap.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value),Training:(i,s)=>s.Training=this.convertTraining(i),Creator:(i,s)=>s.Creator=this.convertCreator(i),Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}convertTraining(t){var n;let r={};return t.attributes&&Object.entries(t.attributes).forEach(([i,s])=>{r[i]=s}),(n=t.children)==null||n.forEach(i=>{r[i.tag]=this.convertExtensionContent(i)}),r}convertCreator(t){var n;let r={};return(n=t.children)==null||n.forEach(i=>{r[i.tag]=this.convertExtensionContent(i)}),r}},de=class extends f{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(t,r){let n={Activity:[],MultiSportSession:[]};return this.processChildren(t,n,{Activity:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("Activity"))==null?void 0:c.convert(i,r);a&&s.Activity&&s.Activity.push(a)},MultiSportSession:(i,s)=>{var c;let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("MultiSportSession"))==null?void 0:c.convert(i,r);a&&s.MultiSportSession&&s.MultiSportSession.push(a)}}),n}},le=class extends f{constructor(){super(...arguments);this.name="MultiSportSessionConverter";this.supportedTags=["MultiSportSession"]}convert(t,r){let n={};return this.processChildren(t,n,{Id:(i,s)=>s.Id=this.parseString(i.value),FirstSport:(i,s)=>{var a;let o=r.metadata.get("decoder");s.FirstSport=(a=o==null?void 0:o.getConverter("FirstSport"))==null?void 0:a.convert(i,r)},NextSport:(i,s)=>{var c;s.NextSport||(s.NextSport=[]);let o=r.metadata.get("decoder"),a=(c=o==null?void 0:o.getConverter("NextSport"))==null?void 0:c.convert(i,r);a&&s.NextSport.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value)}),n}},ue=class extends f{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(t,r){let n={};return this.processChildren(t,n,{Name:(i,s)=>s.Name=this.parseString(i.value)}),n}},me=class extends f{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(t,r){let n={};return this.flattenExtensionElement(t,n),n}flattenExtensionElement(t,r){var n,i;if(!((n=t.children)!=null&&n.length)&&t.value!==void 0){r[t.tag]=this.parseExtensionValue(t.value);return}(i=t.children)!=null&&i.length&&t.children.forEach(s=>{this.flattenExtensionElement(s,r)})}parseExtensionValue(t){if(t===void 0)return;let r=String(t),n=parseFloat(r);return!isNaN(n)&&isFinite(n)?n:r}};import{Parser as We}from"htmlparser2";var Te=class{static tokenizeXML(e){let t=[],r=new We({onopentag(n,i){t.push({type:"open",tag:n,attributes:i})},ontext(n){let i=n.replace(/\n/g,"").trim();i&&t.push({type:"text",tag:"text",value:i})},onclosetag(n){t.push({type:"close",tag:n})}},{xmlMode:!0});return r.write(e),r.end(),t}static compressXML(e){return e.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(e,t=2){let r=" ".repeat(t),n="",i=0,s=!1;for(let o=0;o<e.length;o++){let a=e[o],c=e[o+1];a==="<"?(c==="/"?(i--,s||(n+=`
|
|
12
|
-
`+r.repeat(i))):
|
|
13
|
-
`+r.repeat(i)),i++),s=!0):a===">"&&(s=!1,
|
|
11
|
+
`)}addRouteTrackCommonElements(e,t){var r;this.addOptionalElement(e,"name",t.name),this.addOptionalElement(e,"cmt",t.cmt),this.addOptionalElement(e,"desc",t.desc),this.addOptionalElement(e,"src",t.src),t.link&&this.addLinks(e,t.link),this.addOptionalElement(e,"number",(r=t.number)==null?void 0:r.toString()),this.addOptionalElement(e,"type",t.type)}processPointExtensions(e,t){let r={};return Object.entries({"gpxtpx:TrackPointExtension":{"gpxtpx:hr":"heartRate","gpxtpx:cad":"cadence","gpxtpx:speed":"speed","gpxtpx:atemp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:temp":"temperature"},"gpxpx:PowerExtension":{"gpxpx:PowerInWatts":"power"},"gpxx:GpxExtensions":{"gpxx:Temperature":"temperature","gpxx:Depth":"depth"}}).forEach(([i,s])=>{let o={},a=!1;Object.entries(s).forEach(([p,d])=>{let l;if(e[d]!==void 0)l=e[d];else if(t)if(t[p]!==void 0)l=t[p];else{let u=p.split(":").pop();Object.entries(t).forEach(([T,g])=>{T.endsWith(`:${u}`)&&g!==void 0&&(l=g)})}l!==void 0&&(o[p]=l,a=!0)}),a&&(r[i]=o)}),r}buildTrackPointExtension(e,t){let r=this.deepClone(t["gpxtpx:TrackPointExtension"]||{}),n=Object.keys(Ae);return Object.keys(e).filter(i=>n.includes(i)).forEach(i=>{let s=Ae[i];s&&e[i]!==void 0&&(r[`gpxtpx:${s}`]=e[i])}),r}buildPowerExtension(e,t){return this.deepClone(t["gpxpx:PowerExtension"]||{})}buildGpxExtensions(e,t){let r=this.deepClone(t["gpxx:GpxExtensions"]||{}),n=Object.keys(ke);return Object.keys(e).filter(i=>n.includes(i)).forEach(i=>{let s=ke[i];s&&e[i]!==void 0&&(r[`gpxx:${s}`]=e[i])}),r}buildExtensions(e){let t=this.buildExtensionContent(e);return t?`<extensions>${t}</extensions>`:""}buildExtensionContent(e){return Object.entries(e).filter(([t])=>!t.startsWith("xmlns")).map(([t,r])=>{if(r&&typeof r=="object"){let n=this.buildExtensionContent(r);return`<${t}>${n}</${t}>`}else if(r!=null)return`<${t}>${this.escapeXML(String(r))}</${t}>`;return""}).filter(t=>t).join("")}buildLink(e){let t=[`<link href="${this.escapeXMLAttribute(e.href||"")}">`];return this.addOptionalElement(t,"text",e.text),this.addOptionalElement(t,"type",e.type),t.push("</link>"),t.join("")}addLinks(e,t){(Array.isArray(t)?t:[t]).forEach(n=>{e.push(this.buildLink(n))})}buildTimeElement(e){return typeof e=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(e)?`<time>${e}</time>`:`<time>${$e(e).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(e,t,r,n){if(r!=null&&r!==""){let i=n?n(r):this.escapeXML(r);e.push(`<${t}>${i}</${t}>`)}}isValidCoordinate(e,t){return e!=null&&t!==void 0&&t!==null&&!isNaN(e)&&!isNaN(t)}formatCoordinate(e){return this.roundTo(e,6).toString()}roundTo(e,t){let r=Math.pow(10,t);return Math.round(e*r)/r}escapeXML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}escapeXMLAttribute(e){return typeof e!="string"?String(e||""):e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/\r/g," ").replace(/\n/g," ").replace(/\t/g,"	")}deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(r=>this.deepClone(r));let t={};for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=this.deepClone(e[r]));return t}encoder(e){return this.encode(e)}};var Fe=class extends R{constructor(){super(...arguments);this.name="performance-middleware";this.description="Monitor parsing performance"}async onTokenize(t,r){return t}async onAstGenerate(t,r){let n=this.countNodes(t);return t}async onComplete(t,r){let n=r.metadata.get("performance");return t}countNodes(t){let r=1;if(t.children)for(let n of t.children)r+=this.countNodes(n);return r}},_e=class extends R{constructor(){super(...arguments);this.name="validation-middleware";this.description="Validate GPX data integrity"}async onComplete(t,r){let n=this.validateGPX(t);return n.length>0&&r.metadata.set("validation-errors",n),t}validateGPX(t){let r=[];if(t.version||r.push("Missing GPX version information"),t.creator||r.push("Missing GPX creator information"),t.trk){for(let n of t.trk)if(n.trkseg){for(let i of n.trkseg)if(i.trkpt)for(let s of i.trkpt)(typeof s.lat!="number"||typeof s.lon!="number")&&r.push("Invalid track point coordinates")}}return r}};async function Ge(c){let e=[new Fe,new _e];for(let t of e)await c.registerMiddleware(t)}var f=class extends y{parseHeartRate(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>0&&t<300?t:void 0}parseTCXTime(e){if(!e)return;let t=new Date(e);return isNaN(t.getTime())?void 0:t}parseDistance(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>0?t:void 0}parseSpeed(e){let t=this.parseFloat(e);if(!(typeof t>"u"))return t>=0?t:void 0}parseAltitude(e){return this.parseFloat(e)}parseCoordinate(e){let t=this.parseFloat(e);return t!==0?t:void 0}};var se=class extends f{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(t,r){let n={};return this.processChildren(t,n,{LatitudeDegrees:(i,s)=>s.LatitudeDegrees=this.parseString(i.value),LongitudeDegrees:(i,s)=>s.LongitudeDegrees=this.parseString(i.value)}),n}},oe=class extends f{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(t,r){let n={};return this.processChildren(t,n,{Time:(i,s)=>s.Time=this.parseString(i.value),Position:(i,s)=>{var a;let o=r.metadata.get("decoder");s.Position=(a=o==null?void 0:o.getConverter("Position"))==null?void 0:a.convert(i,r)},AltitudeMeters:(i,s)=>s.AltitudeMeters=this.parseFloat(i.value),DistanceMeters:(i,s)=>s.DistanceMeters=this.parseFloat(i.value),HeartRateBpm:(i,s)=>{if(i.value)s.HeartRateBpm=this.parseFloat(i.value);else{let o=this.getChildByTag(i,"Value");o!=null&&o.value&&(s.HeartRateBpm=this.parseFloat(o.value))}},Cadence:(i,s)=>{let o={Low:0,High:0};this.processChildren(i,o,{Low:(a,p)=>p.Low=this.parseFloat(a.value)||0,High:(a,p)=>p.High=this.parseFloat(a.value)||0}),s.Cadence=o},SensorState:(i,s)=>s.SensorState=i.value,Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}},ae=class extends f{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(t,r){let n={Trackpoint:[]};return this.processChildren(t,n,{Trackpoint:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("Trackpoint"))==null?void 0:p.convert(i,r);a&&s.Trackpoint&&s.Trackpoint.push(a)}}),n}},ce=class extends f{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(t,r){let n={};return this.extractAttributes(t,n,{StartTime:"Id"}),this.processChildren(t,n,{TotalTimeSeconds:(i,s)=>s.TotalTimeSeconds=this.parseFloat(i.value),DistanceMeters:(i,s)=>s.DistanceMeters=this.parseFloat(i.value),MaximumSpeed:(i,s)=>s.MaximumSpeed=this.parseFloat(i.value),Calories:(i,s)=>s.Calories=this.parseFloat(i.value),AverageHeartRateBpm:(i,s)=>s.AverageHeartRateBpm=this.parseFloat(i.value),MaximumHeartRateBpm:(i,s)=>s.MaximumHeartRateBpm=this.parseFloat(i.value),Intensity:(i,s)=>s.Intensity=i.value,TriggerMethod:(i,s)=>s.TriggerMethod=i.value,Track:(i,s)=>{var p;s.Track||(s.Track=[]);let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("Track"))==null?void 0:p.convert(i,r);a&&s.Track.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value),Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}},pe=class extends f{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(t,r){let n={Id:"",Lap:[]};return this.extractAttributes(t,n,{Sport:"Sport"}),this.processChildren(t,n,{Id:(i,s)=>s.Id=this.parseString(i.value),Lap:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("Lap"))==null?void 0:p.convert(i,r);a&&s.Lap.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value),Training:(i,s)=>s.Training=this.convertTraining(i),Creator:(i,s)=>s.Creator=this.convertCreator(i),Extensions:(i,s)=>{let o=r.metadata.get("decoder"),a=o==null?void 0:o.getConverter("Extensions");a&&(s.Extensions=a.convert(i,r))}}),n}convertTraining(t){var n;let r={};return t.attributes&&Object.entries(t.attributes).forEach(([i,s])=>{r[i]=s}),(n=t.children)==null||n.forEach(i=>{r[i.tag]=this.convertExtensionContent(i)}),r}convertCreator(t){var n;let r={};return(n=t.children)==null||n.forEach(i=>{r[i.tag]=this.convertExtensionContent(i)}),r}},de=class extends f{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(t,r){let n={Activity:[],MultiSportSession:[]};return this.processChildren(t,n,{Activity:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("Activity"))==null?void 0:p.convert(i,r);a&&s.Activity&&s.Activity.push(a)},MultiSportSession:(i,s)=>{var p;let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("MultiSportSession"))==null?void 0:p.convert(i,r);a&&s.MultiSportSession&&s.MultiSportSession.push(a)}}),n}},le=class extends f{constructor(){super(...arguments);this.name="MultiSportSessionConverter";this.supportedTags=["MultiSportSession"]}convert(t,r){let n={};return this.processChildren(t,n,{Id:(i,s)=>s.Id=this.parseString(i.value),FirstSport:(i,s)=>{var a;let o=r.metadata.get("decoder");s.FirstSport=(a=o==null?void 0:o.getConverter("FirstSport"))==null?void 0:a.convert(i,r)},NextSport:(i,s)=>{var p;s.NextSport||(s.NextSport=[]);let o=r.metadata.get("decoder"),a=(p=o==null?void 0:o.getConverter("NextSport"))==null?void 0:p.convert(i,r);a&&s.NextSport.push(a)},Notes:(i,s)=>s.Notes=this.parseString(i.value)}),n}},ue=class extends f{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(t,r){let n={};return this.processChildren(t,n,{Name:(i,s)=>s.Name=this.parseString(i.value)}),n}},me=class extends f{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(t,r){let n={};return this.flattenExtensionElement(t,n),n}flattenExtensionElement(t,r){var n,i;if(!((n=t.children)!=null&&n.length)&&t.value!==void 0){r[t.tag]=this.parseExtensionValue(t.value);return}(i=t.children)!=null&&i.length&&t.children.forEach(s=>{this.flattenExtensionElement(s,r)})}parseExtensionValue(t){if(t===void 0)return;let r=String(t),n=parseFloat(r);return!isNaN(n)&&isFinite(n)?n:r}};import{Parser as Be}from"htmlparser2";var Te=class{static tokenizeXML(e){let t=[],r=new Be({onopentag(n,i){t.push({type:"open",tag:n,attributes:i})},ontext(n){let i=n.replace(/\n/g,"").trim();i&&t.push({type:"text",tag:"text",value:i})},onclosetag(n){t.push({type:"close",tag:n})}},{xmlMode:!0});return r.write(e),r.end(),t}static compressXML(e){return e.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(e,t=2){let r=" ".repeat(t),n="",i=0,s=!1;for(let o=0;o<e.length;o++){let a=e[o],p=e[o+1];a==="<"?(p==="/"?(i--,s||(n+=`
|
|
12
|
+
`+r.repeat(i))):p!=="?"&&p!=="!"&&(s||(n+=`
|
|
13
|
+
`+r.repeat(i)),i++),s=!0):a===">"&&(s=!1,p==="<"&&e[o+2]==="/"&&i--),n+=a}return n.trim()}static validateXML(e){try{let t=new Be({},{xmlMode:!0});return t.write(e),t.end(),{isValid:!0}}catch(t){return{isValid:!1,error:t.message}}}static extractXMLDeclaration(e){let t=e.match(/<\?xml\s+([^>]+)\?>/);if(!t)return{};let r=t[1],n={},i=r.match(/version=["']([^"']+)["']/);i&&(n.version=i[1]);let s=r.match(/encoding=["']([^"']+)["']/);s&&(n.encoding=s[1]);let o=r.match(/standalone=["']([^"']+)["']/);return o&&(n.standalone=o[1]),n}static escapeXML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}static unescapeXML(e){return e.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}};var fe=class{constructor(){this.stage="tokenize";this.name="tokenize-processor"}async process(e){if(!e.xmlContent)throw new Error("TCX data cannot be empty");let t=Te.tokenizeXML(e.xmlContent);if(t.length===0)throw new Error("Not a valid TCX file");return e.tokens=t,e.stats.processedTokens=t.length,e}},ge=class{constructor(){this.stage="ast-generate";this.name="ast-generate-processor"}async process(e){var s;let t=Date.now();if(!e.tokens)throw new Error("Tokens cannot be empty");let r=[],n,i=null;for(let o of e.tokens)if(o.type==="open"){let a={tag:o.tag,attributes:o.attributes||{},children:[]};n?i&&((s=i.children)==null||s.push(a)):n=a,r.push(a),i=a}else o.type==="text"&&i?i.value=o.value:o.type==="close"&&(r.pop(),i=r[r.length-1]||null);return e.ast=n,e.performance.astTime=Date.now()-t,e}},he=class{constructor(e){this.getConverter=e;this.stage="convert";this.name="convert-processor"}async process(e){if(!e.ast)throw new Error("AST is empty, cannot convert");let t=this.findTCXRoot(e.ast);if(!t)throw new Error("Not a valid TCX file: TrainingCenterDatabase element not found");let r=this.convertAST(t,e);return e.result=r,e.stats.convertedElements=this.countElements(e.ast),e}findTCXRoot(e){if(e.tag==="TrainingCenterDatabase")return e;if(e.children)for(let t of e.children){let r=this.findTCXRoot(t);if(r)return r}}convertAST(e,t){let r=this.getConverter(e.tag);return r?r.convert(e,t):this.genericConvert(e,t)}genericConvert(e,t){let r={};if(e.attributes&&Object.entries(e.attributes).forEach(([n,i])=>{r[n]=i}),e.value!==void 0)if(e.children&&e.children.length>0)r._value=e.value;else return e.value;return e.children&&e.children.forEach(n=>{let i=this.convertAST(n,t);r[n.tag]?(Array.isArray(r[n.tag])||(r[n.tag]=[r[n.tag]]),r[n.tag].push(i)):r[n.tag]=i}),r}countElements(e){let t=1;if(e.children)for(let r of e.children)t+=this.countElements(r);return t}},ye=class{constructor(){this.stage="complete";this.name="complete-processor"}async process(e){if(!e.result)throw new Error("No conversion result found");let t=Date.now(),r=t-e.performance.startTime;return e.performance.endTime=t,e.performance.processingTime=r,e.metadata.set("performance",{processingTime:r,processedTokens:e.stats.processedTokens,convertedElements:e.stats.convertedElements}),e}};var S=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 fe,new ge,new he(e=>this.getConverter(e)),new ye]}async registerDefaultConverters(){var t;if(this.defaultConvertersRegistered)return;let e=[new se,new oe,new ae,new ce,new pe,new de,new le,new ue,new me];for(let r of e)(t=r.supportedTags)==null||t.forEach(n=>{this.addConverterForTag(n,r)}),this.registeredPlugins.add(r.name);this.defaultConvertersRegistered=!0}addConverterForTag(e,t){this.converterPlugins.has(e)||this.converterPlugins.set(e,[]);let r=this.converterPlugins.get(e);r.push(t),r.sort((n,i)=>(n.priority||100)-(i.priority||100))}async registerConverter(e){var r,i;if(this.registeredPlugins.has(e.name))throw new Error(`Converter plugin ${e.name} already exists`);(r=e.supportedTags)==null||r.forEach(s=>{this.addConverterForTag(s,e)}),this.registeredPlugins.add(e.name);let t=e.priority!==void 0?` (priority: ${e.priority})`:"";(i=e.supportedTags)==null||i.forEach(s=>{let a=(this.converterPlugins.get(s)||[]).map(p=>`${p.name}(${p.priority||100})`)})}async registerMiddleware(e){let t=this.middlewarePlugins.findIndex(n=>n.name===e.name);t!==-1?this.middlewarePlugins[t]=e:this.middlewarePlugins.push(e);let r=[];e.onTokenize&&r.push("onTokenize"),e.onAstGenerate&&r.push("onAstGenerate"),e.onConvert&&r.push("onConvert"),e.onComplete&&r.push("onComplete"),e.onError&&r.push("onError"),r.length>0}getConverter(e){let t=this.converterPlugins.get(e);return t&&t.length>0?t[0]:void 0}getAllConverters(e){return this.converterPlugins.get(e)||[]}unregisterConverter(e){let t;for(let[r,n]of this.converterPlugins){let i=n.findIndex(s=>s.name===e);i!==-1&&(t=n[i],n.splice(i,1),n.length===0&&this.converterPlugins.delete(r))}t&&this.registeredPlugins.delete(e)}unregisterMiddleware(e){let t=this.middlewarePlugins.findIndex(r=>r.name===e);t!==-1&&this.middlewarePlugins.splice(t,1)}async initialize(){var r;if(this.initialized)return;await this.registerDefaultConverters();let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.initialize)==null?void 0:r.call(n,e))}catch{}this.initialized=!0}async destroy(){var r;if(!this.initialized)return;let e=this.createContext(),t=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let n of t)try{await((r=n.destroy)==null?void 0:r.call(n,e))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(e,t,r){var i;let n=t;for(let s of this.middlewarePlugins){let o=s[e];if(o)try{n=await o.call(s,n,r)||n}catch(a){r.errors.push(a),await((i=s.onError)==null?void 0:i.call(s,a,r))}}return n}async parseByBuffer(e){var r;await this.initialize();let t=this.createContext();t.rawData=e,t.xmlContent=e.toString("utf-8"),t.metadata.set("decoder",this);try{for(let n of this.processors)try{switch(t=await n.process(t),n.stage){case"tokenize":t.tokens&&(t.tokens=await this.executeMiddlewareHook("onTokenize",t.tokens,t));break;case"ast-generate":t.ast&&(t.ast=await this.executeMiddlewareHook("onAstGenerate",t.ast,t));break;case"convert":t.result&&(t.result=await this.executeMiddlewareHook("onConvert",t.result,t));break;case"complete":t.result&&(t.result=await this.executeMiddlewareHook("onComplete",t.result,t));break}}catch(i){t.errors.push(i);for(let s of this.middlewarePlugins)await((r=s.onError)==null?void 0:r.call(s,i,t))}return t.result}catch(n){throw n}}convertExtensions(e){var s,o;let t={},{attributes:r,tag:n,value:i}=e;if(r&&Object.entries(r).forEach(([a,p])=>{t[a]=p}),(s=e==null?void 0:e.children)!=null&&s.length)(o=e.children)==null||o.forEach(a=>{t[a.tag]=this.convertExtensions(a)});else if(i!==void 0)return i;return t}async parserByBuffer(e){return this.parseByBuffer(e)}async parseByString(e){let t=Buffer.from(e,"utf-8");return this.parseByBuffer(t)}};import He from"dayjs";import ot from"dayjs/plugin/utc.js";He.extend(ot);var I=class{constructor(e={}){this.compact=e.compact??!0}async encode(e){let t=this.buildTCXXML(e);return Buffer.from(t,"utf-8")}encodeToString(e){return this.buildTCXXML(e)}buildTCXXML(e){let t=this.buildXMLHeader(e),r=this.buildTCXContent(e),i=`${t}${r}
|
|
14
14
|
</TrainingCenterDatabase>`;return this.compact?this.compressXML(i):i}compressXML(e){return e.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(e){let t=e.version||"1.0",r=e.creator||"trackswap",n=e.xmlns||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2",i=e["xmlns:xsi"]||"http://www.w3.org/2001/XMLSchema-instance",s=e["xsi:schemaLocation"]||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd";return['<?xml version="1.0" encoding="UTF-8"?>',`<TrainingCenterDatabase version="${this.escapeXMLAttribute(t)}"`,` creator="${this.escapeXMLAttribute(r)}"`,` xmlns="${this.escapeXMLAttribute(n)}"`,` xmlns:xsi="${this.escapeXMLAttribute(i)}"`,` xsi:schemaLocation="${this.escapeXMLAttribute(s)}">`].join(`
|
|
15
15
|
`)}buildTCXContent(e){let t=[];return e.Folders&&t.push(this.buildFolders(e.Folders)),e.Activities&&t.push(this.buildActivities(e.Activities)),e.Workouts&&t.push(this.buildWorkouts(e.Workouts)),e.Courses&&t.push(this.buildCourses(e.Courses)),e.Author&&t.push(this.buildAuthor(e.Author)),e.Extensions&&t.push(this.buildExtensions(e.Extensions)),t.join(`
|
|
16
16
|
`)}buildFolders(e){let t=["<Folders>"];return e.History&&t.push(this.buildHistory(e.History)),e.Workouts&&t.push(this.buildWorkouts(e.Workouts)),e.Courses,t.push("</Folders>"),t.join(`
|
|
@@ -23,4 +23,4 @@ var G=class{constructor(){this.stage="parse"}async process(e){let t=Date.now();i
|
|
|
23
23
|
`)}buildPosition(e){let t=["<Position>"];return e.LatitudeDegrees&&t.push(`<LatitudeDegrees>${this.formatCoordinate(parseFloat(e.LatitudeDegrees))}</LatitudeDegrees>`),e.LongitudeDegrees&&t.push(`<LongitudeDegrees>${this.formatCoordinate(parseFloat(e.LongitudeDegrees))}</LongitudeDegrees>`),t.push("</Position>"),t.join("")}buildCadence(e){return`<Cadence><Low>${e.Low}</Low><High>${e.High}</High></Cadence>`}buildMultiSportSession(e){let t=["<MultiSportSession>"];return e.Id&&t.push(`<Id>${this.formatTime(e.Id)}</Id>`),e.FirstSport&&t.push(this.buildFirstSport(e.FirstSport)),e.NextSport&&e.NextSport.forEach(r=>{t.push(this.buildNextSport(r))}),this.addOptionalElement(t,"Notes",e.Notes),t.push("</MultiSportSession>"),t.join(`
|
|
24
24
|
`)}buildFirstSport(e){let t=["<FirstSport>"];return e.Activity&&t.push(this.buildActivity(e.Activity)),t.push("</FirstSport>"),t.join(`
|
|
25
25
|
`)}buildNextSport(e){let t=["<NextSport>"];return e.Transition&&t.push(`<Transition>${this.buildActivityLap(e.Transition)}</Transition>`),e.Activity&&t.push(this.buildActivity(e.Activity)),t.push("</NextSport>"),t.join(`
|
|
26
|
-
`)}buildWorkouts(e){return"<Workouts></Workouts>"}buildCourses(e){return"<Courses></Courses>"}buildAuthor(e){let t=["<Author>"];return this.addOptionalElement(t,"Name",e.Name),t.push("</Author>"),t.join("")}buildExtensions(e){let t=this.buildExtensionContent(e);return t?`<Extensions>${t}</Extensions>`:""}buildExtensionContent(e){return Object.entries(e).filter(([t])=>!t.startsWith("xmlns")).map(([t,r])=>{if(r&&typeof r=="object"){let n=this.buildExtensionContent(r);return`<${t}>${n}</${t}>`}else if(r!=null)return`<${t}>${this.escapeXML(String(r))}</${t}>`;return""}).filter(t=>t).join("")}formatTime(e){return typeof e=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)?e:Ke(e).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}addOptionalElement(e,t,r,n){if(r!=null&&r!==""){let i=n?n(r):this.escapeXML(r);e.push(`<${t}>${i}</${t}>`)}}addOptionalNumericElement(e,t,r){r!=null&&!isNaN(r)&&e.push(`<${t}>${r}</${t}>`)}isValidCoordinate(e,t){return e!=null&&t!==void 0&&t!==null&&!isNaN(e)&&!isNaN(t)}formatCoordinate(e){return this.roundTo(e,6).toString()}roundTo(e,t){let r=Math.pow(10,t);return Math.round(e*r)/r}escapeXML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}escapeXMLAttribute(e){return typeof e!="string"?String(e||""):e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/\r/g," ").replace(/\n/g," ").replace(/\t/g,"	")}deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(r=>this.deepClone(r));let t={};for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=this.deepClone(e[r]));return t}encoder(e){return this.encode(e)}};var Me=class extends E{constructor(){super(...arguments);this.name="tcx-performance-middleware";this.description="Monitor TCX parsing performance"}async onTokenize(t,r){return t}async onAstGenerate(t,r){let n=this.countNodes(t);return t}async onComplete(t,r){let n=r.metadata.get("performance");return t}countNodes(t){let r=1;if(t.children)for(let n of t.children)r+=this.countNodes(n);return r}},Le=class extends E{constructor(){super(...arguments);this.name="tcx-validation-middleware";this.description="Validate TCX data integrity"}async onComplete(t,r){let n=this.validateTCX(t);return n.length>0&&r.metadata.set("validation-errors",n),t}validateTCX(t){let r=[];if(t.version||r.push("Missing TCX version information"),t.creator||r.push("Missing TCX creator information"),t.Activities&&t.Activities.Activity){for(let n of t.Activities.Activity)if(n.Id||r.push("Activity missing ID information"),(!n.Lap||n.Lap.length===0)&&r.push("Activity must contain at least one Lap"),n.Lap){for(let i of n.Lap)if(i.Track){for(let s of i.Track)if(s.Trackpoint)for(let o of s.Trackpoint)o.Position&&(!o.Position.LatitudeDegrees||!o.Position.LongitudeDegrees)&&r.push("Invalid trackpoint coordinates")}}}return r}},Oe=class extends E{constructor(){super(...arguments);this.name="tcx-enhancement-middleware";this.description="Enhance TCX data with additional calculated fields"}async onComplete(t,r){if(t.Activities&&t.Activities.Activity)for(let n of t.Activities.Activity)n.totalDistance=this.calculateTotalDistance(n),n.totalDuration=this.calculateTotalDuration(n),n.totalDistance&&n.totalDuration&&(n.averageSpeed=n.totalDistance/n.totalDuration);return t}calculateTotalDistance(t){let r=0;if(t.Lap)for(let n of t.Lap)n.DistanceMeters&&(r+=n.DistanceMeters);return r}calculateTotalDuration(t){let r=0;if(t.Lap)for(let n of t.Lap)n.TotalTimeSeconds&&(r+=n.TotalTimeSeconds);return r}};async function Br(p){let e=[new Me,new Le,new Oe];for(let t of e)await p.registerMiddleware(t)}var S=class extends y{convertPoints(e){return e.map(t=>this.convertPoint(t)).filter(t=>t!==void 0)}convertTime(e){if(e){if(typeof e=="number")return e;if(e instanceof Date)return e.getTime();if(typeof e=="string"){let t=new Date(e);return isNaN(t.getTime())?void 0:t.getTime()}}}calculateDistance(e){if(e.length<2)return;let t=0;for(let r=1;r<e.length;r++){let n=e[r-1],i=e[r],s=6371e3,o=n.lat*Math.PI/180,a=i.lat*Math.PI/180,c=(i.lat-n.lat)*Math.PI/180,d=(i.lon-n.lon)*Math.PI/180,l=Math.sin(c/2)*Math.sin(c/2)+Math.cos(o)*Math.cos(a)*Math.sin(d/2)*Math.sin(d/2),u=2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l));t+=s*u}return t}calculateDuration(e){var n,i;if(e.length<2)return;let t=(n=e[0])==null?void 0:n.time,r=(i=e[e.length-1])==null?void 0:i.time;if(!(!t||!r))return Math.round((r-t)/1e3)}},b=class{constructor(){this.version="1.0.0";this.priority=100}supports(e){return this.supportedTags.includes(e)}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}convertTimeToDate(e){return e?new Date(e):new Date}convertTimeToString(e){return this.convertTimeToDate(e).toISOString()}ensureValidCoordinates(e,t){return e>=-90&&e<=90&&t>=-180&&t<=180}round(e,t=6){let r=Math.pow(10,t);return Math.round(e*r)/r}};var Ye={heartrate:"heartRate","gpxtpx:hr":"heartRate","ns3:hr":"heartRate","gpxdata:hr":"heartRate","gpxdata:cadence":"cadence","gpxtpx:cad":"cadence","ns3:cad":"cadence",cadence:"cadence","gpxtpx:speed":"speed","ns3:speed":"speed",speed:"speed",power:"power","gpxdata:power":"power","gpxpx:PowerInWatts":"power",PowerInWatts:"power","gpxtpx:temp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:atemp":"atemp","gpxx:Temperature":"temperature","gpxx:Depth":"depth"},$e=p=>p*(180/Math.pow(2,31));import L from"dayjs";function Ne(p,e=0){let t=Math.pow(10,e);return Math.round(p*t)/t}var ve=class extends S{constructor(){super(...arguments);this.name="gpx-to-sport-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=t=>{let r={};return Object.entries(t).forEach(([n,i])=>{if(typeof i<"u"&&i!=="undefined"){let s=Ye[n]||n;r[s]=this.autoNumber(i)}}),r}}convert(t,r){if(r.sourceFormat!=="gpx")return;let n=r.sourceData;return this.convertGPX(n)}convertGPX(t){let r={metadata:{originType:"GPX",creator:t.creator,fileType:"gpx"}};return t.wpt&&(r.points=this.convertWpts2Points(t.wpt)),t.trk&&(r.tracks=t.trk.map(n=>{var i;return{name:n.name,trackseg:((i=n.trkseg)==null?void 0:i.map(s=>({name:n.name,points:s.trkpt?this.convertWpts2Points(s.trkpt):[]})))||[]}})),t.rte&&(r.routes=t.rte.map(n=>({name:n.name,points:n.rtept?this.convertWpts2Points(n.rtept):[]}))),r}convertPoint(t){if(t.lat==null||t.lon==null)return;let{extensions:r}=t,n=r?this.convertGPXExtensions(r):{};return{lat:t.lat,lon:t.lon,ele:t.ele,heartRate:t==null?void 0:t.heartRate,speed:t==null?void 0:t.speed,power:t==null?void 0:t.power,cadence:t==null?void 0:t.cadence,time:this.convertTime(t.time),...n}}convertWpts2Points(t){let r=[];for(let n=0;n<t.length;n++){let i=t[n];if(i.lat!=null&&i.lon!=null){let s=this.convertPoint(i);s&&r.push(s)}}return r}autoNumber(t){return typeof t=="string"&&t.trim()!==""&&!isNaN(t)?Number(t):t}},xe=class extends S{constructor(){super(...arguments);this.name="fit-to-sport-converter";this.supportedTags=["fit"]}convert(t,r){if(r.sourceFormat!=="fit")return;let n=r.sourceData;return this.convertFIT(n)}convertFIT(t){var n,i;let r={metadata:{originType:"FIT",fileType:"fit"}};if((n=t.sessionMesgs)!=null&&n.length){r.tracks=[];for(let s of t.sessionMesgs)r.tracks.push({name:s.event,startTime:s.startTime?L(s.startTime).valueOf():void 0,distance:s.totalDistance,duration:s.totalElapsedTime,sport:s.sport,trackseg:this.convertFITLap2Trackseg(s==null?void 0:s.lapMesgs),__fit__sessionMesgType:s})}else if((i=t.courseMesgs)!=null&&i.length){r.routes=[];for(let s of t.courseMesgs)r.routes.push({name:s.event,points:this.convertLap2Points(s==null?void 0:s.lapMesgs)})}return r}convertPoint(t){let{positionLong:r,positionLat:n,altitude:i,timestamp:s,heartRate:o,cadence:a,distance:c,power:d,enhancedAltitude:l,enhancedSpeed:u,temperature:T,...g}=t;if(!(r==null||n==null))return{lat:Ne($e(Number(n)),6),lon:Ne($e(Number(r)),6),ele:i,heartRate:o,power:d,cadence:a,temperature:T,time:s?L(s).valueOf():void 0,...g}}convertFITLap2Trackseg(t){var n;let r=[];if(!(t!=null&&t.length))return[];for(let i of t){let s=((n=i==null?void 0:i.recordMesgs)==null?void 0:n.map(o=>this.convertPoint(o)).filter(o=>o!==void 0))||[];r.push({points:s,duration:i.totalElapsedTime,distance:i.totalDistance,startTime:i.startTime?L(i.startTime).valueOf():void 0,endTime:i.startTime&&i.totalElapsedTime?L(i.startTime).add(i.totalElapsedTime,"second").valueOf():void 0,avgSpeed:i.avgSpeed,maxSpeed:i.maxSpeed,avgCadenceBpm:i.avgCadence,maxCadenceBpm:i.maxCadence,avgPower:i.avgPower,maxPower:i.maxPower,totalAscent:i.totalAscent,totalDescent:i.totalDescent,calories:i.totalCalories,__fit__lapMesgType:i})}return r}convertLap2Points(t){var n;let r=[];if(!(t!=null&&t.length))return[];for(let i of t){let s=((n=i.recordMesgs)==null?void 0:n.map(o=>this.convertPoint(o)).filter(o=>o!==void 0))||[];s.length&&(r=[...r,...s])}return r}},Ce=class extends S{constructor(){super(...arguments);this.name="tcx-to-sport-converter";this.supportedTags=["tcx"]}convert(t,r){if(r.sourceFormat!=="tcx")return;let n=r.sourceData;return this.convertTCX(n)}convertTCX(t){var n,i,s,o;let r={metadata:{originType:"TCX",fileType:"tcx"}};if((i=(n=t.Activities)==null?void 0:n.Activity)!=null&&i.length){r.tracks=[];for(let a of t.Activities.Activity)r.tracks.push({name:a.Id,sport:a.Sport,trackseg:this.convertLap2Trackseg(a.Lap)})}if((o=(s=t.Courses)==null?void 0:s.Course)!=null&&o.length){r.routes=[];for(let a of t.Courses.Course){let c=a.Track||[];for(let d of c)r.routes.push({name:a.Name||"",points:this.convertTCXTrack(d)})}}return r}convertPoint(t){let{Position:r,Time:n,DistanceMeters:i,AltitudeMeters:s}=t;if(!(!(r!=null&&r.LatitudeDegrees)||!(r!=null&&r.LongitudeDegrees)||r.LatitudeDegrees===""||r.LongitudeDegrees===""))return{lat:Number(r.LatitudeDegrees),lon:Number(r.LongitudeDegrees),time:n?L(n).valueOf():void 0,distance:i,ele:s}}convertLap2Trackseg(t){var n,i,s,o;let r=[];for(let a of t)if(a.Track){for(let c of a.Track)if(c.Trackpoint){let d=c.Trackpoint.map(u=>this.convertPoint(u)).filter(u=>u!==void 0),l={duration:a.TotalTimeSeconds,distance:a.DistanceMeters,startTime:(n=d==null?void 0:d[0])==null?void 0:n.time,endTime:(i=d==null?void 0:d[d.length-1])==null?void 0:i.time,avgHeartRateBpm:a==null?void 0:a.AverageHeartRateBpm,maxHeartRateBpm:a==null?void 0:a.MaximumHeartRateBpm,maxSpeed:a.MaximumSpeed,calories:a.Calories,__tcx__Intensity:a==null?void 0:a.Intensity,__tcx__TriggerMethod:a==null?void 0:a.TriggerMethod,avgCadenceBpm:(s=a==null?void 0:a.Cadence)==null?void 0:s.Low,maxCadenceBpm:(o=a==null?void 0:a.Cadence)==null?void 0:o.High,points:d};r.push(l)}}return r}convertTCXTrack(t){return t.Trackpoint?t.Trackpoint.map(r=>this.convertPoint(r)).filter(r=>r!==void 0):[]}};import Tt from"dayjs";function Ze(p){return Math.round(p*(Math.pow(2,31)/180))}var Pe=class extends b{constructor(){super(...arguments);this.name="sport-to-gpx-encoder";this.supportedTags=["gpx"]}encode(t,r){var i,s,o,a,c,d,l;if(r.targetFormat!=="gpx")return;let n={version:"1.1",creator:((i=t.metadata)==null?void 0:i.creator)||"TrackSwap",metadata:{name:(s=t==null?void 0:t.metadata)==null?void 0:s.fileName,time:(o=t==null?void 0:t.metadata)!=null&&o.date?Tt((a=t==null?void 0:t.metadata)==null?void 0:a.date).toDate():void 0}};return(c=t.points)!=null&&c.length&&(n.wpt=this.convertPoints2Wpts(t.points)),(d=t.routes)!=null&&d.length&&(n.rte=t.routes.map(u=>this.convertRoute2GPXRoute(u))),(l=t.tracks)!=null&&l.length&&(n.trk=t.tracks.map(u=>this.convertTrack2GPXTrack(u))),n}convertPoints2Wpts(t){return t==null?void 0:t.filter(r=>!!r.lat&&!!r.lon).map(r=>({lat:r.lat,lon:r.lon,ele:r==null?void 0:r.ele,time:r!=null&&r.time?this.convertTimeToDate(r.time):void 0,speed:r==null?void 0:r.speed,geoidheight:r==null?void 0:r.geoidheight,name:r==null?void 0:r.name,cmt:r==null?void 0:r.cmt,desc:r==null?void 0:r.desc,type:r==null?void 0:r.type,hdop:r==null?void 0:r.hdop,vdop:r==null?void 0:r.vdop,pdop:r==null?void 0:r.pdop,ageofdgpsdata:r==null?void 0:r.ageofdgpsdata,magvar:r.magvar,extensions:this.extractGPXExtensions(r)}))}convertRoute2GPXRoute(t){return{name:t==null?void 0:t.name,cmt:t==null?void 0:t.GPX_cmt,desc:t==null?void 0:t.GPX_desc,number:t==null?void 0:t.GPX_number,type:t==null?void 0:t.GPX_type,rtept:t.points?this.convertPoints2Wpts(t.points):[]}}convertTrack2GPXTrack(t){var r;return{name:t==null?void 0:t.name,cmt:t==null?void 0:t.GPX_cmt,desc:t==null?void 0:t.GPX_desc,src:t==null?void 0:t.GPX_src,number:t==null?void 0:t.GPX_number,type:t==null?void 0:t.GPX_type,trkseg:((r=t.trackseg)==null?void 0:r.map(n=>{var i;return{trkpt:(i=n==null?void 0:n.points)!=null&&i.length?this.convertPoints2Wpts(n.points):[]}}))||[]}}extractGPXExtensions(t){let r={};return typeof(t==null?void 0:t.heartRate)<"u"&&(r["gpxtpx:hr"]=t.heartRate),typeof(t==null?void 0:t.cadence)<"u"&&(r["gpxtpx:cad"]=t.cadence),typeof(t==null?void 0:t.temperature)<"u"&&(r["gpxtpx:atemp"]=t.temperature),typeof(t==null?void 0:t.power)<"u"&&(r.extractGPXExtensions=t.power),Object.keys(r).length>0?r:void 0}},we=class extends b{constructor(){super(...arguments);this.name="sport-to-fit-encoder";this.supportedTags=["fit"]}encode(t,r){var i,s,o;if(r.targetFormat!=="fit")return;let n={};return(i=t.tracks)!=null&&i.length&&(n.sessionMesgs=(s=t==null?void 0:t.tracks)==null?void 0:s.map(a=>this.convertTrack2FITSession(a))),(o=t.routes)!=null&&o.length&&(n.courseMesgs=t.routes.map(a=>this.convertRoute2FITCourse(a))),n}convertTrack2FITSession(t){var n;return{event:(t==null?void 0:t.name)||"session",sport:(t==null?void 0:t.sport)||"generic",startTime:t.startTime?this.convertTimeToString(t.startTime):this.convertTimeToString(void 0),totalDistance:t.distance,totalElapsedTime:t.duration,lapMesgs:((n=t.trackseg)==null?void 0:n.map(i=>this.convertSeg2FITLap(i)))||[]}}convertSeg2FITLap(t){var n;return{startTime:t.startTime?this.convertTimeToString(t.startTime):this.convertTimeToString(void 0),totalElapsedTime:t.duration,totalDistance:t.distance,avgSpeed:t.avgSpeed,maxSpeed:t.maxSpeed,avgCadence:t.avgCadenceBpm,maxCadence:t.maxCadenceBpm,avgPower:t.avgPower,maxPower:t.maxPower,totalAscent:t.totalAscent,totalDescent:t.totalDescent,totalCalories:t.calories,recordMesgs:((n=t.points)==null?void 0:n.map(i=>this.convertPoint2FITRecord(i)))||[]}}convertPoint2FITRecord(t){return{timestamp:t.time?this.convertTimeToString(t.time):this.convertTimeToString(void 0),positionLat:Ze(t.lat),positionLong:Ze(t.lon),altitude:t.ele,speed:t.speed,power:t.power,heartRate:t.heartRate,cadence:t.cadence,temperature:t.temperature,distance:t.distance,enhancedSpeed:t.enhancedSpeed,enhancedAltitude:t.enhancedAltitude,accumulatedPower:t.accumulatedPower}}convertRoute2FITCourse(t){return{event:t.name||"course",lapMesgs:t.points?[this.convertPoints2FITLap(t.points)]:[]}}convertPoints2FITLap(t){let r=t[0],n=t[t.length-1],i=r!=null&&r.time?this.convertTimeToString(r.time):this.convertTimeToString(void 0),s=r!=null&&r.time&&(n!=null&&n.time)?Math.round((n.time-r.time)/1e3):0,o=(n==null?void 0:n.distance)||0;return{startTime:i,totalElapsedTime:s,totalDistance:o,recordMesgs:t.map(a=>this.convertPoint2FITRecord(a))}}},Ee=class extends b{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(t,r){var i,s,o;if(r.targetFormat!=="tcx")return;let n={Author:{Name:((i=t.metadata)==null?void 0:i.creator)||"TrackSwap"}};return(s=t.tracks)!=null&&s.length&&(n.Activities={Activity:t.tracks.map(a=>this.convertTrack2TCXActivity(a))}),(o=t.routes)!=null&&o.length&&(n.Courses={Course:t.routes.map(a=>this.convertRoute2TCXCourse(a))}),n}convertTrack2TCXActivity(t){var n;let r="Other";return(t.sport==="Running"||t.sport==="Biking")&&(r=t.sport),{Id:t.name||`Activity_${Date.now()}`,Sport:r,Lap:((n=t.trackseg)==null?void 0:n.map(i=>this.convertSeg2TCXLap(i)))||[]}}convertSeg2TCXLap(t){let r={TotalTimeSeconds:t.duration,DistanceMeters:t.distance,MaximumSpeed:t.maxSpeed,Calories:t.calories,AverageHeartRateBpm:t.avgHeartRateBpm,MaximumHeartRateBpm:t.maxHeartRateBpm,Intensity:t.__tcx__Intensity||"Active",TriggerMethod:t.__tcx__TriggerMethod||"Manual",Track:t.points?[this.convertPoints2TCXTrack(t.points)]:[]};return(t.avgCadenceBpm!==void 0||t.maxCadenceBpm!==void 0)&&(r.Cadence={Low:t.avgCadenceBpm||0,High:t.maxCadenceBpm||0}),r}convertPoints2TCXTrack(t){return{Trackpoint:t.map(r=>this.convertPoint2TCXTrackpoint(r))}}convertPoint2TCXTrackpoint(t){let r={Time:t.time?this.convertTimeToString(t.time):this.convertTimeToString(void 0),Position:{LatitudeDegrees:t.lat.toString(),LongitudeDegrees:t.lon.toString()},AltitudeMeters:t.ele,DistanceMeters:t.distance};return t.heartRate&&(r.HeartRateBpm=t.heartRate),r}convertRoute2TCXCourse(t){return{Name:t.name||`Course_${Date.now()}`,Track:t.points?[this.convertPoints2TCXTrack(t.points)]:[]}}};var Se=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new ve),this.registerConverter(new xe),this.registerConverter(new Ce)}registerDefaultEncoders(){this.registerEncoder(new Pe),this.registerEncoder(new we),this.registerEncoder(new Ee)}registerConverter(e){this.converters.set(e.name,e)}registerEncoder(e){this.encoders.set(e.name,e)}async convertToSport(e,t){let r={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:t,sourceData:e,performance:{startTime:Date.now()}};try{let n=this.findConverter(t);if(!n)throw new Error(`No converter found for format "${t}"`);let i=Date.now(),s=n.convert({},r);if(r.performance.convertTime=Date.now()-i,!s)throw new Error(`Converter "${n.name}" returned empty result`);return r.result=s,r.performance.endTime=Date.now(),r.stats.endTime=Date.now(),s}catch(n){throw r.errors.push(n),n}}async encodeSport(e,t){let r={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:t,performance:{startTime:Date.now()}};try{let n=this.findEncoder(t);if(!n)throw new Error(`No encoder found for format "${t}"`);let i=Date.now(),s=n.encode(e,r);if(r.performance.encodeTime=Date.now()-i,!s)throw new Error(`Encoder "${n.name}" returned empty result`);return r.result=s,r.performance.endTime=Date.now(),r.stats.endTime=Date.now(),s}catch(n){throw r.errors.push(n),n}}findConverter(e){return Array.from(this.converters.values()).find(t=>{var r;return(r=t.supportedTags)==null?void 0:r.includes(e)})}findEncoder(e){return Array.from(this.encoders.values()).find(t=>{var r;return(r=t.supportedTags)==null?void 0:r.includes(e)})}async destroy(){this.converters.clear(),this.encoders.clear()}};var O=class{constructor(){this.gpxDecoder=new D,this.gpxEncoder=new X,this.fitDecoder=new P,this.fitEncoder=new w,this.tcxDecoder=new R,this.tcxEncoder=new M,this.sportProcessor=new Se}async parseGPX(e){try{return await this.gpxDecoder.parserByBuffer(e)}catch(t){throw new Error(`GPX parsing failed: ${t.message}`)}}async parseGPXString(e){let t=Buffer.from(e,"utf-8");return this.parseGPX(t)}async encodeGPX(e){try{return await this.gpxEncoder.encode(e)}catch(t){throw new Error(`GPX encoding failed: ${t.message}`)}}encodeGPXString(e){try{return this.gpxEncoder.encodeToString(e)}catch(t){throw new Error(`GPX encoding failed: ${t.message}`)}}async parseFIT(e){try{return await this.fitDecoder.parseByBuffer(e)}catch(t){throw new Error(`FIT parsing failed: ${t.message}`)}}async encodeFIT(e){try{return await this.fitEncoder.encode(e)}catch(t){throw new Error(`FIT encoding failed: ${t.message}`)}}async encodeFITCourse(e){try{return await this.fitEncoder.encodeCourse(e)}catch(t){throw new Error(`FIT Course encoding failed: ${t.message}`)}}async parseTCX(e){try{let t=await this.tcxDecoder.parseByBuffer(e);if(!t)throw new Error("TCX parsing result is empty");return t}catch(t){throw new Error(`TCX parsing failed: ${t.message}`)}}async parseTCXString(e){let t=Buffer.from(e,"utf-8");return this.parseTCX(t)}async encodeTCX(e){try{return await this.tcxEncoder.encode(e)}catch(t){throw new Error(`TCX encoding failed: ${t.message}`)}}async encodeTCXString(e){try{return await this.tcxEncoder.encodeToString(e)}catch(t){throw new Error(`TCX encoding failed: ${t.message}`)}}async convertGPXToSport(e){return await this.sportProcessor.convertToSport(e,"gpx")}async convertFITToSport(e){return await this.sportProcessor.convertToSport(e,"fit")}async convertTCXToSport(e){return await this.sportProcessor.convertToSport(e,"tcx")}async convertSportToGPX(e){return await this.sportProcessor.encodeSport(e,"gpx")}async convertSportToFIT(e){return await this.sportProcessor.encodeSport(e,"fit")}async convertSportToTCX(e){return await this.sportProcessor.encodeSport(e,"tcx")}async convertFile(e,t,r){try{let n=r||this.detectFormat(e);if(n==="unknown")throw new Error("Unable to recognize source file format, please specify sourceType parameter");if(n===t)return e;let i;switch(n){case"gpx":let o=await this.parseGPX(e);if(!o)throw new Error("GPX file parsing failed");i=o;break;case"fit":i=await this.parseFIT(e);break;case"tcx":i=await this.parseTCX(e);break;default:throw new Error(`Unsupported source file format: ${n}`)}let s;switch(n){case"gpx":s=await this.convertGPXToSport(i);break;case"fit":s=await this.convertFITToSport(i);break;case"tcx":s=await this.convertTCXToSport(i);break;default:throw new Error(`Unsupported source file format conversion: ${n}`)}switch(t){case"gpx":let o=await this.convertSportToGPX(s);return await this.encodeGPX(o);case"fit":let a=await this.convertSportToFIT(s);return await this.encodeFIT(a);case"tcx":let c=await this.convertSportToTCX(s);return await this.encodeTCX(c);default:throw new Error(`Unsupported target file format: ${t}`)}}catch(n){let i=r||"auto-detect";throw new Error(`${i} to ${t.toUpperCase()} failed: ${n.message}`)}}detectFormat(e){let t=e.toString("utf-8",0,Math.min(1024,e.length));if(e.length>=12&&e.toString("ascii",8,12)===".FIT")return"fit";if(t.includes("<?xml")){if(t.includes("<gpx")||t.includes("http://www.topografix.com/GPX/"))return"gpx";if(t.includes("<TrainingCenterDatabase")||t.includes("http://www.garmin.com/xmlschemas/TrainingCenterDatabase/"))return"tcx"}return"unknown"}async parseFile(e,t){let r=t||this.detectFormat(e);if(r==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");switch(r){case"gpx":let n=await this.parseGPX(e);if(!n)throw new Error("GPX parsing failed");return n;case"fit":return await this.parseFIT(e);case"tcx":return await this.parseTCX(e);default:throw new Error(`Unsupported file format: ${r}`)}}async parseToSport(e,t){let r=t||this.detectFormat(e);if(r==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");switch(r){case"gpx":let n=await this.parseGPX(e);if(!n)throw new Error("GPX parsing failed");return this.convertGPXToSport(n);case"fit":let i=await this.parseFIT(e);return this.convertFITToSport(i);case"tcx":let s=await this.parseTCX(e);return this.convertTCXToSport(s);default:throw new Error(`Unsupported file format: ${r}`)}}getSportProcessor(){return this.sportProcessor}getGPXDecoder(){return this.gpxDecoder}getGPXEncoder(){return this.gpxEncoder}getFITDecoder(){return this.fitDecoder}getFITEncoder(){return this.fitEncoder}getTCXDecoder(){return this.tcxDecoder}getTCXEncoder(){return this.tcxEncoder}async destroy(){await this.gpxDecoder.destroy(),await this.fitDecoder.destroy(),await this.tcxDecoder.destroy(),await this.sportProcessor.destroy()}};var Pn=O;export{ue as AbstractSourceConverter,ce as ActivityConverter,pe as ActivityLapConverter,de as ActivityListConverter,ge as AstGenerateProcessor,be as BaseFITMessageConverter,Ie as BaseFITMiddleware,v as BaseFITStructurePlugin,f as BaseTCXConverter,E as BaseTCXMiddleware,ye as CompleteProcessor,he as ConvertProcessor,k as CourseStructurePlugin,me as ExtensionsConverter,P as FITDecoder,w as FITEncoder,A as FileHeaderPlugin,D as GPXDecoder,X as GPXEncoder,le as MultiSportSessionConverter,Ae as PipelineStage,se as PositionConverter,F as SessionStructurePlugin,R as TCXDecoder,M as TCXEncoder,Oe as TCXEnhancementMiddleware,Me as TCXPerformanceMiddleware,je as TCXPipelineStage,Le as TCXValidationMiddleware,fe as TokenizeProcessor,ae as TrackConverter,O as TrackSwap,oe as TrackpointConverter,Pn as default,ut as registerDefaultMiddlewares,Br as registerDefaultTCXMiddlewares};
|
|
26
|
+
`)}buildWorkouts(e){return"<Workouts></Workouts>"}buildCourses(e){return"<Courses></Courses>"}buildAuthor(e){let t=["<Author>"];return this.addOptionalElement(t,"Name",e.Name),t.push("</Author>"),t.join("")}buildExtensions(e){let t=this.buildExtensionContent(e);return t?`<Extensions>${t}</Extensions>`:""}buildExtensionContent(e){return Object.entries(e).filter(([t])=>!t.startsWith("xmlns")).map(([t,r])=>{if(r&&typeof r=="object"){let n=this.buildExtensionContent(r);return`<${t}>${n}</${t}>`}else if(r!=null)return`<${t}>${this.escapeXML(String(r))}</${t}>`;return""}).filter(t=>t).join("")}formatTime(e){return typeof e=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)?e:He(e).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}addOptionalElement(e,t,r,n){if(r!=null&&r!==""){let i=n?n(r):this.escapeXML(r);e.push(`<${t}>${i}</${t}>`)}}addOptionalNumericElement(e,t,r){r!=null&&!isNaN(r)&&e.push(`<${t}>${r}</${t}>`)}isValidCoordinate(e,t){return e!=null&&t!==void 0&&t!==null&&!isNaN(e)&&!isNaN(t)}formatCoordinate(e){return this.roundTo(e,6).toString()}roundTo(e,t){let r=Math.pow(10,t);return Math.round(e*r)/r}escapeXML(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}escapeXMLAttribute(e){return typeof e!="string"?String(e||""):e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/\r/g," ").replace(/\n/g," ").replace(/\t/g,"	")}deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(r=>this.deepClone(r));let t={};for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=this.deepClone(e[r]));return t}encoder(e){return this.encode(e)}};var A=class extends y{convertPoints(e){return e.map(t=>this.convertPoint(t)).filter(t=>t!==void 0)}convertTime(e){if(e){if(typeof e=="number")return e;if(e instanceof Date)return e.getTime();if(typeof e=="string"){let t=new Date(e);return isNaN(t.getTime())?void 0:t.getTime()}}}calculateDistance(e){if(e.length<2)return;let t=0;for(let r=1;r<e.length;r++){let n=e[r-1],i=e[r],s=6371e3,o=n.lat*Math.PI/180,a=i.lat*Math.PI/180,p=(i.lat-n.lat)*Math.PI/180,d=(i.lon-n.lon)*Math.PI/180,l=Math.sin(p/2)*Math.sin(p/2)+Math.cos(o)*Math.cos(a)*Math.sin(d/2)*Math.sin(d/2),u=2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l));t+=s*u}return t}calculateDuration(e){var n,i;if(e.length<2)return;let t=(n=e[0])==null?void 0:n.time,r=(i=e[e.length-1])==null?void 0:i.time;if(!(!t||!r))return Math.round((r-t)/1e3)}},k=class{constructor(){this.version="1.0.0";this.priority=100}supports(e){return this.supportedTags.includes(e)}async initialize(e){e.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(e){e.metadata.delete(`plugin:${this.name}:initialized`)}async validate(e){return!0}convertTimeToDate(e){return e?new Date(e):new Date}convertTimeToString(e){return this.convertTimeToDate(e).toISOString()}ensureValidCoordinates(e,t){return e>=-90&&e<=90&&t>=-180&&t<=180}round(e,t=6){let r=Math.pow(10,t);return Math.round(e*r)/r}};var Ve={heartrate:"heartRate","gpxtpx:hr":"heartRate","ns3:hr":"heartRate","gpxdata:hr":"heartRate","gpxdata:cadence":"cadence","gpxtpx:cad":"cadence","ns3:cad":"cadence",cadence:"cadence","gpxtpx:speed":"speed","ns3:speed":"speed",speed:"speed",power:"power","gpxdata:power":"power","gpxpx:PowerInWatts":"power",PowerInWatts:"power","gpxtpx:temp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:atemp":"atemp","gpxx:Temperature":"temperature","gpxx:Depth":"depth"},De=c=>c*(180/Math.pow(2,31));import M from"dayjs";function ze(c,e=0){let t=Math.pow(10,e);return Math.round(c*t)/t}var ve=class extends A{constructor(){super(...arguments);this.name="gpx-to-sport-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=t=>{let r={};return Object.entries(t).forEach(([n,i])=>{if(typeof i<"u"&&i!=="undefined"){let s=Ve[n]||n;r[s]=this.autoNumber(i)}}),r}}convert(t,r){if(r.sourceFormat!=="gpx")return;let n=r.sourceData;return this.convertGPX(n)}convertGPX(t){let r={metadata:{originType:"GPX",creator:t.creator,fileType:"gpx"}};return t.wpt&&(r.points=this.convertWpts2Points(t.wpt)),t.trk&&(r.tracks=t.trk.map(n=>{var i;return{name:n.name,trackseg:((i=n.trkseg)==null?void 0:i.map(s=>({name:n.name,points:s.trkpt?this.convertWpts2Points(s.trkpt):[]})))||[]}})),t.rte&&(r.routes=t.rte.map(n=>({name:n.name,points:n.rtept?this.convertWpts2Points(n.rtept):[]}))),r}convertPoint(t){if(t.lat==null||t.lon==null)return;let{extensions:r}=t,n=r?this.convertGPXExtensions(r):{};return{lat:t.lat,lon:t.lon,ele:t.ele,heartRate:t==null?void 0:t.heartRate,speed:t==null?void 0:t.speed,power:t==null?void 0:t.power,cadence:t==null?void 0:t.cadence,time:this.convertTime(t.time),...n}}convertWpts2Points(t){let r=[];for(let n=0;n<t.length;n++){let i=t[n];if(i.lat!=null&&i.lon!=null){let s=this.convertPoint(i);s&&r.push(s)}}return r}autoNumber(t){return typeof t=="string"&&t.trim()!==""&&!isNaN(t)?Number(t):t}},xe=class extends A{constructor(){super(...arguments);this.name="fit-to-sport-converter";this.supportedTags=["fit"]}convert(t,r){if(r.sourceFormat!=="fit")return;let n=r.sourceData;return this.convertFIT(n)}convertFIT(t){var n,i;let r={metadata:{originType:"FIT",fileType:"fit"}};if((n=t.sessionMesgs)!=null&&n.length){r.tracks=[];for(let s of t.sessionMesgs)r.tracks.push({name:s.event,startTime:s.startTime?M(s.startTime).valueOf():void 0,distance:s.totalDistance,duration:s.totalElapsedTime,sport:s.sport,trackseg:this.convertFITLap2Trackseg(s==null?void 0:s.lapMesgs),__fit__sessionMesgType:s})}else if((i=t.courseMesgs)!=null&&i.length){r.routes=[];for(let s of t.courseMesgs)r.routes.push({name:s.event,points:this.convertLap2Points(s==null?void 0:s.lapMesgs)})}return r}convertPoint(t){let{positionLong:r,positionLat:n,altitude:i,timestamp:s,heartRate:o,cadence:a,distance:p,power:d,enhancedAltitude:l,enhancedSpeed:u,temperature:T,...g}=t;if(!(r==null||n==null))return{lat:ze(De(Number(n)),6),lon:ze(De(Number(r)),6),ele:i,heartRate:o,power:d,cadence:a,temperature:T,time:s?M(s).valueOf():void 0,...g}}convertFITLap2Trackseg(t){var n;let r=[];if(!(t!=null&&t.length))return[];for(let i of t){let s=((n=i==null?void 0:i.recordMesgs)==null?void 0:n.map(o=>this.convertPoint(o)).filter(o=>o!==void 0))||[];r.push({points:s,duration:i.totalElapsedTime,distance:i.totalDistance,startTime:i.startTime?M(i.startTime).valueOf():void 0,endTime:i.startTime&&i.totalElapsedTime?M(i.startTime).add(i.totalElapsedTime,"second").valueOf():void 0,avgSpeed:i.avgSpeed,maxSpeed:i.maxSpeed,avgCadenceBpm:i.avgCadence,maxCadenceBpm:i.maxCadence,avgPower:i.avgPower,maxPower:i.maxPower,totalAscent:i.totalAscent,totalDescent:i.totalDescent,calories:i.totalCalories,__fit__lapMesgType:i})}return r}convertLap2Points(t){var n;let r=[];if(!(t!=null&&t.length))return[];for(let i of t){let s=((n=i.recordMesgs)==null?void 0:n.map(o=>this.convertPoint(o)).filter(o=>o!==void 0))||[];s.length&&(r=[...r,...s])}return r}},Ce=class extends A{constructor(){super(...arguments);this.name="tcx-to-sport-converter";this.supportedTags=["tcx"]}convert(t,r){if(r.sourceFormat!=="tcx")return;let n=r.sourceData;return this.convertTCX(n)}convertTCX(t){var n,i,s,o;let r={metadata:{originType:"TCX",fileType:"tcx"}};if((i=(n=t.Activities)==null?void 0:n.Activity)!=null&&i.length){r.tracks=[];for(let a of t.Activities.Activity)r.tracks.push({name:a.Id,sport:a.Sport,trackseg:this.convertLap2Trackseg(a.Lap)})}if((o=(s=t.Courses)==null?void 0:s.Course)!=null&&o.length){r.routes=[];for(let a of t.Courses.Course){let p=a.Track||[];for(let d of p)r.routes.push({name:a.Name||"",points:this.convertTCXTrack(d)})}}return r}convertPoint(t){let{Position:r,Time:n,DistanceMeters:i,AltitudeMeters:s}=t;if(!(!(r!=null&&r.LatitudeDegrees)||!(r!=null&&r.LongitudeDegrees)||r.LatitudeDegrees===""||r.LongitudeDegrees===""))return{lat:Number(r.LatitudeDegrees),lon:Number(r.LongitudeDegrees),time:n?M(n).valueOf():void 0,distance:i,ele:s}}convertLap2Trackseg(t){var n,i,s,o;let r=[];for(let a of t)if(a.Track){for(let p of a.Track)if(p.Trackpoint){let d=p.Trackpoint.map(u=>this.convertPoint(u)).filter(u=>u!==void 0),l={duration:a.TotalTimeSeconds,distance:a.DistanceMeters,startTime:(n=d==null?void 0:d[0])==null?void 0:n.time,endTime:(i=d==null?void 0:d[d.length-1])==null?void 0:i.time,avgHeartRateBpm:a==null?void 0:a.AverageHeartRateBpm,maxHeartRateBpm:a==null?void 0:a.MaximumHeartRateBpm,maxSpeed:a.MaximumSpeed,calories:a.Calories,__tcx__Intensity:a==null?void 0:a.Intensity,__tcx__TriggerMethod:a==null?void 0:a.TriggerMethod,avgCadenceBpm:(s=a==null?void 0:a.Cadence)==null?void 0:s.Low,maxCadenceBpm:(o=a==null?void 0:a.Cadence)==null?void 0:o.High,points:d};r.push(l)}}return r}convertTCXTrack(t){return t.Trackpoint?t.Trackpoint.map(r=>this.convertPoint(r)).filter(r=>r!==void 0):[]}};import at from"dayjs";function Ue(c){return Math.round(c*(Math.pow(2,31)/180))}var Pe=class extends k{constructor(){super(...arguments);this.name="sport-to-gpx-encoder";this.supportedTags=["gpx"]}encode(t,r){var i,s,o,a,p,d,l;if(r.targetFormat!=="gpx")return;let n={version:"1.1",creator:((i=t.metadata)==null?void 0:i.creator)||"TrackSwap",metadata:{name:(s=t==null?void 0:t.metadata)==null?void 0:s.fileName,time:(o=t==null?void 0:t.metadata)!=null&&o.date?at((a=t==null?void 0:t.metadata)==null?void 0:a.date).toDate():void 0}};return(p=t.points)!=null&&p.length&&(n.wpt=this.convertPoints2Wpts(t.points)),(d=t.routes)!=null&&d.length&&(n.rte=t.routes.map(u=>this.convertRoute2GPXRoute(u))),(l=t.tracks)!=null&&l.length&&(n.trk=t.tracks.map(u=>this.convertTrack2GPXTrack(u))),n}convertPoints2Wpts(t){return t==null?void 0:t.filter(r=>!!r.lat&&!!r.lon).map(r=>({lat:r.lat,lon:r.lon,ele:r==null?void 0:r.ele,time:r!=null&&r.time?this.convertTimeToDate(r.time):void 0,speed:r==null?void 0:r.speed,geoidheight:r==null?void 0:r.geoidheight,name:r==null?void 0:r.name,cmt:r==null?void 0:r.cmt,desc:r==null?void 0:r.desc,type:r==null?void 0:r.type,hdop:r==null?void 0:r.hdop,vdop:r==null?void 0:r.vdop,pdop:r==null?void 0:r.pdop,ageofdgpsdata:r==null?void 0:r.ageofdgpsdata,magvar:r.magvar,extensions:this.extractGPXExtensions(r)}))}convertRoute2GPXRoute(t){return{name:t==null?void 0:t.name,cmt:t==null?void 0:t.GPX_cmt,desc:t==null?void 0:t.GPX_desc,number:t==null?void 0:t.GPX_number,type:t==null?void 0:t.GPX_type,rtept:t.points?this.convertPoints2Wpts(t.points):[]}}convertTrack2GPXTrack(t){var r;return{name:t==null?void 0:t.name,cmt:t==null?void 0:t.GPX_cmt,desc:t==null?void 0:t.GPX_desc,src:t==null?void 0:t.GPX_src,number:t==null?void 0:t.GPX_number,type:t==null?void 0:t.GPX_type,trkseg:((r=t.trackseg)==null?void 0:r.map(n=>{var i;return{trkpt:(i=n==null?void 0:n.points)!=null&&i.length?this.convertPoints2Wpts(n.points):[]}}))||[]}}extractGPXExtensions(t){let r={},n={};return typeof(t==null?void 0:t.heartRate)<"u"&&(n["gpxtpx:hr"]=t.heartRate),typeof(t==null?void 0:t.cadence)<"u"&&(n["gpxtpx:cad"]=t.cadence),typeof(t==null?void 0:t.temperature)<"u"&&(n["gpxtpx:atemp"]=t.temperature),Object.keys(n).length>0&&(r["gpxtpx:TrackPointExtension"]=n),typeof(t==null?void 0:t.power)<"u"&&(r["gpxpx:PowerExtension"]={"gpxpx:PowerInWatts":t.power}),Object.keys(r).length>0?r:void 0}},we=class extends k{constructor(){super(...arguments);this.name="sport-to-fit-encoder";this.supportedTags=["fit"]}encode(t,r){var i,s,o;if(r.targetFormat!=="fit")return;let n={};return(i=t.tracks)!=null&&i.length&&(n.sessionMesgs=(s=t==null?void 0:t.tracks)==null?void 0:s.map(a=>this.convertTrack2FITSession(a))),(o=t.routes)!=null&&o.length&&(n.courseMesgs=t.routes.map(a=>this.convertRoute2FITCourse(a))),n}convertTrack2FITSession(t){var n;return{event:(t==null?void 0:t.name)||"session",sport:(t==null?void 0:t.sport)||"generic",startTime:t.startTime?this.convertTimeToString(t.startTime):this.convertTimeToString(void 0),totalDistance:t.distance,totalElapsedTime:t.duration,lapMesgs:((n=t.trackseg)==null?void 0:n.map(i=>this.convertSeg2FITLap(i)))||[]}}convertSeg2FITLap(t){var n;return{startTime:t.startTime?this.convertTimeToString(t.startTime):this.convertTimeToString(void 0),totalElapsedTime:t.duration,totalDistance:t.distance,avgSpeed:t.avgSpeed,maxSpeed:t.maxSpeed,avgCadence:t.avgCadenceBpm,maxCadence:t.maxCadenceBpm,avgPower:t.avgPower,maxPower:t.maxPower,totalAscent:t.totalAscent,totalDescent:t.totalDescent,totalCalories:t.calories,recordMesgs:((n=t.points)==null?void 0:n.map(i=>this.convertPoint2FITRecord(i)))||[]}}convertPoint2FITRecord(t){return{timestamp:t.time?this.convertTimeToString(t.time):this.convertTimeToString(void 0),positionLat:Ue(t.lat),positionLong:Ue(t.lon),altitude:t.ele,speed:t.speed,power:t.power,heartRate:t.heartRate,cadence:t.cadence,temperature:t.temperature,distance:t.distance,enhancedSpeed:t.enhancedSpeed,enhancedAltitude:t.enhancedAltitude,accumulatedPower:t.accumulatedPower}}convertRoute2FITCourse(t){return{event:t.name||"course",lapMesgs:t.points?[this.convertPoints2FITLap(t.points)]:[]}}convertPoints2FITLap(t){let r=t[0],n=t[t.length-1],i=r!=null&&r.time?this.convertTimeToString(r.time):this.convertTimeToString(void 0),s=r!=null&&r.time&&(n!=null&&n.time)?Math.round((n.time-r.time)/1e3):0,o=(n==null?void 0:n.distance)||0;return{startTime:i,totalElapsedTime:s,totalDistance:o,recordMesgs:t.map(a=>this.convertPoint2FITRecord(a))}}},Ee=class extends k{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(t,r){var i,s,o;if(r.targetFormat!=="tcx")return;let n={Author:{Name:((i=t.metadata)==null?void 0:i.creator)||"TrackSwap"}};return(s=t.tracks)!=null&&s.length&&(n.Activities={Activity:t.tracks.map(a=>this.convertTrack2TCXActivity(a))}),(o=t.routes)!=null&&o.length&&(n.Courses={Course:t.routes.map(a=>this.convertRoute2TCXCourse(a))}),n}convertTrack2TCXActivity(t){var n;let r="Other";return(t.sport==="Running"||t.sport==="Biking")&&(r=t.sport),{Id:t.name||`Activity_${Date.now()}`,Sport:r,Lap:((n=t.trackseg)==null?void 0:n.map(i=>this.convertSeg2TCXLap(i)))||[]}}convertSeg2TCXLap(t){let r={TotalTimeSeconds:t.duration,DistanceMeters:t.distance,MaximumSpeed:t.maxSpeed,Calories:t.calories,AverageHeartRateBpm:t.avgHeartRateBpm,MaximumHeartRateBpm:t.maxHeartRateBpm,Intensity:t.__tcx__Intensity||"Active",TriggerMethod:t.__tcx__TriggerMethod||"Manual",Track:t.points?[this.convertPoints2TCXTrack(t.points)]:[]};return(t.avgCadenceBpm!==void 0||t.maxCadenceBpm!==void 0)&&(r.Cadence={Low:t.avgCadenceBpm||0,High:t.maxCadenceBpm||0}),r}convertPoints2TCXTrack(t){return{Trackpoint:t.map(r=>this.convertPoint2TCXTrackpoint(r))}}convertPoint2TCXTrackpoint(t){let r={Time:t.time?this.convertTimeToString(t.time):this.convertTimeToString(void 0),Position:{LatitudeDegrees:t.lat.toString(),LongitudeDegrees:t.lon.toString()},AltitudeMeters:t.ele,DistanceMeters:t.distance};return t.heartRate&&(r.HeartRateBpm=t.heartRate),r}convertRoute2TCXCourse(t){return{Name:t.name||`Course_${Date.now()}`,Track:t.points?[this.convertPoints2TCXTrack(t.points)]:[]}}};var be=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new ve),this.registerConverter(new xe),this.registerConverter(new Ce)}registerDefaultEncoders(){this.registerEncoder(new Pe),this.registerEncoder(new we),this.registerEncoder(new Ee)}registerConverter(e){this.converters.set(e.name,e)}registerEncoder(e){this.encoders.set(e.name,e)}async convertToSport(e,t){let r={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:t,sourceData:e,performance:{startTime:Date.now()}};try{let n=this.findConverter(t);if(!n)throw new Error(`No converter found for format "${t}"`);let i=Date.now(),s=n.convert({},r);if(r.performance.convertTime=Date.now()-i,!s)throw new Error(`Converter "${n.name}" returned empty result`);return r.result=s,r.performance.endTime=Date.now(),r.stats.endTime=Date.now(),s}catch(n){throw r.errors.push(n),n}}async encodeSport(e,t){let r={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:t,performance:{startTime:Date.now()}};try{let n=this.findEncoder(t);if(!n)throw new Error(`No encoder found for format "${t}"`);let i=Date.now(),s=n.encode(e,r);if(r.performance.encodeTime=Date.now()-i,!s)throw new Error(`Encoder "${n.name}" returned empty result`);return r.result=s,r.performance.endTime=Date.now(),r.stats.endTime=Date.now(),s}catch(n){throw r.errors.push(n),n}}findConverter(e){return Array.from(this.converters.values()).find(t=>{var r;return(r=t.supportedTags)==null?void 0:r.includes(e)})}findEncoder(e){return Array.from(this.encoders.values()).find(t=>{var r;return(r=t.supportedTags)==null?void 0:r.includes(e)})}async destroy(){this.converters.clear(),this.encoders.clear()}};var L=class{constructor(){this.gpxDecoder=new E,this.gpxEncoder=new b,this.fitDecoder=new x,this.fitEncoder=new P,this.tcxDecoder=new S,this.tcxEncoder=new I,this.sportProcessor=new be}async parseGPX(e){try{return await this.gpxDecoder.parserByBuffer(e)}catch(t){throw new Error(`GPX parsing failed: ${t.message}`)}}async parseGPXString(e){let t=Buffer.from(e,"utf-8");return this.parseGPX(t)}async encodeGPX(e){try{return await this.gpxEncoder.encode(e)}catch(t){throw new Error(`GPX encoding failed: ${t.message}`)}}encodeGPXString(e){try{return this.gpxEncoder.encodeToString(e)}catch(t){throw new Error(`GPX encoding failed: ${t.message}`)}}async parseFIT(e){try{return await this.fitDecoder.parseByBuffer(e)}catch(t){throw new Error(`FIT parsing failed: ${t.message}`)}}async encodeFIT(e){try{return await this.fitEncoder.encode(e)}catch(t){throw new Error(`FIT encoding failed: ${t.message}`)}}async encodeFITCourse(e){try{return await this.fitEncoder.encodeCourse(e)}catch(t){throw new Error(`FIT Course encoding failed: ${t.message}`)}}async parseTCX(e){try{let t=await this.tcxDecoder.parseByBuffer(e);if(!t)throw new Error("TCX parsing result is empty");return t}catch(t){throw new Error(`TCX parsing failed: ${t.message}`)}}async parseTCXString(e){let t=Buffer.from(e,"utf-8");return this.parseTCX(t)}async encodeTCX(e){try{return await this.tcxEncoder.encode(e)}catch(t){throw new Error(`TCX encoding failed: ${t.message}`)}}async encodeTCXString(e){try{return await this.tcxEncoder.encodeToString(e)}catch(t){throw new Error(`TCX encoding failed: ${t.message}`)}}async convertGPXToSport(e){return await this.sportProcessor.convertToSport(e,"gpx")}async convertFITToSport(e){return await this.sportProcessor.convertToSport(e,"fit")}async convertTCXToSport(e){return await this.sportProcessor.convertToSport(e,"tcx")}async convertSportToGPX(e){return await this.sportProcessor.encodeSport(e,"gpx")}async convertSportToFIT(e){return await this.sportProcessor.encodeSport(e,"fit")}async convertSportToTCX(e){return await this.sportProcessor.encodeSport(e,"tcx")}async convertFile(e,t,r){try{let n=r||this.detectFormat(e);if(n==="unknown")throw new Error("Unable to recognize source file format, please specify sourceType parameter");if(n===t)return e;let i;switch(n){case"gpx":let o=await this.parseGPX(e);if(!o)throw new Error("GPX file parsing failed");i=o;break;case"fit":i=await this.parseFIT(e);break;case"tcx":i=await this.parseTCX(e);break;default:throw new Error(`Unsupported source file format: ${n}`)}let s;switch(n){case"gpx":s=await this.convertGPXToSport(i);break;case"fit":s=await this.convertFITToSport(i);break;case"tcx":s=await this.convertTCXToSport(i);break;default:throw new Error(`Unsupported source file format conversion: ${n}`)}switch(t){case"gpx":let o=await this.convertSportToGPX(s);return await this.encodeGPX(o);case"fit":let a=await this.convertSportToFIT(s);return await this.encodeFIT(a);case"tcx":let p=await this.convertSportToTCX(s);return await this.encodeTCX(p);default:throw new Error(`Unsupported target file format: ${t}`)}}catch(n){let i=r||"auto-detect";throw new Error(`${i} to ${t.toUpperCase()} failed: ${n.message}`)}}detectFormat(e){let t=e.toString("utf-8",0,Math.min(1024,e.length));if(e.length>=12&&e.toString("ascii",8,12)===".FIT")return"fit";if(t.includes("<?xml")){if(t.includes("<gpx")||t.includes("http://www.topografix.com/GPX/"))return"gpx";if(t.includes("<TrainingCenterDatabase")||t.includes("http://www.garmin.com/xmlschemas/TrainingCenterDatabase/"))return"tcx"}return"unknown"}async parseFile(e,t){let r=t||this.detectFormat(e);if(r==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");switch(r){case"gpx":let n=await this.parseGPX(e);if(!n)throw new Error("GPX parsing failed");return n;case"fit":return await this.parseFIT(e);case"tcx":return await this.parseTCX(e);default:throw new Error(`Unsupported file format: ${r}`)}}async parseToSport(e,t){let r=t||this.detectFormat(e);if(r==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");switch(r){case"gpx":let n=await this.parseGPX(e);if(!n)throw new Error("GPX parsing failed");return this.convertGPXToSport(n);case"fit":let i=await this.parseFIT(e);return this.convertFITToSport(i);case"tcx":let s=await this.parseTCX(e);return this.convertTCXToSport(s);default:throw new Error(`Unsupported file format: ${r}`)}}getSportProcessor(){return this.sportProcessor}getGPXDecoder(){return this.gpxDecoder}getGPXEncoder(){return this.gpxEncoder}getFITDecoder(){return this.fitDecoder}getFITEncoder(){return this.fitEncoder}getTCXDecoder(){return this.tcxDecoder}getTCXEncoder(){return this.tcxEncoder}async destroy(){await this.gpxDecoder.destroy(),await this.fitDecoder.destroy(),await this.tcxDecoder.destroy(),await this.sportProcessor.destroy()}};var yn=L;export{x as FITDecoder,P as FITEncoder,E as GPXDecoder,b as GPXEncoder,ie as PipelineStage,S as TCXDecoder,I as TCXEncoder,L as TrackSwap,yn as default,Ge as registerDefaultMiddlewares};
|
package/dist/sport/base.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { IPlugin, IConverterPlugin, IMiddlewarePlugin, BaseConverter, BaseMiddleware, IProcessingContext } from "../core/base.js";
|
|
2
|
-
import {
|
|
2
|
+
import { ActivityType, ActivityPointType, ActivityRouteSegType, ActivityTrackType, TokenAST } from "../types.js";
|
|
3
3
|
export interface SportContext extends IProcessingContext {
|
|
4
4
|
sourceFormat: string;
|
|
5
5
|
sourceData: any;
|
|
6
|
-
result?:
|
|
6
|
+
result?: ActivityType;
|
|
7
7
|
performance: {
|
|
8
8
|
startTime: number;
|
|
9
9
|
convertTime?: number;
|
|
@@ -22,29 +22,29 @@ export interface SportEncodingContext extends IProcessingContext {
|
|
|
22
22
|
export interface ISportPlugin extends IPlugin {
|
|
23
23
|
}
|
|
24
24
|
export interface ISportConverterPlugin extends IConverterPlugin {
|
|
25
|
-
convert(ast: TokenAST, context: SportContext):
|
|
25
|
+
convert(ast: TokenAST, context: SportContext): ActivityType | undefined;
|
|
26
26
|
}
|
|
27
27
|
export interface ISportMiddlewarePlugin extends IMiddlewarePlugin {
|
|
28
28
|
process(context: SportContext): Promise<void>;
|
|
29
29
|
}
|
|
30
30
|
export interface ISportEncoderPlugin extends IPlugin<SportEncodingContext> {
|
|
31
|
-
encode(sportData:
|
|
31
|
+
encode(sportData: ActivityType, context: SportEncodingContext): any | undefined;
|
|
32
32
|
supports(format: string): boolean;
|
|
33
33
|
priority?: number;
|
|
34
34
|
}
|
|
35
35
|
export declare abstract class BaseSportConverter extends BaseConverter<SportContext> implements ISportConverterPlugin {
|
|
36
|
-
protected convertPoints(points: any[]):
|
|
37
|
-
protected abstract convertPoint(point: any):
|
|
36
|
+
protected convertPoints(points: any[]): ActivityPointType[];
|
|
37
|
+
protected abstract convertPoint(point: any): ActivityPointType | undefined;
|
|
38
38
|
protected convertTime(time: Date | string | number | undefined): number | undefined;
|
|
39
|
-
protected calculateDistance(points:
|
|
40
|
-
protected calculateDuration(points:
|
|
39
|
+
protected calculateDistance(points: ActivityPointType[]): number | undefined;
|
|
40
|
+
protected calculateDuration(points: ActivityPointType[]): number | undefined;
|
|
41
41
|
}
|
|
42
42
|
export declare abstract class BaseSportEncoder implements ISportEncoderPlugin {
|
|
43
43
|
abstract name: string;
|
|
44
44
|
abstract supportedTags: string[];
|
|
45
45
|
version: string;
|
|
46
46
|
priority: number;
|
|
47
|
-
abstract encode(sportData:
|
|
47
|
+
abstract encode(sportData: ActivityType, context: SportEncodingContext): any | undefined;
|
|
48
48
|
supports(format: string): boolean;
|
|
49
49
|
initialize(context: SportEncodingContext): Promise<void>;
|
|
50
50
|
destroy(context: SportEncodingContext): Promise<void>;
|
|
@@ -54,11 +54,11 @@ export declare abstract class BaseSportEncoder implements ISportEncoderPlugin {
|
|
|
54
54
|
protected ensureValidCoordinates(lat: number, lon: number): boolean;
|
|
55
55
|
protected round(value: number, precision?: number): number;
|
|
56
56
|
}
|
|
57
|
-
export declare abstract class BaseSportMiddleware extends BaseMiddleware<SportContext,
|
|
57
|
+
export declare abstract class BaseSportMiddleware extends BaseMiddleware<SportContext, ActivityType> implements ISportMiddlewarePlugin {
|
|
58
58
|
abstract process(context: SportContext): Promise<void>;
|
|
59
59
|
onError(error: Error, context: SportContext): Promise<void>;
|
|
60
|
-
protected validateSportFile(sportFile:
|
|
61
|
-
protected validateTrack(track:
|
|
62
|
-
protected validateRoute(route:
|
|
63
|
-
protected validatePoint(point:
|
|
60
|
+
protected validateSportFile(sportFile: ActivityType): boolean;
|
|
61
|
+
protected validateTrack(track: ActivityTrackType): boolean;
|
|
62
|
+
protected validateRoute(route: ActivityRouteSegType): boolean;
|
|
63
|
+
protected validatePoint(point: ActivityPointType): boolean;
|
|
64
64
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { BaseSportConverter, SportContext } from "./base.js";
|
|
2
2
|
import { TokenAST } from "../types.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ActivityType, ActivityPointType } from "../types.js";
|
|
4
4
|
import { WptType } from "../GPX/types.js";
|
|
5
5
|
import { RecordMesgType } from "../FIT/types.js";
|
|
6
6
|
import { TrackpointType } from "../TCX/types.js";
|
|
7
7
|
export declare class GPXToSportConverter extends BaseSportConverter {
|
|
8
8
|
name: string;
|
|
9
9
|
supportedTags: string[];
|
|
10
|
-
convert(ast: TokenAST, context: SportContext):
|
|
10
|
+
convert(ast: TokenAST, context: SportContext): ActivityType | undefined;
|
|
11
11
|
private convertGPX;
|
|
12
|
-
protected convertPoint(point: WptType):
|
|
12
|
+
protected convertPoint(point: WptType): ActivityPointType | undefined;
|
|
13
13
|
private convertWpts2Points;
|
|
14
14
|
private convertGPXExtensions;
|
|
15
15
|
private autoNumber;
|
|
@@ -17,18 +17,18 @@ export declare class GPXToSportConverter extends BaseSportConverter {
|
|
|
17
17
|
export declare class FITToSportConverter extends BaseSportConverter {
|
|
18
18
|
name: string;
|
|
19
19
|
supportedTags: string[];
|
|
20
|
-
convert(ast: TokenAST, context: SportContext):
|
|
20
|
+
convert(ast: TokenAST, context: SportContext): ActivityType | undefined;
|
|
21
21
|
private convertFIT;
|
|
22
|
-
protected convertPoint(point: RecordMesgType):
|
|
22
|
+
protected convertPoint(point: RecordMesgType): ActivityPointType | undefined;
|
|
23
23
|
private convertFITLap2Trackseg;
|
|
24
24
|
private convertLap2Points;
|
|
25
25
|
}
|
|
26
26
|
export declare class TCXToSportConverter extends BaseSportConverter {
|
|
27
27
|
name: string;
|
|
28
28
|
supportedTags: string[];
|
|
29
|
-
convert(ast: TokenAST, context: SportContext):
|
|
29
|
+
convert(ast: TokenAST, context: SportContext): ActivityType | undefined;
|
|
30
30
|
private convertTCX;
|
|
31
|
-
protected convertPoint(point: TrackpointType):
|
|
31
|
+
protected convertPoint(point: TrackpointType): ActivityPointType | undefined;
|
|
32
32
|
private convertLap2Trackseg;
|
|
33
33
|
private convertTCXTrack;
|
|
34
34
|
}
|