npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

trackswap

v0.0.25

Published

A powerful and flexible GPX parser and encoder library for Node.js and TypeScript. TrackSwap provides comprehensive support for GPX 1.1 format with advanced features like plugin system, middleware support, and optimized performance.

Readme

TrackSwap - 多格式轨迹处理库

一个强大的多格式轨迹文件处理库,支持 GPX、FIT、TCX 文件的解析、编码和格式转换。


🌐 Language / 语言: English | 中文


🚀 特性

  • 🔄 多格式支持: GPX 1.1、FIT、TCX 格式
  • 🎯 统一转换: 任意格式之间相互转换
  • 🤖 自动检测: 智能识别文件格式
  • 🧩 扩展系统: 灵活的扩展架构,支持自定义数据处理
  • 📊 智能聚合: 默认启用运动数据聚合(心率、功率、速度等)
  • 🛡️ 类型安全: 完整的 TypeScript 支持
  • 高性能: 优化的解析和编码算法

📦 安装

npm install trackswap

🎯 快速开始

基本使用

import { TrackSwap } from 'trackswap';
import fs from 'fs';

const trackSwap = new TrackSwap();

// 解析 GPX 文件
const gpxBuffer = fs.readFileSync('track.gpx');
const gpxData = await trackSwap.parseGPX(gpxBuffer);

// 解析 FIT 文件
const fitBuffer = fs.readFileSync('activity.fit');
const fitData = await trackSwap.parseFIT(fitBuffer);

// 解析 TCX 文件
const tcxBuffer = fs.readFileSync('workout.tcx');
const tcxData = await trackSwap.parseTCX(tcxBuffer);

格式转换

// 🔄 自动检测格式并转换
const gpxBuffer = await trackSwap.convertFile(anyBuffer, 'gpx');
const fitBuffer = await trackSwap.convertFile(anyBuffer, 'fit');
const tcxBuffer = await trackSwap.convertFile(anyBuffer, 'tcx');

// 🎯 指定源格式转换(提升性能)
const convertedBuffer = await trackSwap.convertFile(
  sourceBuffer, 
  'fit',      // 目标格式
  'gpx'       // 源格式(可选)
);

自动解析

// 🤖 自动检测格式并解析
const parsedData = await trackSwap.parseFile(buffer);

// 🏃‍♂️ 解析并转换为统一的运动数据格式
const sportData = await trackSwap.parseToActivity(buffer);

扩展系统

import { TrackSwap } from 'trackswap';
import { SlopeExtension } from 'trackswap/extensions';

// 🧩 使用扩展增强功能
const trackSwap = new TrackSwap()
  .extend(new SlopeExtension()); // 添加坡度计算

// 📊 默认已启用基础指标聚合(心率、功率、速度、踏频等)
const result = await trackSwap.parseGPX(gpxBuffer);
// result 包含完整的聚合数据和坡度信息

// 🔗 链式添加多个扩展
const enhancedTrackSwap = new TrackSwap()
  .extend(new SlopeExtension())
  .extend(new CustomExtension());

📖 详细使用指南

扩展系统

详细的扩展开发和使用指南请参考:扩展系统文档

1. 文件解析

GPX 文件处理

// 从 Buffer 解析
const gpxData = await trackSwap.parseGPX(buffer);

// 从字符串解析
const gpxData = await trackSwap.parseGPXString(xmlString);

// 编码为 Buffer
const buffer = await trackSwap.encodeGPX(gpxData);

// 编码为字符串
const xmlString = trackSwap.encodeGPXString(gpxData);

FIT 文件处理

// 解析 FIT 文件
const fitData = await trackSwap.parseFIT(buffer);

// 编码为 Activity 文件
const activityBuffer = await trackSwap.encodeFIT(fitData);

// 编码为 Course 文件
const courseBuffer = await trackSwap.encodeFITCourse(fitData);

TCX 文件处理

// 从 Buffer 解析
const tcxData = await trackSwap.parseTCX(buffer);

// 从字符串解析
const tcxData = await trackSwap.parseTCXString(xmlString);

// 编码为 Buffer
const buffer = await trackSwap.encodeTCX(tcxData);

// 编码为字符串
const xmlString = await trackSwap.encodeTCXString(tcxData);

2. 格式转换

统一转换方法

// 🔄 自动检测并转换
const result = await trackSwap.convertFile(sourceBuffer, 'gpx');

// 🎯 指定格式转换
const result = await trackSwap.convertFile(sourceBuffer, 'fit', 'gpx');

// 📊 支持的转换组合
// GPX ↔ FIT ↔ TCX (任意格式之间相互转换)

ActivityType 统一格式

// 转换为统一的运动数据格式
const gpxActivity = await trackSwap.convertGPXToActivity(gpxData);
const fitActivity = await trackSwap.convertFITToActivity(fitData);
const tcxActivity = await trackSwap.convertTCXToActivity(tcxData);

// 从统一格式转换回具体格式
const gpxData = await trackSwap.convertActivityToGPX(sportData);
const fitData = await trackSwap.convertActivityToFIT(sportData);
const tcxData = await trackSwap.convertActivityToTCX(sportData);

3. 智能解析

// 🤖 自动检测格式
const format = trackSwap.detectFormat(buffer);
console.log(`检测到格式: ${format}`); // 'gpx' | 'fit' | 'tcx' | 'unknown'

// 📂 统一解析方法
const parsedData = await trackSwap.parseFile(buffer);
const parsedData = await trackSwap.parseFile(buffer, 'gpx'); // 指定格式

// 🏃‍♂️ 解析为统一格式
const sportData = await trackSwap.parseToActivity(buffer);
const sportData = await trackSwap.parseToActivity(buffer, 'fit'); // 指定格式

🔧 API 参考

TrackSwap 类

解析方法

| 方法 | 说明 | 参数 | 返回值 | |------|------|------|--------| | parseGPX(buffer) | 解析 GPX Buffer | Buffer | Promise<GPX11Type \| undefined> | | parseGPXString(xml) | 解析 GPX 字符串 | string | Promise<GPX11Type \| undefined> | | parseFIT(buffer) | 解析 FIT Buffer | Buffer | Promise<FITFileType> | | parseTCX(buffer) | 解析 TCX Buffer | Buffer | Promise<TCXFileType> | | parseTCXString(xml) | 解析 TCX 字符串 | string | Promise<TCXFileType> | | parseFile(buffer, type?) | 统一解析方法 | Buffer, string? | Promise<GPX11Type \| FITFileType \| TCXFileType> | | parseToActivity(buffer, type?) | 解析为统一格式 | Buffer, string? | Promise<ActivityType> |

编码方法

| 方法 | 说明 | 参数 | 返回值 | |------|------|------|--------| | encodeGPX(data) | 编码 GPX 为 Buffer | GPX11Type | Promise<Buffer> | | encodeGPXString(data) | 编码 GPX 为字符串 | GPX11Type | string | | encodeFIT(data) | 编码 FIT 为 Buffer | FITFileType | Promise<Buffer> | | encodeFITCourse(data) | 编码 FIT Course | FITFileType | Promise<Buffer> | | encodeTCX(data) | 编码 TCX 为 Buffer | TCXFileType | Promise<Buffer> | | encodeTCXString(data) | 编码 TCX 为字符串 | TCXFileType | Promise<string> |

转换方法

| 方法 | 说明 | 参数 | 返回值 | |------|------|------|--------| | convertFile(buffer, target, source?) | 统一转换方法 | Buffer, string, string? | Promise<Buffer> | | convertGPXToActivity(data) | GPX → Activity | GPX11Type | Promise<ActivityType> | | convertFITToActivity(data) | FIT → Activity | FITFileType | Promise<ActivityType> | | convertTCXToActivity(data) | TCX → Activity | TCXFileType | Promise<ActivityType> | | convertActivityToGPX(data) | Activity → GPX | ActivityType | Promise<GPX11Type> | | convertActivityToFIT(data) | Activity → FIT | ActivityType | Promise<FITFileType> | | convertActivityToTCX(data) | Activity → TCX | ActivityType | Promise<TCXFileType> |

工具方法

| 方法 | 说明 | 参数 | 返回值 | |------|------|------|--------| | detectFormat(buffer) | 检测文件格式 | Buffer | 'gpx' \| 'fit' \| 'tcx' \| 'unknown' | | getActivityProcessor() | 获取运动处理器 | - | ActivityProcessor | | destroy() | 清理资源 | - | Promise<void> |

🌟 实际应用示例

批量格式转换

import { TrackSwap } from 'trackswap';
import fs from 'fs';
import path from 'path';

async function batchConvert(inputDir: string, outputFormat: 'gpx' | 'fit' | 'tcx') {
  const trackSwap = new TrackSwap();
  const files = fs.readdirSync(inputDir);
  
  for (const file of files) {
    try {
      const inputPath = path.join(inputDir, file);
      const buffer = fs.readFileSync(inputPath);
      
      // 🔄 自动检测并转换
      const converted = await trackSwap.convertFile(buffer, outputFormat);
      
      const outputPath = path.join(inputDir, 
        `${path.parse(file).name}.${outputFormat}`);
      fs.writeFileSync(outputPath, converted);
      
      console.log(`✅ 转换完成: ${file} → ${outputFormat}`);
    } catch (error) {
      console.error(`❌ 转换失败: ${file}`, error);
    }
  }
  
  await trackSwap.destroy();
}

// 使用示例
await batchConvert('./tracks', 'gpx');

轨迹数据分析

async function analyzeTrack(buffer: Buffer) {
  const trackSwap = new TrackSwap();
  
  // 🔍 检测格式
  const format = trackSwap.detectFormat(buffer);
  console.log(`文件格式: ${format}`);
  
  // 📊 转换为统一格式进行分析
  const sportData = await trackSwap.parseToActivity(buffer);
  
  // 分析数据
  const analysis = {
    totalDistance: sportData.summary?.totalDistance || 0,
    totalTime: sportData.summary?.totalTime || 0,
    avgSpeed: sportData.summary?.avgSpeed || 0,
    maxSpeed: sportData.summary?.maxSpeed || 0,
    trackPoints: sportData.tracks?.[0]?.segments?.[0]?.points?.length || 0
  };
  
  console.log('轨迹分析结果:', analysis);
  
  await trackSwap.destroy();
  return analysis;
}

多格式数据融合

async function mergeMultiFormatTracks(files: { buffer: Buffer, name: string }[]) {
  const trackSwap = new TrackSwap();
  const allActivityData: ActivityType[] = [];
  
  // 🔄 将所有格式转换为统一格式
  for (const file of files) {
    try {
      const sportData = await trackSwap.parseToActivity(file.buffer);
      sportData.metadata = { ...sportData.metadata, originalFile: file.name };
      allActivityData.push(sportData);
    } catch (error) {
      console.error(`解析失败: ${file.name}`, error);
    }
  }
  
  // 融合数据逻辑
  const mergedData = mergeActivityData(allActivityData);
  
  // 输出为不同格式
  const results = {
    gpx: await trackSwap.convertActivityToGPX(mergedData),
    fit: await trackSwap.convertActivityToFIT(mergedData),
    tcx: await trackSwap.convertActivityToTCX(mergedData)
  };
  
  await trackSwap.destroy();
  return results;
}

🏗️ 架构设计

TrackSwap 采用模块化架构,核心组件包括:

┌─────────────────────────────────────────────────────────────┐
│                    TrackSwap 架构图                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  🔧 核心处理模块                                             │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ • GPXDecoder/Encoder - GPX 文件处理                     │ │
│  │ • FITDecoder/Encoder - FIT 文件处理                     │ │
│  │ • TCXDecoder/Encoder - TCX 文件处理                     │ │
│  │ • ActivityProcessor - 统一格式转换处理                      │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                             │
│  🔄 转换引擎                                                │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ • GPXToActivityConverter - GPX → ActivityType            │ │
│  │ • FITToActivityConverter - FIT → ActivityType            │ │
│  │ • TCXToActivityConverter - TCX → ActivityType            │ │
│  │ • ActivityToGPXEncoder - ActivityType → GPX              │ │
│  │ • ActivityToFITEncoder - ActivityType → FIT              │ │
│  │ • ActivityToTCXEncoder - ActivityType → TCX              │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                             │
│  🎯 统一接口                                                │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ • 自动格式检测                                           │ │
│  │ • 统一解析方法                                           │ │
│  │ • 统一转换方法                                           │ │
│  │ • 生命周期管理                                           │ │
│  └─────────────────────────────────────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

🔍 支持的格式

GPX (GPS Exchange Format)

  • ✅ GPX 1.1 标准
  • ✅ 航路点 (Waypoints)
  • ✅ 路线 (Routes)
  • ✅ 轨迹 (Tracks)
  • ✅ 元数据 (Metadata)
  • ✅ 扩展属性

FIT (Flexible and Interoperable Data Transfer)

  • ✅ Activity 文件
  • ✅ Course 文件
  • ✅ 轨迹点数据
  • ✅ 心率、速度、海拔等传感器数据
  • ✅ Garmin 设备兼容

TCX (Training Center XML)

  • ✅ 训练数据
  • ✅ 运动轨迹
  • ✅ 心率区间
  • ✅ 圈速数据
  • ✅ Garmin Connect 兼容

🛠️ 开发指南

环境要求

  • Node.js >= 16
  • TypeScript >= 4.5

项目结构

src/
├── TrackSwap.ts          # 主入口类
├── activity/             # 活动处理模块
│   ├── extensions.ts     # 扩展系统核心
│   ├── slope-extension.ts # 坡度计算扩展
│   ├── processor.ts      # 活动处理器
│   └── pipeline.ts       # 数据处理管道
├── decoders/             # 解码器模块
│   ├── GPXDecoder.ts
│   ├── FITDecoder.ts
│   └── TCXDecoder.ts
├── encoders/             # 编码器模块
│   ├── GPXEncoder.ts
│   ├── FITEncoder.ts
│   └── TCXEncoder.ts
├── converters/           # 格式转换器
│   ├── GPXConverter.ts
│   ├── FITConverter.ts
│   └── TCXConverter.ts
└── types.ts              # 公共类型定义

贡献指南

  1. Fork 项目
  2. 创建特性分支
  3. 提交更改
  4. 发起 Pull Request

📄 许可证

MIT License

🙏 致谢

感谢所有贡献者和开源社区的支持!