trackswap 0.0.1 → 0.0.3

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.
Files changed (58) hide show
  1. package/README.md +322 -281
  2. package/dist/FIT/base.d.ts +61 -0
  3. package/dist/FIT/crc.d.ts +1 -0
  4. package/dist/FIT/decoder.d.ts +35 -0
  5. package/dist/FIT/encoder.d.ts +45 -0
  6. package/dist/FIT/index.d.ts +12 -0
  7. package/dist/FIT/mesg.d.ts +37 -0
  8. package/dist/FIT/middleware.d.ts +33 -0
  9. package/dist/FIT/plugins.d.ts +17 -0
  10. package/dist/FIT/processor.d.ts +34 -0
  11. package/dist/FIT/types/course_point.d.ts +56 -0
  12. package/dist/FIT/types/event.d.ts +49 -0
  13. package/dist/FIT/types/event_type.d.ts +18 -0
  14. package/dist/FIT/types/file.d.ts +23 -0
  15. package/dist/FIT/types/index.d.ts +119 -0
  16. package/dist/FIT/types/mesg_num.d.ts +105 -0
  17. package/dist/FIT/types/sport.d.ts +47 -0
  18. package/dist/FIT/types.d.ts +196 -0
  19. package/dist/FIT/util.d.ts +1 -0
  20. package/dist/GPX/base.d.ts +14 -77
  21. package/dist/GPX/converters.d.ts +12 -66
  22. package/dist/GPX/decoder.d.ts +5 -71
  23. package/dist/GPX/encoder.d.ts +4 -109
  24. package/dist/GPX/index.d.ts +1 -1
  25. package/dist/GPX/middleware.d.ts +18 -0
  26. package/dist/GPX/processor.d.ts +0 -18
  27. package/dist/GPX/types.d.ts +2 -111
  28. package/dist/TCX/base.d.ts +19 -0
  29. package/dist/TCX/converters.d.ts +51 -0
  30. package/dist/TCX/decoder.d.ts +33 -0
  31. package/dist/TCX/encoder.d.ts +41 -0
  32. package/dist/TCX/index.d.ts +13 -0
  33. package/dist/TCX/middleware.d.ts +18 -0
  34. package/dist/TCX/processor.d.ts +30 -0
  35. package/dist/TCX/types.d.ts +190 -0
  36. package/dist/TrackSwap.d.ts +37 -33
  37. package/dist/core/base.d.ts +73 -0
  38. package/dist/core/index.d.ts +2 -0
  39. package/dist/core/xml-utils.d.ts +17 -0
  40. package/dist/index.js +24 -5
  41. package/dist/sport/base.d.ts +63 -0
  42. package/dist/sport/converters.d.ts +33 -0
  43. package/dist/sport/encoders.d.ts +34 -0
  44. package/dist/sport/index.d.ts +17 -0
  45. package/dist/sport/processor.d.ts +19 -0
  46. package/dist/types.d.ts +91 -13
  47. package/package.json +25 -7
  48. package/dist/GPX/base.js +0 -83
  49. package/dist/GPX/converters.js +0 -444
  50. package/dist/GPX/decoder.js +0 -403
  51. package/dist/GPX/encoder.js +0 -510
  52. package/dist/GPX/extensions/index.js +0 -14
  53. package/dist/GPX/index.js +0 -11
  54. package/dist/GPX/processor.js +0 -187
  55. package/dist/GPX/types.js +0 -1
  56. package/dist/GPX/util.js +0 -18
  57. package/dist/TrackSwap.js +0 -84
  58. package/dist/types.js +0 -1
@@ -0,0 +1,63 @@
1
+ import { IPlugin, IConverterPlugin, IMiddlewarePlugin, BaseConverter, BaseMiddleware, IProcessingContext } from "../core/base.js";
2
+ import { SportFileType, SportPointType, SportRouteSegType, SportTrackType } from "../types.js";
3
+ export interface SportContext extends IProcessingContext {
4
+ sourceFormat: "gpx" | "fit" | "tcx";
5
+ sourceData: any;
6
+ result?: SportFileType;
7
+ performance: {
8
+ startTime: number;
9
+ convertTime?: number;
10
+ validateTime?: number;
11
+ endTime?: number;
12
+ };
13
+ }
14
+ export interface SportEncodingContext extends IProcessingContext {
15
+ targetFormat: "gpx" | "fit" | "tcx";
16
+ result?: any;
17
+ performance: {
18
+ startTime: number;
19
+ encodeTime?: number;
20
+ validateTime?: number;
21
+ endTime?: number;
22
+ };
23
+ }
24
+ export interface ISportPlugin extends IPlugin<SportContext> {
25
+ }
26
+ export interface ISportConverterPlugin extends IConverterPlugin<SportContext> {
27
+ }
28
+ export interface ISportMiddlewarePlugin extends IMiddlewarePlugin<SportContext, SportFileType> {
29
+ }
30
+ export interface ISportEncoderPlugin extends IPlugin<SportEncodingContext> {
31
+ encode(sportData: SportFileType, context: SportEncodingContext): any | undefined;
32
+ supports(format: string): boolean;
33
+ priority?: number;
34
+ }
35
+ export declare abstract class BaseSportConverter extends BaseConverter<SportContext> implements ISportConverterPlugin {
36
+ protected convertPoints(points: any[]): SportPointType[];
37
+ protected abstract convertPoint(point: any): SportPointType | undefined;
38
+ protected convertTime(time: Date | string | number | undefined): number | undefined;
39
+ protected calculateDistance(points: SportPointType[]): number | undefined;
40
+ protected calculateDuration(points: SportPointType[]): number | undefined;
41
+ }
42
+ export declare abstract class BaseSportEncoder implements ISportEncoderPlugin {
43
+ abstract name: string;
44
+ abstract supportedTags: string[];
45
+ version: string;
46
+ priority: number;
47
+ abstract encode(sportData: SportFileType, context: SportEncodingContext): any | undefined;
48
+ supports(format: string): boolean;
49
+ initialize(context: SportEncodingContext): Promise<void>;
50
+ destroy(context: SportEncodingContext): Promise<void>;
51
+ validate(context: SportEncodingContext): Promise<boolean>;
52
+ protected convertTimeToDate(time: number | undefined): Date;
53
+ protected convertTimeToString(time: number | undefined): string;
54
+ protected ensureValidCoordinates(lat: number, lon: number): boolean;
55
+ protected round(value: number, precision?: number): number;
56
+ }
57
+ export declare abstract class BaseSportMiddleware extends BaseMiddleware<SportContext, SportFileType> implements ISportMiddlewarePlugin {
58
+ onError(error: Error, context: SportContext): Promise<void>;
59
+ protected validateSportFile(sportFile: SportFileType): boolean;
60
+ protected validateTrack(track: SportTrackType): boolean;
61
+ protected validateRoute(route: SportRouteSegType): boolean;
62
+ protected validatePoint(point: SportPointType): boolean;
63
+ }
@@ -0,0 +1,33 @@
1
+ import { BaseSportConverter, SportContext } from "./base.js";
2
+ import { TokenAST } from "../types.js";
3
+ import { SportFileType, SportPointType } from "../types.js";
4
+ import { WptType } from "../GPX/types.js";
5
+ import { RecordMesgType } from "../FIT/types.js";
6
+ import { TrackpointType } from "../TCX/types.js";
7
+ export declare class GPXToSportConverter extends BaseSportConverter {
8
+ name: string;
9
+ supportedTags: string[];
10
+ convert(ast: TokenAST, context: SportContext): SportFileType | undefined;
11
+ private convertGPX;
12
+ protected convertPoint(point: WptType): SportPointType | undefined;
13
+ private convertWpts2Points;
14
+ private convertGPXExtensions;
15
+ }
16
+ export declare class FITToSportConverter extends BaseSportConverter {
17
+ name: string;
18
+ supportedTags: string[];
19
+ convert(ast: TokenAST, context: SportContext): SportFileType | undefined;
20
+ private convertFIT;
21
+ protected convertPoint(point: RecordMesgType): SportPointType | undefined;
22
+ private convertFITLap2Trackseg;
23
+ private convertLap2Points;
24
+ }
25
+ export declare class TCXToSportConverter extends BaseSportConverter {
26
+ name: string;
27
+ supportedTags: string[];
28
+ convert(ast: TokenAST, context: SportContext): SportFileType | undefined;
29
+ private convertTCX;
30
+ protected convertPoint(point: TrackpointType): SportPointType | undefined;
31
+ private convertLap2Trackseg;
32
+ private convertTCXTrack;
33
+ }
@@ -0,0 +1,34 @@
1
+ import { BaseSportEncoder, SportEncodingContext } from "./base.js";
2
+ import { SportFileType } from "../types.js";
3
+ import { GPX11Type } from "../GPX/types.js";
4
+ import { FITFileType } from "../FIT/types.js";
5
+ import { TCXFileType } from "../TCX/types.js";
6
+ export declare class SportToGPXEncoder extends BaseSportEncoder {
7
+ name: string;
8
+ supportedTags: string[];
9
+ encode(sportData: SportFileType, context: SportEncodingContext): GPX11Type | undefined;
10
+ private convertPoints2Wpts;
11
+ private convertRoute2GPXRoute;
12
+ private convertTrack2GPXTrack;
13
+ private extractGPXExtensions;
14
+ }
15
+ export declare class SportToFITEncoder extends BaseSportEncoder {
16
+ name: string;
17
+ supportedTags: string[];
18
+ encode(sportData: SportFileType, context: SportEncodingContext): FITFileType | undefined;
19
+ private convertTrack2FITSession;
20
+ private convertSeg2FITLap;
21
+ private convertPoint2FITRecord;
22
+ private convertRoute2FITCourse;
23
+ private convertPoints2FITLap;
24
+ }
25
+ export declare class SportToTCXEncoder extends BaseSportEncoder {
26
+ name: string;
27
+ supportedTags: string[];
28
+ encode(sportData: SportFileType, context: SportEncodingContext): TCXFileType | undefined;
29
+ private convertTrack2TCXActivity;
30
+ private convertSeg2TCXLap;
31
+ private convertPoints2TCXTrack;
32
+ private convertPoint2TCXTrackpoint;
33
+ private convertRoute2TCXCourse;
34
+ }
@@ -0,0 +1,17 @@
1
+ export * from "./base.js";
2
+ export * from "./converters.js";
3
+ export * from "./encoders.js";
4
+ export * from "./processor.js";
5
+ import { GPXToSportConverter, FITToSportConverter, TCXToSportConverter } from "./converters.js";
6
+ import { SportToGPXEncoder, SportToFITEncoder, SportToTCXEncoder } from "./encoders.js";
7
+ import { SportProcessor } from "./processor.js";
8
+ declare const _default: {
9
+ GPXToSportConverter: typeof GPXToSportConverter;
10
+ FITToSportConverter: typeof FITToSportConverter;
11
+ TCXToSportConverter: typeof TCXToSportConverter;
12
+ SportToGPXEncoder: typeof SportToGPXEncoder;
13
+ SportToFITEncoder: typeof SportToFITEncoder;
14
+ SportToTCXEncoder: typeof SportToTCXEncoder;
15
+ SportProcessor: typeof SportProcessor;
16
+ };
17
+ export default _default;
@@ -0,0 +1,19 @@
1
+ import { ISportConverterPlugin, ISportEncoderPlugin } from "./base.js";
2
+ import { SportFileType } from "../types.js";
3
+ import { GPX11Type } from "../GPX/types.js";
4
+ import { FITFileType } from "../FIT/types.js";
5
+ import { TCXFileType } from "../TCX/types.js";
6
+ export declare class SportProcessor {
7
+ private converters;
8
+ private encoders;
9
+ constructor();
10
+ private registerDefaultConverters;
11
+ private registerDefaultEncoders;
12
+ registerConverter(converter: ISportConverterPlugin): void;
13
+ registerEncoder(encoder: ISportEncoderPlugin): void;
14
+ convertToSport(sourceData: GPX11Type | FITFileType | TCXFileType, sourceFormat: "gpx" | "fit" | "tcx"): Promise<SportFileType>;
15
+ encodeSport(sportData: SportFileType, targetFormat: "gpx" | "fit" | "tcx"): Promise<GPX11Type | FITFileType | TCXFileType>;
16
+ private findConverter;
17
+ private findEncoder;
18
+ destroy(): Promise<void>;
19
+ }
package/dist/types.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { LapMesgType, RecordMesgType, SessionMesgType, UserProfileMesgType } from "./FIT/types.js";
2
+ import { IntensityType, TriggerMethodType } from "./TCX/types.js";
1
3
  export interface Token {
2
4
  type: "open" | "close" | "text";
3
5
  tag: string;
@@ -13,22 +15,98 @@ export interface TokenAST {
13
15
  export interface AttributeType {
14
16
  [key: string]: string;
15
17
  }
16
- /**
17
- * The latitude of the point. Decimal degrees, WGS84 datum.
18
- * @type {number} -90.0 <= value <= 90.0
19
- */
20
18
  export type LatitudeType = number;
21
- /**
22
- * The longitude of the point. Decimal degrees, WGS84 datum.
23
- * @type {number} -180.0 <= value < 180.0
24
- */
25
19
  export type LongitudeType = number;
26
- /**
27
- * Used for bearing, heading, course. Units are decimal degrees, true (not magnetic).
28
- * @type {number} 0.0 <= value < 360.0
29
-
30
- */
31
20
  export type DegreesType = number;
32
21
  export interface ExtensionsType {
33
22
  [key: string]: string | number | undefined | ExtensionsType;
34
23
  }
24
+ export interface SportFileType {
25
+ metadata?: {
26
+ originType: "GPX" | "FIT" | "TCX" | "HIJSON";
27
+ fileName?: string;
28
+ fileType?: string;
29
+ creator?: string;
30
+ date?: string;
31
+ };
32
+ points?: SportPointType[];
33
+ routes?: SportRouteSegType[];
34
+ tracks?: SportTrackType[];
35
+ __fit__UserProfileMesgs?: UserProfileMesgType[];
36
+ }
37
+ export interface SportPointType {
38
+ lat: LatitudeType;
39
+ lon: LongitudeType;
40
+ ele?: number;
41
+ time?: number;
42
+ heart?: number;
43
+ distance?: number;
44
+ accumulatedPower?: number;
45
+ speed?: number;
46
+ power?: number;
47
+ cadence?: number;
48
+ temperature?: number;
49
+ enhancedAltitude?: number;
50
+ enhancedSpeed?: number;
51
+ __fit__RecordMesgType?: RecordMesgType;
52
+ magvar?: DegreesType;
53
+ geoidheight?: number;
54
+ name?: string;
55
+ cmt?: string;
56
+ desc?: string;
57
+ src?: string;
58
+ sym?: string;
59
+ type?: string;
60
+ sat?: string;
61
+ hdop?: number;
62
+ vdop?: number;
63
+ pdop?: number;
64
+ ageofdgpsdata?: number;
65
+ dgpsid?: DegreesType;
66
+ turn?: number;
67
+ extensions?: ExtensionsType;
68
+ }
69
+ export interface SportTrackType {
70
+ name?: string;
71
+ sport?: string;
72
+ trackseg?: SportRouteSegType[];
73
+ extensions?: ExtensionsType;
74
+ startTime?: number;
75
+ startLat?: LatitudeType;
76
+ startLon?: LongitudeType;
77
+ duration?: number;
78
+ distance?: number;
79
+ endTime?: number;
80
+ endLat?: LatitudeType;
81
+ endLon?: LongitudeType;
82
+ __fit__sessionMesgType?: SessionMesgType;
83
+ }
84
+ export interface SportRouteSegType {
85
+ name?: string;
86
+ sport?: string;
87
+ points?: SportPointType[];
88
+ duration?: number;
89
+ distance?: number;
90
+ startTime?: number;
91
+ endTime?: number;
92
+ avgHeartRateBpm?: number;
93
+ maxHeartRateBpm?: number;
94
+ avgSpeed?: number;
95
+ maxSpeed?: number;
96
+ avgCadenceBpm?: number;
97
+ maxCadenceBpm?: number;
98
+ avgPower?: number;
99
+ maxPower?: number;
100
+ avgTemperature?: number;
101
+ maxTemperature?: number;
102
+ avgAltitude?: number;
103
+ maxEnhancedAltitude?: number;
104
+ totalAscent?: number;
105
+ totalDescent?: number;
106
+ calories?: number;
107
+ __tcx__Intensity?: IntensityType;
108
+ __tcx__TriggerMethod?: TriggerMethodType;
109
+ __tcx__Notes?: string;
110
+ __tcx__Extensions?: any;
111
+ __fit__lapMesgType?: LapMesgType;
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trackswap",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "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.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,15 +11,29 @@
11
11
  }
12
12
  },
13
13
  "files": [
14
- "dist/**/*",
14
+ "dist/index.js",
15
+ "dist/index.d.ts",
16
+ "dist/TrackSwap.d.ts",
17
+ "dist/types.d.ts",
18
+ "dist/**/*.d.ts",
15
19
  "README.md",
16
20
  "LICENSE"
17
21
  ],
18
22
  "scripts": {
19
23
  "dev": "ts-node src/index.ts",
20
- "build": "tsc",
24
+ "clean": "rm -rf dist",
25
+ "build": "npm run clean && npm run build:types && npm run build:prod && npm run build:optimize",
26
+ "build:types": "tsc --emitDeclarationOnly",
27
+ "build:prod": "NODE_ENV=production node build.config.js",
28
+ "build:dev": "npm run clean && npm run build:types && NODE_ENV=development node build.config.js",
29
+ "build:optimize": "node scripts/optimize-dist.js",
30
+ "build:js": "esbuild src/index.ts --bundle --platform=node --target=node14 --format=esm --outfile=dist/index.js --minify --sourcemap",
31
+ "build:tsc": "tsc && npm run minify",
32
+ "minify": "terser dist/**/*.js --compress --mangle --output dist/index.min.js --source-map",
33
+ "analyze": "NODE_ENV=production ANALYZE=true node build.config.js",
21
34
  "start": "node dist/index.js",
22
35
  "test:gpx": "cd example/gpx && rm -f output* test_*.json *_report.json *_encoded.xml && node test.js",
36
+ "test:fit": "cd example/FIT && rm -rf output && node test.js",
23
37
  "prepublishOnly": "npm run build"
24
38
  },
25
39
  "keywords": [
@@ -37,27 +51,31 @@
37
51
  "geospatial",
38
52
  "trackswap"
39
53
  ],
40
- "author": "buerber1016",
54
+ "author": "berber1016",
41
55
  "license": "MIT",
42
56
  "type": "module",
43
57
  "repository": {
44
58
  "type": "git",
45
- "url": "https://github.com/buerber1016/trackswap.git"
59
+ "url": "https://github.com/berber1016/trackswap.git"
46
60
  },
47
- "homepage": "https://github.com/buerber1016/trackswap#readme",
61
+ "homepage": "https://github.com/berber1016/trackswap#readme",
48
62
  "bugs": {
49
- "url": "https://github.com/buerber1016/trackswap/issues"
63
+ "url": "https://github.com/berber1016/trackswap/issues"
50
64
  },
51
65
  "engines": {
52
66
  "node": ">=14.0.0"
53
67
  },
54
68
  "devDependencies": {
55
69
  "@types/node": "^22.15.24",
70
+ "esbuild": "^0.19.12",
71
+ "terser": "^5.27.0",
56
72
  "ts-node": "^10.9.2",
57
73
  "typescript": "^5.8.3"
58
74
  },
59
75
  "dependencies": {
76
+ "@garmin/fitsdk": "^21.171.0",
60
77
  "dayjs": "^1.11.13",
78
+ "geolib": "^3.3.4",
61
79
  "htmlparser2": "^10.0.0"
62
80
  }
63
81
  }
package/dist/GPX/base.js DELETED
@@ -1,83 +0,0 @@
1
- // ============ 基础工具类 ============
2
- /**
3
- * 基础转换器抽象类
4
- */
5
- export class BaseConverter {
6
- constructor() {
7
- this.version = "1.0.0";
8
- this.priority = 100;
9
- }
10
- supports(tag) {
11
- return this.supportedTags.includes(tag);
12
- }
13
- async initialize(context) {
14
- context.metadata.set(`plugin:${this.name}:initialized`, true);
15
- }
16
- async destroy(context) {
17
- context.metadata.delete(`plugin:${this.name}:initialized`);
18
- }
19
- async validate(context) {
20
- return true;
21
- }
22
- // 工具方法
23
- parseFloat(value) {
24
- if (typeof value === "number")
25
- return value;
26
- if (typeof value === "string")
27
- return parseFloat(value) || 0;
28
- return 0;
29
- }
30
- parseString(value) {
31
- return String(value || "");
32
- }
33
- hasRequiredAttributes(ast, required) {
34
- return required.every((attr) => ast.attributes?.[attr]);
35
- }
36
- extractAttributes(ast, target, mapping) {
37
- if (!ast.attributes)
38
- return;
39
- Object.entries(ast.attributes).forEach(([key, value]) => {
40
- const targetKey = mapping[key];
41
- if (targetKey && targetKey in target) {
42
- target[targetKey] = this.parseFloat(value);
43
- }
44
- });
45
- }
46
- processChildren(ast, target, processors) {
47
- ast.children?.forEach((child) => {
48
- const processor = processors[child.tag];
49
- if (processor) {
50
- processor(child, target);
51
- }
52
- });
53
- }
54
- }
55
- /**
56
- * 基础中间件抽象类
57
- */
58
- export class BaseMiddleware {
59
- constructor() {
60
- this.version = "1.0.0";
61
- this.description = "";
62
- }
63
- async initialize(context) { }
64
- async destroy(context) { }
65
- async validate(context) {
66
- return true;
67
- }
68
- async onTokenize(tokens, context) {
69
- return tokens;
70
- }
71
- async onAstGenerate(ast, context) {
72
- return ast;
73
- }
74
- async onConvert(result, context) {
75
- return result;
76
- }
77
- async onComplete(result, context) {
78
- return result;
79
- }
80
- async onError(error, context) {
81
- console.error(`中间件 ${this.name} 处理错误:`, error);
82
- }
83
- }