fit-file-parser 2.0.4 → 2.1.0

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.
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ *
4
+ * this file is auto generated using src/type_generator.ts
5
+ * it parses the big FIT definition object from src/fit.js into usable typescript types
6
+ * do not edit this file directly, instead edit the generator and
7
+ * regenerate it with "npm run codegen"
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import type { ParsedLap, ParsedSession } from './fit_types.js';
2
+ export declare function mapDataIntoLap(inputLaps: ParsedLap[], lapKey: 'records' | 'lengths', data: any[]): ParsedLap[];
3
+ export declare function mapDataIntoSession(inputSessions: ParsedSession[], laps: ParsedLap[]): ParsedSession[];
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapDataIntoLap = mapDataIntoLap;
4
+ exports.mapDataIntoSession = mapDataIntoSession;
5
+ function mapDataIntoLap(inputLaps, lapKey, data) {
6
+ const laps = [...inputLaps];
7
+ let index = 0;
8
+ for (let i = 0; i < laps.length; i++) {
9
+ const lap = laps[i];
10
+ const nextLap = laps[i + 1];
11
+ const tempData = [];
12
+ const lapStartTime = new Date(lap.start_time).getTime();
13
+ const nextLapStartTime = nextLap
14
+ ? new Date(nextLap.start_time).getTime()
15
+ : null;
16
+ for (let j = index; j < data.length; j++) {
17
+ const row = data[j];
18
+ if (nextLap && nextLapStartTime) {
19
+ const timestamp = new Date(row.timestamp).getTime();
20
+ if (lapStartTime <= timestamp && nextLapStartTime > timestamp) {
21
+ tempData.push(row);
22
+ }
23
+ else if (nextLapStartTime <= timestamp) {
24
+ index = j;
25
+ break;
26
+ }
27
+ }
28
+ else {
29
+ tempData.push(row);
30
+ }
31
+ }
32
+ if (!laps[i][lapKey]) {
33
+ laps[i][lapKey] = tempData;
34
+ }
35
+ }
36
+ return laps;
37
+ }
38
+ function mapDataIntoSession(inputSessions, laps) {
39
+ const sessions = [...inputSessions];
40
+ let lapIndex = 0;
41
+ for (let i = 0; i < sessions.length; i++) {
42
+ const session = sessions[i];
43
+ const nextSession = sessions[i + 1];
44
+ const tempLaps = [];
45
+ const sessionStartTime = new Date(session.start_time).getTime();
46
+ const nextSessionStartTime = nextSession
47
+ ? new Date(nextSession.start_time).getTime()
48
+ : null;
49
+ for (let j = lapIndex; j < laps.length; j++) {
50
+ const lap = laps[j];
51
+ if (nextSession && nextSessionStartTime) {
52
+ const lapStartTime = new Date(lap.start_time).getTime();
53
+ if (sessionStartTime <= lapStartTime
54
+ && nextSessionStartTime > lapStartTime) {
55
+ tempLaps.push(lap);
56
+ }
57
+ else if (nextSessionStartTime <= lapStartTime) {
58
+ lapIndex = j;
59
+ break;
60
+ }
61
+ }
62
+ else {
63
+ tempLaps.push(lap);
64
+ }
65
+ }
66
+ if (!sessions[i].laps) {
67
+ sessions[i].laps = tempLaps;
68
+ }
69
+ }
70
+ return sessions;
71
+ }
@@ -0,0 +1,7 @@
1
+ import type { MessageObject } from './fit.js';
2
+ import type { MesgNum } from './fit_types.js';
3
+ export declare function getFitMessage(messageNum: number): {
4
+ name: MesgNum | '';
5
+ getAttributes: (fieldNum: number) => MessageObject;
6
+ };
7
+ export declare function getFitMessageBaseType(inp: any): any;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFitMessage = getFitMessage;
4
+ exports.getFitMessageBaseType = getFitMessageBaseType;
5
+ const fit_js_1 = require("./fit.js");
6
+ function getFieldObject(fieldNum, messageNum) {
7
+ const message = fit_js_1.FIT.messages[messageNum];
8
+ if (!message) {
9
+ return {};
10
+ }
11
+ return message[fieldNum] || {};
12
+ }
13
+ function getMessageName(messageNum) {
14
+ const message = fit_js_1.FIT.messages[messageNum];
15
+ return message ? message.name : '';
16
+ }
17
+ function getFitMessage(messageNum) {
18
+ return {
19
+ name: getMessageName(messageNum),
20
+ getAttributes: (fieldNum) => getFieldObject(fieldNum, messageNum),
21
+ };
22
+ }
23
+ // TODO
24
+ function getFitMessageBaseType(inp) {
25
+ return inp;
26
+ }
@@ -0,0 +1 @@
1
+ {"type": "commonjs"}
@@ -0,0 +1,26 @@
1
+ import type { PropertySignature, Statement, TypeNode } from 'typescript';
2
+ import type { Message, MessageObject } from './fit.js';
3
+ import ts from 'typescript';
4
+ type SnakeToCamelCase<S extends string> = S extends `${infer T}_${infer U}` ? `${T}${Capitalize<SnakeToCamelCase<U>>}` : S;
5
+ export declare function line(): ts.Node;
6
+ export declare function comment(contents: string): ts.Node[];
7
+ export declare function header(): ts.Node;
8
+ export declare function capitalize<T extends string>(s: T): string;
9
+ export declare function snakeToCamel<T extends string>(s: T): SnakeToCamelCase<Capitalize<T>>;
10
+ export declare function unicodeToChar(text: string): string;
11
+ export declare function generateProperty(name: string, type: TypeNode, optional?: boolean): PropertySignature;
12
+ export declare function generateArrayProperty(name: string, type: TypeNode, optional?: boolean): PropertySignature;
13
+ export declare function generateTypeFromField(def: MessageObject): TypeNode;
14
+ export declare function generateTypes(types: {
15
+ [typeName: string]: Record<number, string | number>;
16
+ }): Statement[];
17
+ export declare function generateOptions(options: {
18
+ [typeName: string]: Record<number, string | number>;
19
+ }): ts.Node[];
20
+ export declare function generateUtilities(): Statement[];
21
+ export declare function generateFitType(): Statement;
22
+ export declare function generateMessages(messages: {
23
+ [messageId: number]: Message;
24
+ }): Statement[];
25
+ export declare function main(): string;
26
+ export {};
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.line = line;
7
+ exports.comment = comment;
8
+ exports.header = header;
9
+ exports.capitalize = capitalize;
10
+ exports.snakeToCamel = snakeToCamel;
11
+ exports.unicodeToChar = unicodeToChar;
12
+ exports.generateProperty = generateProperty;
13
+ exports.generateArrayProperty = generateArrayProperty;
14
+ exports.generateTypeFromField = generateTypeFromField;
15
+ exports.generateTypes = generateTypes;
16
+ exports.generateOptions = generateOptions;
17
+ exports.generateUtilities = generateUtilities;
18
+ exports.generateFitType = generateFitType;
19
+ exports.generateMessages = generateMessages;
20
+ exports.main = main;
21
+ const typescript_1 = __importDefault(require("typescript"));
22
+ const fit_js_1 = require("./fit.js");
23
+ function line() {
24
+ return typescript_1.default.factory.createIdentifier('\n');
25
+ }
26
+ function comment(contents) {
27
+ return [
28
+ typescript_1.default.factory.createIdentifier('\n'),
29
+ typescript_1.default.factory.createIdentifier(`// ${contents}`),
30
+ typescript_1.default.factory.createIdentifier('\n'),
31
+ ];
32
+ }
33
+ function header() {
34
+ return typescript_1.default.factory.createNodeArray([typescript_1.default.factory.createJSDocComment(`
35
+ this file is auto generated using src/type_generator.ts
36
+ it parses the big FIT definition object from src/fit.js into usable typescript types
37
+ do not edit this file directly, instead edit the generator and
38
+ regenerate it with "npm run codegen"
39
+ `)])[0];
40
+ }
41
+ function capitalize(s) {
42
+ if (s.length === 0) {
43
+ return s;
44
+ }
45
+ return (s[0].toUpperCase() + s.slice(1));
46
+ }
47
+ function snakeToCamel(s) {
48
+ return s.split('_').map(part => capitalize(part)).join('');
49
+ }
50
+ function unicodeToChar(text) {
51
+ return text.replace(/\\u[\dA-F]{4}/gi, (match) => {
52
+ return String.fromCharCode(Number.parseInt(match.replace(/\\u/g, ''), 16));
53
+ });
54
+ }
55
+ function generateProperty(name, type, optional = true) {
56
+ return typescript_1.default.factory.createPropertySignature(undefined, typescript_1.default.factory.createIdentifier(name), optional ? typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionToken) : undefined, type);
57
+ }
58
+ function generateArrayProperty(name, type, optional = true) {
59
+ return generateProperty(name, typescript_1.default.factory.createArrayTypeNode(type), optional);
60
+ }
61
+ function generateTypeFromField(def) {
62
+ switch (def.type) {
63
+ case 'byte_array':
64
+ return typescript_1.default.factory.createArrayTypeNode(typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UnknownKeyword));
65
+ case 'bool':
66
+ return typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.BooleanKeyword);
67
+ case 'date_time':
68
+ case 'string':
69
+ return typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.StringKeyword);
70
+ case 'uint32':
71
+ case 'uint64':
72
+ case 'uint16':
73
+ case 'uint8':
74
+ case 'int32':
75
+ case 'int64':
76
+ case 'int16':
77
+ case 'int8':
78
+ case 'sint32':
79
+ case 'sint16':
80
+ case 'sint8':
81
+ case 'float32':
82
+ case 'float64':
83
+ case 'uint32z':
84
+ case 'uint64z':
85
+ case 'uint16z':
86
+ case 'uint8z':
87
+ case 'localtime_into_day':
88
+ case 'byte':
89
+ case 'device_index':
90
+ return typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword);
91
+ default:
92
+ return typescript_1.default.factory.createTypeReferenceNode(snakeToCamel(def.type));
93
+ }
94
+ }
95
+ function generateTypes(types) {
96
+ const nodes = [];
97
+ const typeNames = Object.keys(types);
98
+ typeNames.forEach((name) => {
99
+ if (name === 'message_index') {
100
+ return;
101
+ }
102
+ const type = types[name];
103
+ const names = Object.values(type);
104
+ const typeAlias = typescript_1.default.factory.createTypeAliasDeclaration([
105
+ typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword),
106
+ ], snakeToCamel(name), undefined, typescript_1.default.factory.createUnionTypeNode([...names.map(n => typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral(String(n)))), ...(name === 'mesg_num'
107
+ // TODO those are somehow missing in the FIT.types.mesg_num definition
108
+ // especially 'tank_update' (319 in messages) is mapped to 'tank_pressure' a bug?
109
+ ? [
110
+ typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral('o_hr_settings')),
111
+ typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral('tank_update')),
112
+ typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral('definition')),
113
+ ]
114
+ : [])]));
115
+ nodes.push(typeAlias);
116
+ });
117
+ return nodes;
118
+ }
119
+ function generateOptions(options) {
120
+ const nodes = [];
121
+ const optionNames = Object.keys(options);
122
+ // generate type aliases for each option (all unit values)
123
+ optionNames.forEach((name) => {
124
+ const option = options[name];
125
+ const names = Object.keys(option);
126
+ const unit = typescript_1.default.factory.createTypeAliasDeclaration([
127
+ typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword),
128
+ ], capitalize(name), undefined, typescript_1.default.factory.createUnionTypeNode(names.map(n => typescript_1.default.factory.createLiteralTypeNode(typescript_1.default.factory.createStringLiteral(unicodeToChar(n))))));
129
+ nodes.push(unit);
130
+ });
131
+ nodes.push(line());
132
+ // generate FitOptions interface which contains all options and their respective types (from above)
133
+ const fitOptions = typescript_1.default.factory.createInterfaceDeclaration([
134
+ typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword),
135
+ ], 'FitOptions', undefined, undefined, [
136
+ ...optionNames.map(name => generateProperty(name, typescript_1.default.factory.createTypeReferenceNode(typescript_1.default.factory.createIdentifier('Unit'), [typescript_1.default.factory.createTypeReferenceNode(typescript_1.default.factory.createIdentifier(capitalize(name)))]), false)),
137
+ ]);
138
+ nodes.push(fitOptions);
139
+ return nodes;
140
+ }
141
+ function generateUtilities() {
142
+ const nodes = [];
143
+ const unitType = typescript_1.default.factory.createTypeAliasDeclaration([typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword)], 'Unit', [typescript_1.default.factory.createTypeParameterDeclaration(undefined, 'T', typescript_1.default.factory.createTypeReferenceNode('string'))], typescript_1.default.factory.createTypeReferenceNode('Record', [
144
+ typescript_1.default.factory.createTypeReferenceNode('T'),
145
+ typescript_1.default.factory.createTypeLiteralNode([
146
+ generateProperty('multiplier', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword), false),
147
+ generateProperty('offset', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword), false),
148
+ ]),
149
+ ]));
150
+ nodes.push(unitType);
151
+ const messageIndex = typescript_1.default.factory.createInterfaceDeclaration([typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword)], 'MessageIndex', undefined, undefined, [
152
+ generateProperty('0', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.BooleanKeyword), false),
153
+ generateProperty('value', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword), false),
154
+ generateProperty('reserved', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.BooleanKeyword), false),
155
+ generateProperty('selected', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.BooleanKeyword), false),
156
+ ]);
157
+ nodes.push(messageIndex);
158
+ return nodes;
159
+ }
160
+ function generateAdditionalFields(msg) {
161
+ if (msg.name === 'lap') {
162
+ return [
163
+ generateArrayProperty('records', typescript_1.default.factory.createTypeReferenceNode(snakeToCamel('parsed_record'))),
164
+ generateArrayProperty('lengths', typescript_1.default.factory.createTypeReferenceNode(snakeToCamel('parsed_length'))),
165
+ ];
166
+ }
167
+ if (msg.name === 'session') {
168
+ return [
169
+ generateArrayProperty('laps', typescript_1.default.factory.createTypeReferenceNode(snakeToCamel('parsed_lap'))),
170
+ ];
171
+ }
172
+ if (msg.name === 'activity') {
173
+ const props = {
174
+ sessions: 'parsed_session',
175
+ events: 'parsed_event',
176
+ hrv: 'parsed_hrv',
177
+ device_infos: 'parsed_device_info',
178
+ developer_data_ids: 'parsed_developer_data_id',
179
+ field_descriptions: 'parsed_field_description',
180
+ sports: 'parsed_sport',
181
+ };
182
+ return Object.keys(props).map(prop => generateArrayProperty(prop, typescript_1.default.factory.createTypeReferenceNode(snakeToCamel(props[prop]))));
183
+ }
184
+ return [];
185
+ }
186
+ function generateFitType() {
187
+ const collectionProperties = {
188
+ laps: 'parsed_lap',
189
+ records: 'parsed_record',
190
+ sessions: 'parsed_session',
191
+ lengths: 'parsed_length',
192
+ events: 'parsed_event',
193
+ device_infos: 'parsed_device_info',
194
+ developer_data_ids: 'parsed_developer_data_id',
195
+ field_descriptions: 'parsed_field_description',
196
+ hrv: 'parsed_hrv',
197
+ hr_zone: 'parsed_hr_zone',
198
+ power_zone: 'parsed_power_zone',
199
+ dive_gases: 'parsed_dive_gas',
200
+ course_points: 'parsed_course_point',
201
+ sports: 'parsed_sport',
202
+ monitors: 'parsed_monitoring',
203
+ stress: 'parsed_stress_level',
204
+ file_ids: 'parsed_file_id',
205
+ monitor_info: 'parsed_monitoring_info',
206
+ definitions: 'unknown',
207
+ tank_updates: 'parsed_tank_update',
208
+ tank_summaries: 'parsed_tank_summary',
209
+ };
210
+ const referenceProperties = {
211
+ file_creator: 'parsed_file_creator',
212
+ device_settings: 'parsed_device_settings',
213
+ dive_summary: '?parsed_dive_summary',
214
+ dive_settings: '?parsed_dive_settings',
215
+ software: 'parsed_software',
216
+ user_profile: 'parsed_user_profile',
217
+ activity: 'parsed_activity',
218
+ zones_target: '?parsed_zones_target',
219
+ };
220
+ return typescript_1.default.factory.createInterfaceDeclaration([typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword)], 'ParsedFit', undefined, undefined, [
221
+ generateProperty('protocolVersion', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword)),
222
+ generateProperty('profileVersion', typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.NumberKeyword)),
223
+ ...Object.keys(referenceProperties).map(prop => generateProperty(prop, typescript_1.default.factory.createTypeReferenceNode(snakeToCamel(referenceProperties[prop].replace('?', ''))), referenceProperties[prop].startsWith('?'))),
224
+ ...Object.keys(collectionProperties).map(prop => generateArrayProperty(prop, collectionProperties[prop] === 'unknown'
225
+ ? typescript_1.default.factory.createKeywordTypeNode(typescript_1.default.SyntaxKind.UnknownKeyword)
226
+ : typescript_1.default.factory.createTypeReferenceNode(snakeToCamel(collectionProperties[prop])))),
227
+ ]);
228
+ }
229
+ function generateMessages(messages) {
230
+ const nodes = [];
231
+ Object.keys(messages).forEach((name) => {
232
+ const msg = fit_js_1.FIT.messages[Number(name)];
233
+ const messageType = typescript_1.default.factory.createInterfaceDeclaration([
234
+ typescript_1.default.factory.createModifier(typescript_1.default.SyntaxKind.ExportKeyword),
235
+ ], snakeToCamel(`parsed_${msg.name}`), undefined, undefined, [
236
+ ...Object.keys(msg).filter(n => n !== 'name').map((id) => {
237
+ const def = msg[Number(id)];
238
+ return generateProperty(def.field, generateTypeFromField(def), !['start_time', 'timestamp'].includes(def.field));
239
+ }),
240
+ ...generateAdditionalFields(msg),
241
+ ]);
242
+ nodes.push(messageType);
243
+ });
244
+ return nodes;
245
+ }
246
+ function main() {
247
+ const sourceFile = typescript_1.default.createSourceFile('', '', typescript_1.default.ScriptTarget.Latest);
248
+ const nodes = [];
249
+ const printer = typescript_1.default.createPrinter({ newLine: typescript_1.default.NewLineKind.LineFeed });
250
+ nodes.push(header());
251
+ nodes.push(...comment('utility types used internally'));
252
+ nodes.push(...generateUtilities());
253
+ nodes.push(...comment('parsed from Fit.types'));
254
+ nodes.push(...generateTypes(fit_js_1.FIT.types));
255
+ nodes.push(...comment('parsed from Fit.options'));
256
+ nodes.push(...generateOptions(fit_js_1.FIT.options));
257
+ nodes.push(...comment('parsed from Fit.messages'));
258
+ nodes.push(...generateMessages(fit_js_1.FIT.messages));
259
+ nodes.push(...comment('the returned type after parsing a .fit file'));
260
+ nodes.push(generateFitType());
261
+ const nodesArray = typescript_1.default.factory.createNodeArray(nodes);
262
+ return printer.printList(typescript_1.default.ListFormat.MultiLine, nodesArray, sourceFile);
263
+ }
@@ -0,0 +1,55 @@
1
+ export interface ParsedElement {
2
+ [key: string]: any;
3
+ message_index?: Record<string, any>;
4
+ }
5
+ export interface ParsedTimestampableElement extends ParsedElement {
6
+ timestamp: string;
7
+ }
8
+ export interface ParsedLap extends ParsedTimestampableElement {
9
+ records?: ParsedTimestampableElement[];
10
+ lengths?: ParsedTimestampableElement[];
11
+ }
12
+ export interface ParsedActivity extends ParsedTimestampableElement {
13
+ sessions?: ParsedSession[];
14
+ events?: ParsedTimestampableElement[];
15
+ hrv?: ParsedHrv[];
16
+ device_infos?: ParsedTimestampableElement[];
17
+ developer_data_ids?: any[];
18
+ field_descriptions?: any[];
19
+ sports?: ParsedElement[];
20
+ }
21
+ export interface ParsedSession extends ParsedTimestampableElement {
22
+ laps?: ParsedLap[];
23
+ }
24
+ export interface ParsedHrv {
25
+ time: number[];
26
+ }
27
+ export interface ParsedFit {
28
+ protocolVersion: number;
29
+ profileVersion: number;
30
+ software?: unknown;
31
+ user_profile: ParsedElement;
32
+ laps?: ParsedLap[];
33
+ records?: ParsedTimestampableElement[];
34
+ sessions?: ParsedSession[];
35
+ activity: ParsedActivity;
36
+ lengths?: ParsedElement[];
37
+ events?: ParsedTimestampableElement[];
38
+ device_infos?: ParsedTimestampableElement[];
39
+ developer_data_ids?: ParsedElement[];
40
+ field_descriptions?: ParsedElement[];
41
+ hrv?: ParsedHrv[];
42
+ hr_zone?: ParsedElement[];
43
+ power_zone?: ParsedElement[];
44
+ dive_gases?: ParsedTimestampableElement[];
45
+ course_points?: ParsedElement[];
46
+ sports?: ParsedElement[];
47
+ devices?: ParsedElement[];
48
+ monitors?: ParsedElement[];
49
+ stress?: ParsedElement[];
50
+ file_ids?: ParsedElement[];
51
+ monitor_info?: ParsedElement[];
52
+ definitions?: ParsedElement[];
53
+ tank_updates?: ParsedElement[];
54
+ tank_summaries?: ParsedElement[];
55
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,4 @@
1
- import type { Buffer } from 'node:buffer';
1
+ import type { Buffer } from 'buffer';
2
2
  import type { ParsedFit } from './fit_types.js';
3
3
  export interface FitParserOptions {
4
4
  force?: boolean;
package/eslint.config.js CHANGED
@@ -4,4 +4,12 @@ export default antfu({
4
4
  type: 'lib',
5
5
  gitignore: true,
6
6
  ignores: ['**/test/*.json'],
7
+ stylistic: {
8
+ indent: 2,
9
+ quotes: 'single',
10
+ },
11
+ formatters: true,
12
+ rules: {
13
+ 'unicorn/prefer-node-protocol': 'off',
14
+ },
7
15
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fit-file-parser",
3
3
  "type": "module",
4
- "version": "2.0.4",
4
+ "version": "2.1.0",
5
5
  "private": false,
6
6
  "description": "Parse your .FIT files easily, directly from JS (Garmin, Polar, Suunto)",
7
7
  "author": {
@@ -35,10 +35,11 @@
35
35
  "exports": {
36
36
  ".": {
37
37
  "types": "./dist/fit-parser.d.ts",
38
- "import": "./dist/fit-parser.js"
38
+ "import": "./dist/fit-parser.js",
39
+ "require": "./dist/cjs/fit-parser.js"
39
40
  }
40
41
  },
41
- "main": "dist/fit-parser.js",
42
+ "main": "dist/cjs/fit-parser.js",
42
43
  "maintainers": [
43
44
  {
44
45
  "email": "jimmykane9@gmail.com",
@@ -58,15 +59,20 @@
58
59
  "lint": "eslint .",
59
60
  "fmt": "eslint --fix .",
60
61
  "type-check": "tsc --noEmit",
61
- "build": "tsc --noCheck"
62
+ "build": "tsc --noCheck && tsc --project tsconfig.cjs.json --noCheck && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json"
62
63
  },
63
64
  "test": "vitest",
65
+ "dependencies": {
66
+ "buffer": "^6.0.3"
67
+ },
64
68
  "devDependencies": {
65
69
  "@antfu/eslint-config": "^6.2.0",
66
70
  "@types/node": "^24.10.1",
67
71
  "@vitest/coverage-v8": "^4.0.13",
68
72
  "eslint": "^9.10.0",
73
+ "eslint-plugin-format": "^1.1.0",
74
+ "tsx": "^4.21.0",
69
75
  "typescript": "^5.9.3",
70
76
  "vitest": "^4.0.13"
71
77
  }
72
- }
78
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "commonjs",
5
+ "outDir": "./dist/cjs",
6
+ "verbatimModuleSyntax": false
7
+ }
8
+ }