trackswap 0.0.2 → 0.0.4

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 (83) hide show
  1. package/README.md +328 -281
  2. package/dist/FIT/base.d.ts +0 -30
  3. package/dist/FIT/decoder.d.ts +0 -48
  4. package/dist/FIT/encoder.d.ts +0 -97
  5. package/dist/FIT/mesg.d.ts +0 -3
  6. package/dist/FIT/middleware.d.ts +0 -15
  7. package/dist/FIT/plugins.d.ts +0 -9
  8. package/dist/FIT/processor.d.ts +0 -24
  9. package/dist/FIT/types/mesg_num.d.ts +102 -102
  10. package/dist/FIT/types/sport.d.ts +44 -44
  11. package/dist/FIT/types.d.ts +0 -35
  12. package/dist/GPX/base.d.ts +6 -50
  13. package/dist/GPX/converters.d.ts +0 -30
  14. package/dist/GPX/decoder.d.ts +0 -66
  15. package/dist/GPX/encoder.d.ts +0 -109
  16. package/dist/GPX/middleware.d.ts +0 -9
  17. package/dist/GPX/processor.d.ts +0 -18
  18. package/dist/GPX/types.d.ts +0 -108
  19. package/dist/TCX/base.d.ts +0 -33
  20. package/dist/TCX/converters.d.ts +0 -24
  21. package/dist/TCX/decoder.d.ts +0 -54
  22. package/dist/TCX/encoder.d.ts +0 -109
  23. package/dist/TCX/index.d.ts +4 -2
  24. package/dist/TCX/middleware.d.ts +11 -13
  25. package/dist/TCX/processor.d.ts +13 -21
  26. package/dist/TCX/types.d.ts +1 -13
  27. package/dist/TrackSwap.d.ts +37 -33
  28. package/dist/core/base.d.ts +0 -46
  29. package/dist/core/xml-utils.d.ts +0 -24
  30. package/dist/index.cjs +26 -0
  31. package/dist/index.js +26 -5
  32. package/dist/sport/base.d.ts +64 -0
  33. package/dist/sport/converters.d.ts +33 -0
  34. package/dist/sport/encoders.d.ts +34 -0
  35. package/dist/sport/index.d.ts +17 -0
  36. package/dist/sport/processor.d.ts +19 -0
  37. package/dist/types.d.ts +91 -13
  38. package/package.json +23 -5
  39. package/dist/FIT/base.js +0 -101
  40. package/dist/FIT/crc.js +0 -16
  41. package/dist/FIT/decoder.js +0 -323
  42. package/dist/FIT/encoder.js +0 -445
  43. package/dist/FIT/index.js +0 -13
  44. package/dist/FIT/mesg.js +0 -208
  45. package/dist/FIT/middleware.js +0 -206
  46. package/dist/FIT/plugins.js +0 -104
  47. package/dist/FIT/processor.js +0 -170
  48. package/dist/FIT/types/course_point.js +0 -58
  49. package/dist/FIT/types/event.js +0 -50
  50. package/dist/FIT/types/event_type.js +0 -19
  51. package/dist/FIT/types/file.js +0 -24
  52. package/dist/FIT/types/index.js +0 -297
  53. package/dist/FIT/types/mesg_num.js +0 -106
  54. package/dist/FIT/types/sport.js +0 -48
  55. package/dist/FIT/types.js +0 -1
  56. package/dist/FIT/util.js +0 -7
  57. package/dist/GPX/base.js +0 -56
  58. package/dist/GPX/converters.js +0 -352
  59. package/dist/GPX/decoder.js +0 -409
  60. package/dist/GPX/encoder.js +0 -513
  61. package/dist/GPX/extensions/index.js +0 -14
  62. package/dist/GPX/index.js +0 -11
  63. package/dist/GPX/middleware.js +0 -93
  64. package/dist/GPX/processor.js +0 -188
  65. package/dist/GPX/types.js +0 -1
  66. package/dist/GPX/util.js +0 -18
  67. package/dist/TCX/base.js +0 -62
  68. package/dist/TCX/converters.js +0 -333
  69. package/dist/TCX/decoder.js +0 -350
  70. package/dist/TCX/encoder.js +0 -513
  71. package/dist/TCX/index.js +0 -9
  72. package/dist/TCX/middleware.js +0 -93
  73. package/dist/TCX/processor.js +0 -197
  74. package/dist/TCX/types.js +0 -1
  75. package/dist/TrackSwap.js +0 -84
  76. package/dist/core/base.js +0 -138
  77. package/dist/core/decoder.d.ts +0 -66
  78. package/dist/core/decoder.js +0 -90
  79. package/dist/core/index.js +0 -4
  80. package/dist/core/processor.d.ts +0 -69
  81. package/dist/core/processor.js +0 -265
  82. package/dist/core/xml-utils.js +0 -140
  83. package/dist/types.js +0 -1
@@ -1,197 +0,0 @@
1
- import { Parser } from "htmlparser2";
2
- /**
3
- * 流水线阶段
4
- */
5
- export var PipelineStage;
6
- (function (PipelineStage) {
7
- PipelineStage["TOKENIZE"] = "tokenize";
8
- PipelineStage["AST_GENERATE"] = "ast_generate";
9
- PipelineStage["CONVERT"] = "convert";
10
- PipelineStage["COMPLETE"] = "complete";
11
- })(PipelineStage || (PipelineStage = {}));
12
- /**
13
- * Tokenize处理器,将XML转为Token
14
- */
15
- export class TokenizeProcessor {
16
- constructor() {
17
- this.stage = PipelineStage.TOKENIZE;
18
- }
19
- async process(context) {
20
- const startTime = Date.now();
21
- if (!context.xmlContent) {
22
- throw new Error("XML内容不能为空");
23
- }
24
- const tokens = [];
25
- const parser = new Parser({
26
- onopentag(name, attribs) {
27
- tokens.push({
28
- type: "open",
29
- tag: name,
30
- attributes: attribs,
31
- });
32
- },
33
- ontext(text) {
34
- const filteredText = text.replace(/\n/g, "").trim();
35
- if (filteredText) {
36
- tokens.push({ type: "text", tag: "text", value: filteredText });
37
- }
38
- },
39
- onclosetag(name) {
40
- tokens.push({ type: "close", tag: name });
41
- },
42
- }, { xmlMode: true });
43
- parser.write(context.xmlContent);
44
- parser.end();
45
- context.tokens = tokens;
46
- context.performance.tokenizeTime = Date.now() - startTime;
47
- return context;
48
- }
49
- }
50
- /**
51
- * AST生成处理器
52
- */
53
- export class AstGenerateProcessor {
54
- constructor() {
55
- this.stage = PipelineStage.AST_GENERATE;
56
- }
57
- async process(context) {
58
- const startTime = Date.now();
59
- if (!context.tokens) {
60
- throw new Error("Tokens不能为空");
61
- }
62
- const stack = [];
63
- let root = undefined;
64
- let current = null;
65
- for (const token of context.tokens) {
66
- if (token.type === "open") {
67
- const newElement = {
68
- tag: token.tag,
69
- attributes: token.attributes || {},
70
- children: [],
71
- };
72
- if (!root) {
73
- root = newElement;
74
- }
75
- else if (current) {
76
- current.children?.push(newElement);
77
- }
78
- stack.push(newElement);
79
- current = newElement;
80
- }
81
- else if (token.type === "text" && current) {
82
- current.value = token.value;
83
- }
84
- else if (token.type === "close") {
85
- stack.pop();
86
- current = stack[stack.length - 1] || null;
87
- }
88
- }
89
- context.ast = root;
90
- context.performance.astTime = Date.now() - startTime;
91
- return context;
92
- }
93
- }
94
- /**
95
- * 转换处理器
96
- */
97
- export class ConvertProcessor {
98
- constructor(getConverter) {
99
- this.getConverter = getConverter;
100
- this.stage = PipelineStage.CONVERT;
101
- }
102
- async process(context) {
103
- const startTime = Date.now();
104
- if (!context.ast) {
105
- throw new Error("AST不能为空");
106
- }
107
- const tcx = {};
108
- // 处理根节点属性
109
- if (context.ast.attributes) {
110
- Object.entries(context.ast.attributes).forEach(([key, value]) => {
111
- if (key.startsWith("xmlns:")) {
112
- tcx[key] = value.replace(/'/g, "'");
113
- }
114
- else if (key === "xsi:schemaLocation") {
115
- tcx[key] = value.replace(/'/g, "'");
116
- }
117
- else {
118
- tcx[key] = value;
119
- }
120
- });
121
- }
122
- // 处理子节点
123
- context.ast.children?.forEach((child) => {
124
- const converter = this.getConverter(child.tag);
125
- if (!converter) {
126
- console.error(`标签 ${child.tag} 未找到对应的 converter`);
127
- return;
128
- }
129
- try {
130
- const result = converter.convert(child, context);
131
- if (result) {
132
- this.assignResult(tcx, child.tag, result);
133
- }
134
- }
135
- catch (error) {
136
- context.errors.push(error);
137
- console.error(`转换器 ${converter.name} 处理标签 ${child.tag} 时出错:`, error);
138
- }
139
- });
140
- context.result = tcx;
141
- context.performance.convertTime = Date.now() - startTime;
142
- return context;
143
- }
144
- assignResult(tcx, tag, result) {
145
- switch (tag) {
146
- case "Folders":
147
- tcx.Folders = result;
148
- break;
149
- case "Activities":
150
- tcx.Activities = result;
151
- break;
152
- case "Workouts":
153
- tcx.Workouts = result;
154
- break;
155
- case "Courses":
156
- tcx.Courses = result;
157
- break;
158
- case "Author":
159
- tcx.Author = result;
160
- break;
161
- case "Extensions":
162
- tcx.Extensions = result;
163
- break;
164
- default:
165
- // 对于其他标签,直接赋值
166
- tcx[tag] = result;
167
- break;
168
- }
169
- }
170
- }
171
- /**
172
- * 完成处理器
173
- */
174
- export class CompleteProcessor {
175
- constructor() {
176
- this.stage = PipelineStage.COMPLETE;
177
- }
178
- async process(context) {
179
- context.performance.endTime = Date.now();
180
- // 记录性能指标
181
- const totalTime = context.performance.endTime - context.performance.startTime;
182
- context.metadata.set("performance", {
183
- totalTime,
184
- tokenizeTime: context.performance.tokenizeTime,
185
- astTime: context.performance.astTime,
186
- convertTime: context.performance.convertTime,
187
- });
188
- // 更新统计信息
189
- if (context.stats) {
190
- context.stats.endTime = Date.now();
191
- if (context.tokens) {
192
- context.stats.processedTokens = context.tokens.length;
193
- }
194
- }
195
- return context;
196
- }
197
- }
package/dist/TCX/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
package/dist/TrackSwap.js DELETED
@@ -1,84 +0,0 @@
1
- import { GPXDecoder, GPXEncoder } from "./GPX/index.js";
2
- /**
3
- * GPX轨迹交换处理类
4
- * 提供GPX文件的解析和编码功能
5
- */
6
- export class TrackSwap {
7
- constructor() {
8
- this.decoder = new GPXDecoder();
9
- this.encoder = new GPXEncoder();
10
- }
11
- // ==================== 解析功能 ====================
12
- /**
13
- * 解析GPX文件Buffer为GPX对象
14
- */
15
- async parseGPX(buffer) {
16
- try {
17
- return await this.decoder.parserByBuffer(buffer);
18
- }
19
- catch (error) {
20
- console.error("GPX解析失败:", error);
21
- throw new Error(`GPX解析失败: ${error.message}`);
22
- }
23
- }
24
- /**
25
- * 解析GPX文件字符串为GPX对象
26
- */
27
- async parseGPXString(xmlString) {
28
- const buffer = Buffer.from(xmlString, "utf-8");
29
- return this.parseGPX(buffer);
30
- }
31
- // ==================== 编码功能 ====================
32
- /**
33
- * 编码GPX对象为Buffer
34
- */
35
- async encodeGPX(gpxData) {
36
- try {
37
- return await this.encoder.encode(gpxData);
38
- }
39
- catch (error) {
40
- console.error("GPX编码失败:", error);
41
- throw new Error(`GPX编码失败: ${error.message}`);
42
- }
43
- }
44
- /**
45
- * 编码GPX对象为XML字符串
46
- */
47
- encodeGPXString(gpxData) {
48
- try {
49
- return this.encoder.encodeToString(gpxData);
50
- }
51
- catch (error) {
52
- console.error("GPX编码失败:", error);
53
- throw new Error(`GPX编码失败: ${error.message}`);
54
- }
55
- }
56
- // ==================== 实例管理 ====================
57
- /**
58
- * 获取解码器实例
59
- */
60
- getDecoder() {
61
- return this.decoder;
62
- }
63
- /**
64
- * 获取编码器实例
65
- */
66
- getEncoder() {
67
- return this.encoder;
68
- }
69
- /**
70
- * 销毁实例,清理资源
71
- */
72
- async destroy() {
73
- await this.decoder.destroy();
74
- }
75
- // ==================== 向后兼容 ====================
76
- /**
77
- * @deprecated 使用 encodeGPX() 替代
78
- */
79
- async encoderGPX(gpx) {
80
- return this.encodeGPX(gpx);
81
- }
82
- }
83
- // 默认导出
84
- export default { TrackSwap };
package/dist/core/base.js DELETED
@@ -1,138 +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
- parseInt(value) {
31
- if (typeof value === "number")
32
- return Math.floor(value);
33
- if (typeof value === "string")
34
- return parseInt(value, 10) || 0;
35
- return 0;
36
- }
37
- parseString(value) {
38
- return String(value || "");
39
- }
40
- parseBoolean(value) {
41
- if (typeof value === "boolean")
42
- return value;
43
- if (typeof value === "string")
44
- return value.toLowerCase() === "true";
45
- return false;
46
- }
47
- parseDate(value) {
48
- if (!value)
49
- return undefined;
50
- const date = new Date(value);
51
- return isNaN(date.getTime()) ? undefined : date;
52
- }
53
- hasRequiredAttributes(ast, required) {
54
- return required.every((attr) => ast.attributes?.[attr]);
55
- }
56
- extractAttributes(ast, target, mapping) {
57
- if (!ast.attributes)
58
- return;
59
- Object.entries(ast.attributes).forEach(([key, value]) => {
60
- const targetKey = mapping[key];
61
- if (targetKey && targetKey in target) {
62
- target[targetKey] = String(value || "");
63
- }
64
- });
65
- }
66
- processChildren(ast, target, processors) {
67
- ast.children?.forEach((child) => {
68
- const fn = processors[child.tag];
69
- if (fn)
70
- fn(child, target);
71
- });
72
- }
73
- getChildValue(ast, tag) {
74
- const child = ast.children?.find((c) => c.tag === tag);
75
- return child?.value ? String(child.value) : undefined;
76
- }
77
- getChildByTag(ast, tag) {
78
- return ast.children?.find((c) => c.tag === tag);
79
- }
80
- getChildrenByTag(ast, tag) {
81
- return ast.children?.filter((c) => c.tag === tag) || [];
82
- }
83
- // ============ 扩展处理工具 ============
84
- /**
85
- * 通用的 Extensions 处理方法
86
- */
87
- convertExtensions(extensionsAST) {
88
- const extensions = {};
89
- extensionsAST.children?.forEach((child) => {
90
- extensions[child.tag] = this.convertExtensionContent(child);
91
- });
92
- return extensions;
93
- }
94
- /**
95
- * 递归转换 Extensions 内容
96
- */
97
- convertExtensionContent(extension) {
98
- if (extension.children?.length) {
99
- const result = {};
100
- extension.children.forEach((child) => {
101
- result[child.tag] = this.convertExtensionContent(child);
102
- });
103
- return result;
104
- }
105
- else {
106
- return extension.value;
107
- }
108
- }
109
- }
110
- /**
111
- * 通用基础中间件抽象类
112
- */
113
- export class BaseMiddleware {
114
- constructor() {
115
- this.version = "1.0.0";
116
- this.description = "";
117
- }
118
- async initialize(context) { }
119
- async destroy(context) { }
120
- async validate(context) {
121
- return true;
122
- }
123
- async onTokenize(tokens, context) {
124
- return tokens;
125
- }
126
- async onAstGenerate(ast, context) {
127
- return ast;
128
- }
129
- async onConvert(result, context) {
130
- return result;
131
- }
132
- async onComplete(result, context) {
133
- return result;
134
- }
135
- async onError(error, context) {
136
- console.error(`中间件 ${this.name} 处理错误:`, error);
137
- }
138
- }
@@ -1,66 +0,0 @@
1
- import { IPlugin, IProcessingContext } from "./base.js";
2
- import { Processor } from "./processor.js";
3
- /**
4
- * 通用解码器基类
5
- */
6
- export declare abstract class BaseDecoder<TContext extends IProcessingContext = IProcessingContext, TResult = any> {
7
- protected processor: Processor<TContext, TResult>;
8
- protected initialized: boolean;
9
- constructor();
10
- /**
11
- * 抽象方法:初始化默认转换器
12
- */
13
- protected abstract initializeDefaultConverters(): void;
14
- /**
15
- * 抽象方法:创建处理上下文
16
- */
17
- protected abstract createContext(options: {
18
- skipValidation?: boolean;
19
- enableStats?: boolean;
20
- userData?: Record<string, any>;
21
- }): TContext;
22
- /**
23
- * 解析 Buffer 数据
24
- */
25
- parseByBuffer(buffer: Buffer, options?: {
26
- skipValidation?: boolean;
27
- enableStats?: boolean;
28
- userData?: Record<string, any>;
29
- }): Promise<TResult>;
30
- /**
31
- * 解析 XML 字符串
32
- */
33
- parseByString(xmlContent: string, options?: {
34
- skipValidation?: boolean;
35
- enableStats?: boolean;
36
- userData?: Record<string, any>;
37
- }): Promise<TResult>;
38
- /**
39
- * 注册自定义插件
40
- */
41
- registerPlugin(plugin: IPlugin<TContext>): void;
42
- /**
43
- * 批量注册插件
44
- */
45
- registerPlugins(plugins: IPlugin<TContext>[]): void;
46
- /**
47
- * 移除插件
48
- */
49
- unregisterPlugin(name: string): boolean;
50
- /**
51
- * 获取已注册的插件列表
52
- */
53
- getRegisteredPlugins(): IPlugin<TContext>[];
54
- /**
55
- * 清空所有插件(保留默认转换器)
56
- */
57
- reset(): void;
58
- /**
59
- * 获取处理器实例(用于高级自定义)
60
- */
61
- getProcessor(): Processor<TContext, TResult>;
62
- /**
63
- * 获取转换器
64
- */
65
- getConverter(tag: string): import("./base.js").IConverterPlugin<TContext> | undefined;
66
- }
@@ -1,90 +0,0 @@
1
- import { Processor } from "./processor.js";
2
- import { XMLUtils } from "./xml-utils.js";
3
- /**
4
- * 通用解码器基类
5
- */
6
- export class BaseDecoder {
7
- constructor() {
8
- this.initialized = false;
9
- this.processor = new Processor();
10
- }
11
- /**
12
- * 解析 Buffer 数据
13
- */
14
- async parseByBuffer(buffer, options = {}) {
15
- const xmlContent = buffer.toString("utf-8");
16
- return this.parseByString(xmlContent, options);
17
- }
18
- /**
19
- * 解析 XML 字符串
20
- */
21
- async parseByString(xmlContent, options = {}) {
22
- try {
23
- // 确保转换器已初始化
24
- if (!this.initialized) {
25
- this.initializeDefaultConverters();
26
- }
27
- // 验证 XML 格式
28
- if (!options.skipValidation) {
29
- const validation = XMLUtils.validateXML(xmlContent);
30
- if (!validation.isValid) {
31
- throw new Error(`XML 格式错误: ${validation.error}`);
32
- }
33
- }
34
- // 1. Tokenize XML
35
- const tokens = XMLUtils.tokenizeXML(xmlContent);
36
- // 2. 创建上下文
37
- const context = this.createContext(options);
38
- // 3. 使用处理器处理
39
- const result = await this.processor.process(tokens, context, options);
40
- return result;
41
- }
42
- catch (error) {
43
- throw new Error(`解析失败: ${error.message}`);
44
- }
45
- }
46
- /**
47
- * 注册自定义插件
48
- */
49
- registerPlugin(plugin) {
50
- this.processor.registerPlugin(plugin);
51
- }
52
- /**
53
- * 批量注册插件
54
- */
55
- registerPlugins(plugins) {
56
- this.processor.registerPlugins(plugins);
57
- }
58
- /**
59
- * 移除插件
60
- */
61
- unregisterPlugin(name) {
62
- return this.processor.unregisterPlugin(name);
63
- }
64
- /**
65
- * 获取已注册的插件列表
66
- */
67
- getRegisteredPlugins() {
68
- return this.processor.getRegisteredPlugins();
69
- }
70
- /**
71
- * 清空所有插件(保留默认转换器)
72
- */
73
- reset() {
74
- this.processor.clear();
75
- this.initialized = false;
76
- this.initializeDefaultConverters();
77
- }
78
- /**
79
- * 获取处理器实例(用于高级自定义)
80
- */
81
- getProcessor() {
82
- return this.processor;
83
- }
84
- /**
85
- * 获取转换器
86
- */
87
- getConverter(tag) {
88
- return this.processor.getConverter(tag);
89
- }
90
- }
@@ -1,4 +0,0 @@
1
- // ============ 基础架构 ============
2
- export { BaseConverter, BaseMiddleware, } from "./base.js";
3
- // ============ XML 工具 ============
4
- export { XMLUtils } from "./xml-utils.js";
@@ -1,69 +0,0 @@
1
- import { Token, TokenAST } from "../types.js";
2
- import { IPlugin, IConverterPlugin, IProcessingContext } from "./base.js";
3
- /**
4
- * 通用处理器 - 负责管理插件和处理流程
5
- */
6
- export declare class Processor<TContext extends IProcessingContext = IProcessingContext, TResult = any> {
7
- private converters;
8
- private middlewares;
9
- private plugins;
10
- /**
11
- * 注册插件
12
- */
13
- registerPlugin(plugin: IPlugin<TContext>): void;
14
- /**
15
- * 批量注册插件
16
- */
17
- registerPlugins(plugins: IPlugin<TContext>[]): void;
18
- /**
19
- * 获取转换器
20
- */
21
- getConverter(tag: string): IConverterPlugin<TContext> | undefined;
22
- /**
23
- * 移除插件
24
- */
25
- unregisterPlugin(name: string): boolean;
26
- /**
27
- * 获取已注册的插件列表
28
- */
29
- getRegisteredPlugins(): IPlugin<TContext>[];
30
- /**
31
- * 清空所有插件
32
- */
33
- clear(): void;
34
- /**
35
- * 处理数据 - 四阶段处理流程
36
- */
37
- process(tokens: Token[], context: TContext, options?: {
38
- skipValidation?: boolean;
39
- enableStats?: boolean;
40
- }): Promise<TResult>;
41
- /**
42
- * 生成 AST
43
- */
44
- generateAST(tokens: Token[]): TokenAST;
45
- /**
46
- * 转换 AST
47
- */
48
- convertAST(ast: TokenAST, context: TContext): any;
49
- /**
50
- * 通用转换逻辑
51
- */
52
- private convertGeneric;
53
- /**
54
- * 初始化插件
55
- */
56
- private initializePlugins;
57
- /**
58
- * 销毁插件
59
- */
60
- private destroyPlugins;
61
- /**
62
- * 检查是否为转换器插件
63
- */
64
- private isConverterPlugin;
65
- /**
66
- * 检查是否为中间件插件
67
- */
68
- private isMiddlewarePlugin;
69
- }