fit-file-parser 1.20.0 → 2.0.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.
package/dist/binary.js CHANGED
@@ -1,47 +1,27 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.addEndian = addEndian;
7
- exports.readRecord = readRecord;
8
- exports.getArrayBuffer = getArrayBuffer;
9
- exports.calculateCRC = calculateCRC;
10
-
11
- var _fit = require('./fit');
12
-
13
- var _messages = require('./messages');
14
-
15
- var _buffer = require('buffer');
16
-
17
- function addEndian(littleEndian, bytes) {
18
- var result = 0;
19
- if (!littleEndian) bytes.reverse();
20
- for (var i = 0; i < bytes.length; i++) {
21
- result += bytes[i] << (i << 3) >>> 0;
1
+ import { Buffer } from 'node:buffer';
2
+ import { FIT } from './fit.js';
3
+ import { getFitMessage, getFitMessageBaseType } from './messages.js';
4
+ const CompressedLocalMsgNumMask = 0x60;
5
+ const CompressedHeaderMask = 0x80;
6
+ const GarminTimeOffset = 631065600000;
7
+ let monitoring_timestamp = 0;
8
+ export function addEndian(littleEndian, bytes) {
9
+ let result = 0;
10
+ if (!littleEndian)
11
+ bytes.reverse();
12
+ for (let i = 0; i < bytes.length; i++) {
13
+ result += (bytes[i] << (i << 3)) >>> 0;
22
14
  }
23
-
24
15
  return result;
25
16
  }
26
-
27
- var timestamp = 0;
28
- var lastTimeOffset = 0;
29
- var CompressedTimeMask = 31;
30
- var CompressedLocalMesgNumMask = 0x60;
31
- var CompressedHeaderMask = 0x80;
32
- var GarminTimeOffset = 631065600000;
33
- var monitoring_timestamp = 0;
34
-
35
17
  function readData(blob, fDef, startIndex, options) {
36
- if (fDef.endianAbility === true) {
37
- var temp = [];
38
- for (var i = 0; i < fDef.size; i++) {
18
+ if (fDef.endianAbility) {
19
+ const temp = [];
20
+ for (let i = 0; i < fDef.size; i++) {
39
21
  temp.push(blob[startIndex + i]);
40
22
  }
41
-
42
- var buffer = new Uint8Array(temp).buffer;
43
- var dataView = new DataView(buffer);
44
-
23
+ const { buffer } = new Uint8Array(temp);
24
+ const dataView = new DataView(buffer);
45
25
  try {
46
26
  switch (fDef.type) {
47
27
  case 'sint16':
@@ -58,56 +38,54 @@ function readData(blob, fDef, startIndex, options) {
58
38
  return dataView.getFloat32(0, fDef.littleEndian);
59
39
  case 'float64':
60
40
  return dataView.getFloat64(0, fDef.littleEndian);
61
- case 'uint32_array':
62
- var array32 = [];
63
- for (var _i = 0; _i < fDef.size; _i += 4) {
64
- array32.push(dataView.getUint32(_i, fDef.littleEndian));
41
+ case 'uint32_array': {
42
+ const array32 = [];
43
+ for (let i = 0; i < fDef.size; i += 4) {
44
+ array32.push(dataView.getUint32(i, fDef.littleEndian));
65
45
  }
66
46
  return array32;
67
- case 'uint16_array':
68
- var array = [];
69
- for (var _i2 = 0; _i2 < fDef.size; _i2 += 2) {
70
- array.push(dataView.getUint16(_i2, fDef.littleEndian));
47
+ }
48
+ case 'uint16_array': {
49
+ const array = [];
50
+ for (let i = 0; i < fDef.size; i += 2) {
51
+ array.push(dataView.getUint16(i, fDef.littleEndian));
71
52
  }
72
53
  return array;
54
+ }
73
55
  }
74
- } catch (e) {
56
+ }
57
+ catch (e) {
75
58
  if (!options.force) {
76
59
  throw e;
77
60
  }
78
61
  }
79
-
80
62
  return addEndian(fDef.littleEndian, temp);
81
63
  }
82
-
83
64
  if (fDef.type === 'string') {
84
- var _temp = [];
85
- for (var _i3 = 0; _i3 < fDef.size; _i3++) {
86
- if (blob[startIndex + _i3]) {
87
- _temp.push(blob[startIndex + _i3]);
65
+ const temp = [];
66
+ for (let i = 0; i < fDef.size; i++) {
67
+ if (blob[startIndex + i]) {
68
+ temp.push(blob[startIndex + i]);
88
69
  }
89
70
  }
90
- return new _buffer.Buffer.from(_temp).toString('utf-8');
71
+ return Buffer.from(temp).toString('utf-8');
91
72
  }
92
-
93
73
  if (fDef.type === 'byte_array') {
94
- var _temp2 = [];
95
- for (var _i4 = 0; _i4 < fDef.size; _i4++) {
96
- _temp2.push(blob[startIndex + _i4]);
74
+ const temp = [];
75
+ for (let i = 0; i < fDef.size; i++) {
76
+ temp.push(blob[startIndex + i]);
97
77
  }
98
- return _temp2;
78
+ return temp;
99
79
  }
100
-
101
80
  return blob[startIndex];
102
81
  }
103
-
104
82
  function formatByType(data, type, scale, offset) {
105
83
  switch (type) {
106
84
  case 'date_time':
107
85
  case 'local_date_time':
108
86
  return new Date(data * 1000 + GarminTimeOffset);
109
87
  case 'sint32':
110
- return data * _fit.FIT.scConst;
88
+ return data * FIT.scConst;
111
89
  case 'uint8':
112
90
  case 'sint16':
113
91
  case 'uint32':
@@ -115,37 +93,37 @@ function formatByType(data, type, scale, offset) {
115
93
  return scale ? data / scale + offset : data;
116
94
  case 'uint32_array':
117
95
  case 'uint16_array':
118
- return data.map(function (dataItem) {
119
- return scale ? dataItem / scale + offset : dataItem;
120
- });
96
+ return data.map((dataItem) => scale ? dataItem / scale + offset : dataItem);
121
97
  default:
122
- if (!_fit.FIT.types[type]) {
123
- return data;
124
- }
125
- // Quick check for a mask
126
- var values = [];
127
- for (var key in _fit.FIT.types[type]) {
128
- if (_fit.FIT.types[type].hasOwnProperty(key)) {
129
- values.push(_fit.FIT.types[type][key]);
98
+ {
99
+ if (!FIT.types[type]) {
100
+ return data;
130
101
  }
131
- }
132
- if (values.indexOf('mask') === -1) {
133
- return _fit.FIT.types[type][data];
134
- }
135
- var dataItem = {};
136
- for (var key in _fit.FIT.types[type]) {
137
- if (_fit.FIT.types[type].hasOwnProperty(key)) {
138
- if (_fit.FIT.types[type][key] === 'mask') {
139
- dataItem.value = data & key;
140
- } else {
141
- dataItem[_fit.FIT.types[type][key]] = !!((data & key) >> 7); // Not sure if we need the >> 7 and casting to boolean but from all the masked props of fields so far this seems to be the case
102
+ // Quick check for a mask
103
+ const values = [];
104
+ for (const key in FIT.types[type]) {
105
+ if (key in FIT.types[type]) {
106
+ values.push(String(FIT.types[type][key]));
142
107
  }
143
108
  }
109
+ if (!values.includes('mask')) {
110
+ return FIT.types[type][data];
111
+ }
112
+ const dataItem = {};
113
+ for (const key in FIT.types[type]) {
114
+ if (key in FIT.types[type]) {
115
+ if (FIT.types[type][key] === 'mask') {
116
+ dataItem.value = data & Number(key);
117
+ }
118
+ else {
119
+ dataItem[FIT.types[type][key]] = !!((data & Number(key)) >> 7); // Not sure if we need the >> 7 and casting to boolean but from all the masked props of fields so far this seems to be the case
120
+ }
121
+ }
122
+ }
123
+ return dataItem;
144
124
  }
145
- return dataItem;
146
125
  }
147
126
  }
148
-
149
127
  function isInvalidValue(data, type) {
150
128
  switch (type) {
151
129
  case 'enum':
@@ -167,6 +145,7 @@ function isInvalidValue(data, type) {
167
145
  case 'float32':
168
146
  return data === 0xFFFFFFFF;
169
147
  case 'float64':
148
+ // eslint-disable-next-line no-loss-of-precision
170
149
  return data === 0xFFFFFFFFFFFFFFFF;
171
150
  case 'uint8z':
172
151
  return data === 0x00;
@@ -177,8 +156,10 @@ function isInvalidValue(data, type) {
177
156
  case 'byte':
178
157
  return data === 0xFF;
179
158
  case 'sint64':
159
+ // eslint-disable-next-line no-loss-of-precision
180
160
  return data === 0x7FFFFFFFFFFFFFFF;
181
161
  case 'uint64':
162
+ // eslint-disable-next-line no-loss-of-precision
182
163
  return data === 0xFFFFFFFFFFFFFFFF;
183
164
  case 'uint64z':
184
165
  return data === 0x0000000000000000;
@@ -186,12 +167,11 @@ function isInvalidValue(data, type) {
186
167
  return false;
187
168
  }
188
169
  }
189
-
190
- function convertTo(data, unitsList, speedUnit) {
191
- var unitObj = _fit.FIT.options[unitsList][speedUnit];
192
- return unitObj ? data * unitObj.multiplier + unitObj.offset : data;
170
+ function convertTo(data, unitsList, unitName) {
171
+ const options = FIT.options[unitsList];
172
+ const unit = options[unitName];
173
+ return unit ? data * unit.multiplier + unit.offset : data;
193
174
  }
194
-
195
175
  function applyOptions(data, field, options) {
196
176
  switch (field) {
197
177
  case 'speed':
@@ -240,205 +220,185 @@ function applyOptions(data, field, options) {
240
220
  return data;
241
221
  }
242
222
  }
243
-
244
- function readRecord(blob, messageTypes, developerFields, startIndex, options, startDate, pausedTime) {
245
- var recordHeader = blob[startIndex];
246
- var localMessageType = recordHeader & 15;
247
-
223
+ export function readRecord(blob, messageTypes, developerFields, startIndex, options, startDate, pausedTime) {
224
+ const recordHeader = blob[startIndex];
225
+ let localMessageType = recordHeader & 15;
248
226
  if ((recordHeader & CompressedHeaderMask) === CompressedHeaderMask) {
249
- //compressed timestamp
250
-
251
- var timeoffset = recordHeader & CompressedTimeMask;
252
- timestamp += timeoffset - lastTimeOffset & CompressedTimeMask;
253
- lastTimeOffset = timeoffset;
254
-
255
- localMessageType = (recordHeader & CompressedLocalMesgNumMask) >> 5;
256
- } else if ((recordHeader & 64) === 64) {
227
+ // compressed timestamp
228
+ localMessageType = (recordHeader & CompressedLocalMsgNumMask) >> 5;
229
+ }
230
+ else if ((recordHeader & 64) === 64) {
257
231
  // is definition message
258
232
  // startIndex + 1 is reserved
259
-
260
- var hasDeveloperData = (recordHeader & 32) === 32;
261
- var lEnd = blob[startIndex + 2] === 0;
262
- var numberOfFields = blob[startIndex + 5];
263
- var numberOfDeveloperDataFields = hasDeveloperData ? blob[startIndex + 5 + numberOfFields * 3 + 1] : 0;
264
-
265
- var mTypeDef = {
233
+ const hasDeveloperData = (recordHeader & 32) === 32;
234
+ const lEnd = blob[startIndex + 2] === 0;
235
+ const numberOfFields = blob[startIndex + 5];
236
+ const numberOfDeveloperDataFields = hasDeveloperData
237
+ ? blob[startIndex + 5 + numberOfFields * 3 + 1]
238
+ : 0;
239
+ const mTypeDef = {
266
240
  littleEndian: lEnd,
267
- globalMessageNumber: addEndian(lEnd, [blob[startIndex + 3], blob[startIndex + 4]]),
241
+ globalMessageNumber: addEndian(lEnd, [
242
+ blob[startIndex + 3],
243
+ blob[startIndex + 4],
244
+ ]),
268
245
  numberOfFields: numberOfFields + numberOfDeveloperDataFields,
269
- fieldDefs: []
246
+ fieldDefs: [],
270
247
  };
271
-
272
- var _message = (0, _messages.getFitMessage)(mTypeDef.globalMessageNumber);
273
-
274
- for (var i = 0; i < numberOfFields; i++) {
275
- var fDefIndex = startIndex + 6 + i * 3;
276
- var baseType = blob[fDefIndex + 2];
277
-
278
- var _message$getAttribute = _message.getAttributes(blob[fDefIndex]),
279
- field = _message$getAttribute.field,
280
- type = _message$getAttribute.type;
281
-
282
- var fDef = {
283
- type: type,
248
+ const message = getFitMessage(mTypeDef.globalMessageNumber);
249
+ for (let i = 0; i < numberOfFields; i++) {
250
+ const fDefIndex = startIndex + 6 + i * 3;
251
+ const baseType = blob[fDefIndex + 2];
252
+ const { field, type } = message.getAttributes(blob[fDefIndex]);
253
+ const fDef = {
254
+ type,
284
255
  fDefNo: blob[fDefIndex],
285
256
  size: blob[fDefIndex + 1],
286
257
  endianAbility: (baseType & 128) === 128,
287
258
  littleEndian: lEnd,
288
259
  baseTypeNo: baseType & 15,
289
260
  name: field,
290
- dataType: (0, _messages.getFitMessageBaseType)(baseType & 15)
261
+ dataType: getFitMessageBaseType(baseType & 15),
291
262
  };
292
-
293
263
  mTypeDef.fieldDefs.push(fDef);
294
264
  }
295
-
296
265
  // numberOfDeveloperDataFields = 0 so it wont crash here and wont loop
297
- for (var _i5 = 0; _i5 < numberOfDeveloperDataFields; _i5++) {
266
+ for (let i = 0; i < numberOfDeveloperDataFields; i++) {
298
267
  // If we fail to parse then try catch
299
268
  try {
300
- var _fDefIndex = startIndex + 6 + numberOfFields * 3 + 1 + _i5 * 3;
301
-
302
- var fieldNum = blob[_fDefIndex];
303
- var size = blob[_fDefIndex + 1];
304
- var devDataIndex = blob[_fDefIndex + 2];
305
-
306
- var devDef = developerFields[devDataIndex][fieldNum];
307
-
308
- var _baseType = devDef.fit_base_type_id;
309
-
310
- var _fDef = {
311
- type: _fit.FIT.types.fit_base_type[_baseType],
269
+ const fDefIndex = startIndex + 6 + numberOfFields * 3 + 1 + i * 3;
270
+ const fieldNum = blob[fDefIndex];
271
+ const size = blob[fDefIndex + 1];
272
+ const devDataIndex = blob[fDefIndex + 2];
273
+ const devDef = developerFields[devDataIndex][fieldNum];
274
+ const baseType = devDef.fit_base_type_id;
275
+ const fDef = {
276
+ type: FIT.types.fit_base_type[baseType],
312
277
  fDefNo: fieldNum,
313
- size: size,
314
- endianAbility: (_baseType & 128) === 128,
278
+ size,
279
+ endianAbility: (baseType & 128) === 128,
315
280
  littleEndian: lEnd,
316
- baseTypeNo: _baseType & 15,
281
+ baseTypeNo: baseType & 15,
317
282
  name: devDef.field_name,
318
- dataType: (0, _messages.getFitMessageBaseType)(_baseType & 15),
283
+ dataType: getFitMessageBaseType(baseType & 15),
319
284
  scale: devDef.scale || 1,
320
285
  offset: devDef.offset || 0,
321
286
  developerDataIndex: devDataIndex,
322
- isDeveloperField: true
287
+ isDeveloperField: true,
323
288
  };
324
-
325
- mTypeDef.fieldDefs.push(_fDef);
326
- } catch (e) {
289
+ mTypeDef.fieldDefs.push(fDef);
290
+ }
291
+ catch (e) {
327
292
  if (options.force) {
328
293
  continue;
329
294
  }
330
295
  throw e;
331
296
  }
332
297
  }
333
-
334
298
  messageTypes[localMessageType] = mTypeDef;
335
-
336
- var nextIndex = startIndex + 6 + mTypeDef.numberOfFields * 3;
337
- var nextIndexWithDeveloperData = nextIndex + 1;
338
-
299
+ const nextIndex = startIndex + 6 + mTypeDef.numberOfFields * 3;
300
+ const nextIndexWithDeveloperData = nextIndex + 1;
339
301
  return {
340
302
  messageType: 'definition',
341
- nextIndex: hasDeveloperData ? nextIndexWithDeveloperData : nextIndex
303
+ nextIndex: hasDeveloperData ? nextIndexWithDeveloperData : nextIndex,
342
304
  };
343
305
  }
344
-
345
- var messageType = messageTypes[localMessageType] || messageTypes[0];
346
-
306
+ const messageType = messageTypes[localMessageType] || messageTypes[0];
347
307
  // TODO: handle compressed header ((recordHeader & 128) == 128)
348
-
349
308
  // uncompressed header
350
- var messageSize = 0;
351
- var readDataFromIndex = startIndex + 1;
352
- var fields = {};
353
- var message = (0, _messages.getFitMessage)(messageType.globalMessageNumber);
354
-
355
- for (var _i6 = 0; _i6 < messageType.fieldDefs.length; _i6++) {
356
- var _fDef2 = messageType.fieldDefs[_i6];
357
- var data = readData(blob, _fDef2, readDataFromIndex, options);
358
-
359
- if (!isInvalidValue(data, _fDef2.type)) {
360
- if (_fDef2.isDeveloperField) {
361
-
362
- var field = _fDef2.name;
363
- var type = _fDef2.type;
364
- var scale = _fDef2.scale;
365
- var offset = _fDef2.offset;
366
-
367
- fields[_fDef2.name] = applyOptions(formatByType(data, type, scale, offset), field, options);
368
- } else {
369
- var _message$getAttribute2 = message.getAttributes(_fDef2.fDefNo),
370
- _field = _message$getAttribute2.field,
371
- _type = _message$getAttribute2.type,
372
- _scale = _message$getAttribute2.scale,
373
- _offset = _message$getAttribute2.offset;
374
-
375
- if (_field !== 'unknown' && _field !== '' && _field !== undefined) {
376
- fields[_field] = applyOptions(formatByType(data, _type, _scale, _offset), _field, options);
309
+ let messageSize = 0;
310
+ let readDataFromIndex = startIndex + 1;
311
+ const fields = {};
312
+ const message = getFitMessage(messageType.globalMessageNumber);
313
+ for (let i = 0; i < messageType.fieldDefs.length; i++) {
314
+ const fDef = messageType.fieldDefs[i];
315
+ const data = readData(blob, fDef, readDataFromIndex, options);
316
+ if (!isInvalidValue(data, fDef.type)) {
317
+ if (fDef.isDeveloperField) {
318
+ const field = fDef.name;
319
+ const { type } = fDef;
320
+ const { scale } = fDef;
321
+ const { offset } = fDef;
322
+ fields[fDef.name] = applyOptions(formatByType(data, type, scale, offset), field, options);
323
+ }
324
+ else {
325
+ const { field, type, scale, offset } = message.getAttributes(fDef.fDefNo);
326
+ if (field !== 'unknown' && field !== '' && field !== undefined) {
327
+ fields[field] = applyOptions(formatByType(data, type, scale, offset), field, options);
377
328
  }
378
329
  }
379
-
380
330
  if (message.name === 'record' && options.elapsedRecordField) {
381
- fields.elapsed_time = (fields.timestamp - startDate) / 1000;
331
+ fields.elapsed_time = (fields.timestamp - (startDate || 0)) / 1000;
382
332
  fields.timer_time = fields.elapsed_time - pausedTime;
383
333
  }
384
334
  }
385
-
386
- readDataFromIndex += _fDef2.size;
387
- messageSize += _fDef2.size;
335
+ readDataFromIndex += fDef.size;
336
+ messageSize += fDef.size;
388
337
  }
389
-
390
338
  if (message.name === 'field_description') {
391
- developerFields[fields.developer_data_index] = developerFields[fields.developer_data_index] || [];
339
+ developerFields[fields.developer_data_index]
340
+ = developerFields[fields.developer_data_index] || [];
392
341
  developerFields[fields.developer_data_index][fields.field_definition_number] = fields;
393
342
  }
394
-
395
343
  if (message.name === 'monitoring') {
396
- //we need to keep the raw timestamp value so we can calculate subsequent timestamp16 fields
344
+ // TODO weirdly uses global variables?
345
+ // we need to keep the raw timestamp value so we can calculate subsequent timestamp16 fields
397
346
  if (fields.timestamp) {
398
347
  monitoring_timestamp = fields.timestamp;
399
348
  fields.timestamp = new Date(fields.timestamp * 1000 + GarminTimeOffset);
400
349
  }
401
350
  if (fields.timestamp16 && !fields.timestamp) {
402
- monitoring_timestamp += fields.timestamp16 - (monitoring_timestamp & 0xFFFF) & 0xFFFF;
403
- //fields.timestamp = monitoring_timestamp;
351
+ monitoring_timestamp
352
+ += (fields.timestamp16 - (monitoring_timestamp & 0xFFFF)) & 0xFFFF;
353
+ // fields.timestamp = monitoring_timestamp;
404
354
  fields.timestamp = new Date(monitoring_timestamp * 1000 + GarminTimeOffset);
405
355
  }
406
356
  }
407
-
408
- var result = {
357
+ return {
409
358
  messageType: message.name,
410
359
  nextIndex: startIndex + messageSize + 1,
411
- message: fields
360
+ message: fields,
412
361
  };
413
-
414
- return result;
415
362
  }
416
-
417
- function getArrayBuffer(buffer) {
363
+ export function getArrayBuffer(buffer) {
418
364
  if (buffer instanceof ArrayBuffer) {
419
365
  return buffer;
420
366
  }
421
- var ab = new ArrayBuffer(buffer.length);
422
- var view = new Uint8Array(ab);
423
- for (var i = 0; i < buffer.length; ++i) {
367
+ const ab = new ArrayBuffer(buffer.length);
368
+ const view = new Uint8Array(ab);
369
+ for (let i = 0; i < buffer.length; ++i) {
424
370
  view[i] = buffer[i];
425
371
  }
426
372
  return ab;
427
373
  }
428
-
429
- function calculateCRC(blob, start, end) {
430
- var crcTable = [0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400];
431
-
432
- var crc = 0;
433
- for (var i = start; i < end; i++) {
434
- var byteVal = blob[i];
435
- var tmp = crcTable[crc & 0xF];
436
- crc = crc >> 4 & 0x0FFF;
374
+ export function calculateCRC(blob, start, end) {
375
+ const crcTable = [
376
+ 0x0000,
377
+ 0xCC01,
378
+ 0xD801,
379
+ 0x1400,
380
+ 0xF001,
381
+ 0x3C00,
382
+ 0x2800,
383
+ 0xE401,
384
+ 0xA001,
385
+ 0x6C00,
386
+ 0x7800,
387
+ 0xB401,
388
+ 0x5000,
389
+ 0x9C01,
390
+ 0x8801,
391
+ 0x4400,
392
+ ];
393
+ let crc = 0;
394
+ for (let i = start; i < end; i++) {
395
+ const byteVal = blob[i];
396
+ let tmp = crcTable[crc & 0xF];
397
+ crc = (crc >> 4) & 0x0FFF;
437
398
  crc = crc ^ tmp ^ crcTable[byteVal & 0xF];
438
399
  tmp = crcTable[crc & 0xF];
439
- crc = crc >> 4 & 0x0FFF;
440
- crc = crc ^ tmp ^ crcTable[byteVal >> 4 & 0xF];
400
+ crc = (crc >> 4) & 0x0FFF;
401
+ crc = crc ^ tmp ^ crcTable[(byteVal >> 4) & 0xF];
441
402
  }
442
-
443
403
  return crc;
444
- }
404
+ }
@@ -0,0 +1,19 @@
1
+ import type { Buffer } from 'node:buffer';
2
+ import type { ParsedFit } from './types.js';
3
+ export interface FitParserOptions {
4
+ force?: boolean;
5
+ speedUnit?: string;
6
+ lengthUnit?: string;
7
+ temperatureUnit?: string;
8
+ elapsedRecordField?: boolean;
9
+ pressureUnit?: string;
10
+ mode?: 'list' | 'cascade' | 'both';
11
+ }
12
+ type FitParserCallback = (error: string | undefined, data: ParsedFit | undefined) => void;
13
+ export default class FitParser {
14
+ private readonly options;
15
+ constructor(options?: FitParserOptions);
16
+ parseAsync(content: ArrayBuffer | Buffer<ArrayBuffer>): Promise<ParsedFit>;
17
+ parse(content: ArrayBuffer | Buffer<ArrayBuffer>, callback: FitParserCallback): void;
18
+ }
19
+ export {};