fit-file-parser 1.21.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/.github/workflows/ci.yml +29 -0
- package/CHANGELOG.md +22 -22
- package/CONTRIBUTORS.md +3 -1
- package/README.md +39 -21
- package/dist/binary.d.ts +11 -0
- package/dist/binary.js +181 -221
- package/dist/fit-parser.d.ts +19 -0
- package/dist/fit-parser.js +232 -252
- package/dist/fit.d.ts +52 -0
- package/dist/fit.js +7886 -4299
- package/dist/helper.d.ts +3 -0
- package/dist/helper.js +63 -66
- package/dist/messages.d.ts +6 -0
- package/dist/messages.js +19 -20
- package/dist/types.d.ts +55 -0
- package/dist/types.js +1 -0
- package/eslint.config.js +7 -0
- package/package.json +38 -48
- package/tsconfig.json +15 -0
- package/vitest.config.js +8 -0
package/dist/helper.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ParsedLap, ParsedSession } from './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[];
|
package/dist/helper.js
CHANGED
|
@@ -1,70 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
export function mapDataIntoLap(inputLaps, lapKey, data) {
|
|
2
|
+
const laps = [...inputLaps];
|
|
3
|
+
let index = 0;
|
|
4
|
+
for (let i = 0; i < laps.length; i++) {
|
|
5
|
+
const lap = laps[i];
|
|
6
|
+
const nextLap = laps[i + 1];
|
|
7
|
+
const tempData = [];
|
|
8
|
+
const lapStartTime = new Date(lap.start_time).getTime();
|
|
9
|
+
const nextLapStartTime = nextLap
|
|
10
|
+
? new Date(nextLap.start_time).getTime()
|
|
11
|
+
: null;
|
|
12
|
+
for (let j = index; j < data.length; j++) {
|
|
13
|
+
const row = data[j];
|
|
14
|
+
if (nextLap && nextLapStartTime) {
|
|
15
|
+
const timestamp = new Date(row.timestamp).getTime();
|
|
16
|
+
if (lapStartTime <= timestamp && nextLapStartTime > timestamp) {
|
|
17
|
+
tempData.push(row);
|
|
18
|
+
}
|
|
19
|
+
else if (nextLapStartTime <= timestamp) {
|
|
20
|
+
index = j;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
tempData.push(row);
|
|
26
|
+
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!laps[i][lapKey]) {
|
|
34
|
-
laps[i][lapKey] = tempData;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return laps;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
var mapDataIntoSession = exports.mapDataIntoSession = function mapDataIntoSession(inputSessions, laps) {
|
|
42
|
-
var sessions = [].concat(_toConsumableArray(inputSessions));
|
|
43
|
-
var lapIndex = 0;
|
|
44
|
-
for (var i = 0; i < sessions.length; i++) {
|
|
45
|
-
var session = sessions[i];
|
|
46
|
-
var nextSession = sessions[i + 1];
|
|
47
|
-
var tempLaps = [];
|
|
48
|
-
var sessionStartTime = new Date(session.start_time).getTime();
|
|
49
|
-
var nextSessionStartTime = nextSession ? new Date(nextSession.start_time).getTime() : null;
|
|
50
|
-
for (var j = lapIndex; j < laps.length; j++) {
|
|
51
|
-
var lap = laps[j];
|
|
52
|
-
if (nextSession) {
|
|
53
|
-
var lapStartTime = new Date(lap.start_time).getTime();
|
|
54
|
-
if (sessionStartTime <= lapStartTime && nextSessionStartTime > lapStartTime) {
|
|
55
|
-
tempLaps.push(lap);
|
|
56
|
-
} else if (nextSessionStartTime <= lapStartTime) {
|
|
57
|
-
lapIndex = j;
|
|
58
|
-
break;
|
|
28
|
+
if (!laps[i][lapKey]) {
|
|
29
|
+
laps[i][lapKey] = tempData;
|
|
59
30
|
}
|
|
60
|
-
} else {
|
|
61
|
-
tempLaps.push(lap);
|
|
62
|
-
}
|
|
63
31
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
32
|
+
return laps;
|
|
33
|
+
}
|
|
34
|
+
export function mapDataIntoSession(inputSessions, laps) {
|
|
35
|
+
const sessions = [...inputSessions];
|
|
36
|
+
let lapIndex = 0;
|
|
37
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
38
|
+
const session = sessions[i];
|
|
39
|
+
const nextSession = sessions[i + 1];
|
|
40
|
+
const tempLaps = [];
|
|
41
|
+
const sessionStartTime = new Date(session.start_time).getTime();
|
|
42
|
+
const nextSessionStartTime = nextSession
|
|
43
|
+
? new Date(nextSession.start_time).getTime()
|
|
44
|
+
: null;
|
|
45
|
+
for (let j = lapIndex; j < laps.length; j++) {
|
|
46
|
+
const lap = laps[j];
|
|
47
|
+
if (nextSession && nextSessionStartTime) {
|
|
48
|
+
const lapStartTime = new Date(lap.start_time).getTime();
|
|
49
|
+
if (sessionStartTime <= lapStartTime
|
|
50
|
+
&& nextSessionStartTime > lapStartTime) {
|
|
51
|
+
tempLaps.push(lap);
|
|
52
|
+
}
|
|
53
|
+
else if (nextSessionStartTime <= lapStartTime) {
|
|
54
|
+
lapIndex = j;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
tempLaps.push(lap);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!sessions[i].laps) {
|
|
63
|
+
sessions[i].laps = tempLaps;
|
|
64
|
+
}
|
|
67
65
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
};
|
|
66
|
+
return sessions;
|
|
67
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MessageName, MessageObject } from './fit.js';
|
|
2
|
+
export declare function getFitMessage(messageNum: number): {
|
|
3
|
+
name: MessageName | '';
|
|
4
|
+
getAttributes: (fieldNum: number) => MessageObject;
|
|
5
|
+
};
|
|
6
|
+
export declare function getFitMessageBaseType(inp: any): any;
|
package/dist/messages.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
exports.getFitMessage = getFitMessage;
|
|
7
|
-
exports.getFitMessageBaseType = getFitMessageBaseType;
|
|
8
|
-
|
|
9
|
-
var _fit = require('./fit');
|
|
10
|
-
|
|
11
|
-
function getFitMessage(messageNum) {
|
|
12
|
-
return {
|
|
13
|
-
name: (0, _fit.getMessageName)(messageNum),
|
|
14
|
-
getAttributes: function getAttributes(fieldNum) {
|
|
15
|
-
return (0, _fit.getFieldObject)(fieldNum, messageNum);
|
|
1
|
+
import { FIT } from './fit.js';
|
|
2
|
+
function getFieldObject(fieldNum, messageNum) {
|
|
3
|
+
const message = FIT.messages[messageNum];
|
|
4
|
+
if (!message) {
|
|
5
|
+
return {};
|
|
16
6
|
}
|
|
17
|
-
|
|
7
|
+
return message[fieldNum] || {};
|
|
8
|
+
}
|
|
9
|
+
function getMessageName(messageNum) {
|
|
10
|
+
const message = FIT.messages[messageNum];
|
|
11
|
+
return message ? message.name : '';
|
|
12
|
+
}
|
|
13
|
+
export function getFitMessage(messageNum) {
|
|
14
|
+
return {
|
|
15
|
+
name: getMessageName(messageNum),
|
|
16
|
+
getAttributes: (fieldNum) => getFieldObject(fieldNum, messageNum),
|
|
17
|
+
};
|
|
18
18
|
}
|
|
19
|
-
|
|
20
19
|
// TODO
|
|
21
|
-
function getFitMessageBaseType(
|
|
22
|
-
|
|
23
|
-
}
|
|
20
|
+
export function getFitMessageBaseType(inp) {
|
|
21
|
+
return inp;
|
|
22
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -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
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/eslint.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "fit-file-parser",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Parse your .FIT files easily, directly from JS (Garmin, Polar, Suunto)",
|
|
6
|
+
"version": "2.0.0",
|
|
2
7
|
"author": {
|
|
3
8
|
"name": "jimmykane"
|
|
4
9
|
},
|
|
5
|
-
"bugs": {
|
|
6
|
-
"url": "https://github.com/jimmykane/fit-parser"
|
|
7
|
-
},
|
|
8
10
|
"contributors": [
|
|
9
11
|
{
|
|
10
12
|
"email": "jimmykane9@gmail.com",
|
|
@@ -15,40 +17,27 @@
|
|
|
15
17
|
"name": "Wasa Choksuwattanasakul"
|
|
16
18
|
}
|
|
17
19
|
],
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"@babel/core": "^7.4.4",
|
|
21
|
-
"@babel/preset-env": "^7.4.4",
|
|
22
|
-
"babel": "^6.3.26",
|
|
23
|
-
"babel-core": "^6.26.3",
|
|
24
|
-
"babel-polyfill": "^6.26.0",
|
|
25
|
-
"babel-preset-env": "^1.7.0",
|
|
26
|
-
"babel-preset-es2015": "^6.24.1",
|
|
27
|
-
"babel-preset-stage-2": "^6.24.1",
|
|
28
|
-
"babel-register": "^6.26.0",
|
|
29
|
-
"chai": "^3.4.1",
|
|
30
|
-
"del": "^2.2.0",
|
|
31
|
-
"eslint": "^2.8.0",
|
|
32
|
-
"eslint-config-airbnb": "^8.0.0",
|
|
33
|
-
"eslint-plugin-import": "^1.6.1",
|
|
34
|
-
"gulp": "^3.9.1",
|
|
35
|
-
"gulp-babel": "^6.1.3",
|
|
36
|
-
"gulp-jshint": "^2.1.0",
|
|
37
|
-
"gulp-mocha": "^2.2.0",
|
|
38
|
-
"jshint": "^2.10.2",
|
|
39
|
-
"mocha": "^2.3.4",
|
|
40
|
-
"run-sequence": "^1.1.5"
|
|
41
|
-
},
|
|
42
|
-
"directories": {},
|
|
43
|
-
"engine": "node >= 0.10.x",
|
|
20
|
+
"engine": "node >= 20.0.x",
|
|
21
|
+
"license": "MIT",
|
|
44
22
|
"homepage": "https://github.com/jimmykane/fit-parser",
|
|
23
|
+
"repository": {
|
|
24
|
+
"url": "git+ssh://git@github.com/jimmykane/fit-parser.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/jimmykane/fit-parser"
|
|
28
|
+
},
|
|
45
29
|
"keywords": [
|
|
46
30
|
"fit",
|
|
47
31
|
"ant",
|
|
48
32
|
"garmin",
|
|
49
33
|
"parse"
|
|
50
34
|
],
|
|
51
|
-
"
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/fit-parser.d.ts",
|
|
38
|
+
"import": "./dist/fit-parser.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
52
41
|
"main": "dist/fit-parser.js",
|
|
53
42
|
"maintainers": [
|
|
54
43
|
{
|
|
@@ -56,24 +45,25 @@
|
|
|
56
45
|
"name": "Dimitrios Kanellopoulos"
|
|
57
46
|
}
|
|
58
47
|
],
|
|
59
|
-
"name": "fit-file-parser",
|
|
60
|
-
"optionalDependencies": {},
|
|
61
|
-
"private": false,
|
|
62
|
-
"repository": {
|
|
63
|
-
"type": "git",
|
|
64
|
-
"url": "git+ssh://git@github.com/jimmykane/fit-parser.git"
|
|
65
|
-
},
|
|
66
48
|
"scripts": {
|
|
67
|
-
"example-output": "
|
|
68
|
-
"example-output-tank": "
|
|
69
|
-
"example-output-summary-first": "
|
|
70
|
-
"example-output-summary-last": "
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
49
|
+
"example-output": "node examples/parse.js examples/example.fit > examples/output-example.json",
|
|
50
|
+
"example-output-tank": "node examples/parse.js examples/example-diving.fit > examples/output-diving.json",
|
|
51
|
+
"example-output-summary-first": "node examples/parse.js examples/triathlon_summary_first.fit > examples/output_summary_first.json",
|
|
52
|
+
"example-output-summary-last": "node examples/parse.js examples/triathlon_summary_last.fit > examples/output_summary_last.json",
|
|
53
|
+
"pre-examples": "npm run build",
|
|
54
|
+
"examples": "npm run example-output && npm run example-output-tank && npm run example-output-summary-first && npm run example-output-summary-last",
|
|
55
|
+
"test": "vitest",
|
|
56
|
+
"lint": "eslint .",
|
|
57
|
+
"fmt": "eslint --fix .",
|
|
58
|
+
"type-check": "tsc --noEmit",
|
|
59
|
+
"build": "tsc --noCheck"
|
|
74
60
|
},
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
61
|
+
"test": "vitest",
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@antfu/eslint-config": "^6.2.0",
|
|
64
|
+
"@types/node": "^24.10.1",
|
|
65
|
+
"eslint": "^9.10.0",
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"vitest": "^4.0.13"
|
|
78
68
|
}
|
|
79
|
-
}
|
|
69
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"rootDir": "./src",
|
|
5
|
+
"module": "Node16",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"skipLibCheck": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"],
|
|
14
|
+
"exclude": ["node_modules", "**/*.spec.ts"]
|
|
15
|
+
}
|