incyclist-services 1.4.22 → 1.4.23
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/lib/activities/base/model/index.d.ts +1 -0
- package/lib/activities/upload/index.d.ts +1 -0
- package/lib/activities/upload/index.js +1 -0
- package/lib/activities/upload/intervals.d.ts +18 -0
- package/lib/activities/upload/intervals.js +160 -0
- package/lib/activities/upload/strava copy.d.ts +18 -0
- package/lib/activities/upload/strava copy.js +170 -0
- package/lib/apps/base/api/index.d.ts +1 -0
- package/lib/apps/base/api/index.js +1 -0
- package/lib/apps/base/api/intervals/api.d.ts +21 -0
- package/lib/apps/base/api/intervals/api.js +117 -0
- package/lib/apps/base/api/intervals/index.d.ts +2 -0
- package/lib/apps/base/api/intervals/index.js +18 -0
- package/lib/apps/base/api/intervals/types.d.ts +49 -0
- package/lib/apps/base/api/intervals/types.js +2 -0
- package/lib/apps/intervals/IntervalsAppConnection.d.ts +23 -0
- package/lib/apps/intervals/IntervalsAppConnection.js +203 -0
- package/lib/apps/intervals/StravaAppConnection.d.ts +28 -0
- package/lib/apps/intervals/StravaAppConnection.js +211 -0
- package/lib/apps/intervals/index.d.ts +0 -0
- package/lib/apps/intervals/index.js +0 -0
- package/lib/apps/intervals/types.d.ts +6 -0
- package/lib/apps/intervals/types.js +2 -0
- package/lib/apps/service.js +3 -1
- package/package.json +1 -1
|
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./velohero"), exports);
|
|
18
18
|
__exportStar(require("./strava"), exports);
|
|
19
|
+
__exportStar(require("./intervals"), exports);
|
|
19
20
|
__exportStar(require("./types"), exports);
|
|
20
21
|
__exportStar(require("./factory"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IncyclistService } from "../../base/service";
|
|
2
|
+
import { ActivityDetails } from "../base";
|
|
3
|
+
import { IActivityUpload } from "./types";
|
|
4
|
+
import { IntervalsAppConnection } from "../../apps/intervals/IntervalsAppConnection";
|
|
5
|
+
import { IntervalsFormat } from "../../apps";
|
|
6
|
+
export declare class IntervalsUpload extends IncyclistService implements IActivityUpload {
|
|
7
|
+
protected isInitialized: any;
|
|
8
|
+
protected connection: IntervalsAppConnection;
|
|
9
|
+
constructor();
|
|
10
|
+
init(): boolean;
|
|
11
|
+
isConnected(): boolean;
|
|
12
|
+
upload(activity: ActivityDetails, format?: string): Promise<boolean>;
|
|
13
|
+
getUrl(activityId: string): string;
|
|
14
|
+
protected getIntervalsFormat(format: string): IntervalsFormat;
|
|
15
|
+
protected ensureInitialized(): any;
|
|
16
|
+
protected getIntervalsAppConnection(): IntervalsAppConnection;
|
|
17
|
+
protected getApi(): import("../../apps").IntervalsApi;
|
|
18
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
46
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
47
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.IntervalsUpload = void 0;
|
|
51
|
+
const service_1 = require("../../base/service");
|
|
52
|
+
const types_1 = require("../../base/types");
|
|
53
|
+
const Injection_1 = require("../../base/decorators/Injection");
|
|
54
|
+
const factory_1 = require("./factory");
|
|
55
|
+
const IntervalsAppConnection_1 = require("../../apps/intervals/IntervalsAppConnection");
|
|
56
|
+
let IntervalsUpload = (() => {
|
|
57
|
+
let _classDecorators = [types_1.Singleton];
|
|
58
|
+
let _classDescriptor;
|
|
59
|
+
let _classExtraInitializers = [];
|
|
60
|
+
let _classThis;
|
|
61
|
+
let _classSuper = service_1.IncyclistService;
|
|
62
|
+
let _instanceExtraInitializers = [];
|
|
63
|
+
let _getIntervalsAppConnection_decorators;
|
|
64
|
+
var IntervalsUpload = _classThis = class extends _classSuper {
|
|
65
|
+
constructor() {
|
|
66
|
+
super('IntervalsUpload');
|
|
67
|
+
this.isInitialized = __runInitializers(this, _instanceExtraInitializers);
|
|
68
|
+
this.connection = new IntervalsAppConnection_1.IntervalsAppConnection();
|
|
69
|
+
this.isInitialized = false;
|
|
70
|
+
this.init();
|
|
71
|
+
}
|
|
72
|
+
init() {
|
|
73
|
+
if (this.isInitialized)
|
|
74
|
+
return true;
|
|
75
|
+
this.isInitialized = this.getIntervalsAppConnection().init();
|
|
76
|
+
return this.isInitialized;
|
|
77
|
+
}
|
|
78
|
+
isConnected() {
|
|
79
|
+
return this.getIntervalsAppConnection().isConnected();
|
|
80
|
+
}
|
|
81
|
+
upload(activity_1) {
|
|
82
|
+
return __awaiter(this, arguments, void 0, function* (activity, format = 'TCX') {
|
|
83
|
+
try {
|
|
84
|
+
const ok = this.ensureInitialized();
|
|
85
|
+
if (!ok) {
|
|
86
|
+
this.logEvent({ message: 'Intervals.icu Upload skipped', reason: 'not initialized' });
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (!this.isConnected())
|
|
90
|
+
return false;
|
|
91
|
+
const lcFormat = format.toLowerCase();
|
|
92
|
+
const ucFormat = format.toUpperCase();
|
|
93
|
+
this.logEvent({ message: 'Intervals.icu Upload', format: ucFormat });
|
|
94
|
+
if (!activity.links)
|
|
95
|
+
activity.links = {};
|
|
96
|
+
const fileName = activity[`${lcFormat}FileName`];
|
|
97
|
+
const res = yield this.getApi().upload(fileName, {
|
|
98
|
+
name: activity.title,
|
|
99
|
+
description: '',
|
|
100
|
+
format: this.getIntervalsFormat(format)
|
|
101
|
+
});
|
|
102
|
+
this.logEvent({ message: 'Intervals.icu Upload success', activityId: res.intervalsId });
|
|
103
|
+
activity.links.intervals = {
|
|
104
|
+
activity_id: res.intervalsId,
|
|
105
|
+
url: this.getUrl(res.intervalsId)
|
|
106
|
+
};
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
this.logEvent({ message: 'Intervals.icu Upload failure', error: err.message });
|
|
111
|
+
activity.links.intervals = {
|
|
112
|
+
error: err.message
|
|
113
|
+
};
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
getUrl(activityId) {
|
|
119
|
+
return `https://intervals.icu/activities/${activityId}`;
|
|
120
|
+
}
|
|
121
|
+
getIntervalsFormat(format) {
|
|
122
|
+
switch (format.toLowerCase()) {
|
|
123
|
+
case 'tcx':
|
|
124
|
+
return 'tcx';
|
|
125
|
+
case 'fit':
|
|
126
|
+
return 'fit';
|
|
127
|
+
case 'gox':
|
|
128
|
+
return 'gpx';
|
|
129
|
+
default:
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
ensureInitialized() {
|
|
134
|
+
if (!this.isInitialized)
|
|
135
|
+
this.init();
|
|
136
|
+
return this.isInitialized;
|
|
137
|
+
}
|
|
138
|
+
getIntervalsAppConnection() {
|
|
139
|
+
return this.connection;
|
|
140
|
+
}
|
|
141
|
+
getApi() {
|
|
142
|
+
return this.getIntervalsAppConnection().getApi();
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
__setFunctionName(_classThis, "IntervalsUpload");
|
|
146
|
+
(() => {
|
|
147
|
+
var _a;
|
|
148
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create((_a = _classSuper[Symbol.metadata]) !== null && _a !== void 0 ? _a : null) : void 0;
|
|
149
|
+
_getIntervalsAppConnection_decorators = [Injection_1.Injectable];
|
|
150
|
+
__esDecorate(_classThis, null, _getIntervalsAppConnection_decorators, { kind: "method", name: "getIntervalsAppConnection", static: false, private: false, access: { has: obj => "getIntervalsAppConnection" in obj, get: obj => obj.getIntervalsAppConnection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
151
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
152
|
+
IntervalsUpload = _classThis = _classDescriptor.value;
|
|
153
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
154
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
155
|
+
})();
|
|
156
|
+
return IntervalsUpload = _classThis;
|
|
157
|
+
})();
|
|
158
|
+
exports.IntervalsUpload = IntervalsUpload;
|
|
159
|
+
const factory = new factory_1.ActivityUploadFactory();
|
|
160
|
+
factory.add('intervals', new IntervalsUpload());
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IncyclistService } from "../../base/service";
|
|
2
|
+
import { ActivityDetails } from "../base";
|
|
3
|
+
import { StravaFormat } from "../../apps/base/api/strava";
|
|
4
|
+
import { IActivityUpload } from "./types";
|
|
5
|
+
import { StravaAppConnection } from "../../apps/strava/StravaAppConnection";
|
|
6
|
+
export declare class StravaUpload extends IncyclistService implements IActivityUpload {
|
|
7
|
+
protected isInitialized: any;
|
|
8
|
+
protected connection: StravaAppConnection;
|
|
9
|
+
constructor();
|
|
10
|
+
init(): boolean;
|
|
11
|
+
isConnected(): boolean;
|
|
12
|
+
upload(activity: ActivityDetails, format?: string): Promise<boolean>;
|
|
13
|
+
getUrl(activityId: string): string;
|
|
14
|
+
protected getStravaFormat(format: string): StravaFormat;
|
|
15
|
+
protected ensureInitialized(): any;
|
|
16
|
+
protected getStravaAppConnection(): StravaAppConnection;
|
|
17
|
+
protected getApi(): import("../../apps/base/api/strava").StravaApi;
|
|
18
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
46
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
47
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.StravaUpload = void 0;
|
|
51
|
+
const service_1 = require("../../base/service");
|
|
52
|
+
const types_1 = require("../../base/types");
|
|
53
|
+
const strava_1 = require("../../apps/base/api/strava");
|
|
54
|
+
const Injection_1 = require("../../base/decorators/Injection");
|
|
55
|
+
const factory_1 = require("./factory");
|
|
56
|
+
const StravaAppConnection_1 = require("../../apps/strava/StravaAppConnection");
|
|
57
|
+
let StravaUpload = (() => {
|
|
58
|
+
let _classDecorators = [types_1.Singleton];
|
|
59
|
+
let _classDescriptor;
|
|
60
|
+
let _classExtraInitializers = [];
|
|
61
|
+
let _classThis;
|
|
62
|
+
let _classSuper = service_1.IncyclistService;
|
|
63
|
+
let _instanceExtraInitializers = [];
|
|
64
|
+
let _getStravaAppConnection_decorators;
|
|
65
|
+
var StravaUpload = _classThis = class extends _classSuper {
|
|
66
|
+
constructor() {
|
|
67
|
+
super('StravaUpload');
|
|
68
|
+
this.isInitialized = __runInitializers(this, _instanceExtraInitializers);
|
|
69
|
+
this.connection = new StravaAppConnection_1.StravaAppConnection();
|
|
70
|
+
this.isInitialized = false;
|
|
71
|
+
this.init();
|
|
72
|
+
}
|
|
73
|
+
init() {
|
|
74
|
+
if (this.isInitialized)
|
|
75
|
+
return true;
|
|
76
|
+
this.isInitialized = this.getStravaAppConnection().init();
|
|
77
|
+
return this.isInitialized;
|
|
78
|
+
}
|
|
79
|
+
isConnected() {
|
|
80
|
+
return this.getStravaAppConnection().isConnected();
|
|
81
|
+
}
|
|
82
|
+
upload(activity_1) {
|
|
83
|
+
return __awaiter(this, arguments, void 0, function* (activity, format = 'TCX') {
|
|
84
|
+
try {
|
|
85
|
+
const ok = this.ensureInitialized();
|
|
86
|
+
if (!ok) {
|
|
87
|
+
this.logEvent({ message: 'Strava Upload skipped', reason: 'not initialized' });
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (!this.isConnected())
|
|
91
|
+
return false;
|
|
92
|
+
const lcFormat = format.toLowerCase();
|
|
93
|
+
const ucFormat = format.toUpperCase();
|
|
94
|
+
this.logEvent({ message: 'Strava Upload', format: ucFormat });
|
|
95
|
+
if (!activity.links)
|
|
96
|
+
activity.links = {};
|
|
97
|
+
const fileName = activity[`${lcFormat}FileName`];
|
|
98
|
+
const res = yield this.getApi().upload(fileName, {
|
|
99
|
+
name: activity.title,
|
|
100
|
+
description: '',
|
|
101
|
+
format: this.getStravaFormat(format)
|
|
102
|
+
});
|
|
103
|
+
this.logEvent({ message: 'Strava Upload success', activityId: res.stravaId });
|
|
104
|
+
activity.links.strava = {
|
|
105
|
+
activity_id: res.stravaId,
|
|
106
|
+
url: this.getUrl(res.stravaId)
|
|
107
|
+
};
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err instanceof strava_1.DuplicateError) {
|
|
112
|
+
this.logEvent({ message: 'Strava Upload failure', error: 'duplicate', activityId: err.stravaId });
|
|
113
|
+
activity.links.strava = {
|
|
114
|
+
activity_id: err.stravaId,
|
|
115
|
+
url: this.getUrl(err.stravaId)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.logEvent({ message: 'Strava Upload failure', error: err.message });
|
|
120
|
+
activity.links.strava = {
|
|
121
|
+
error: err.message
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
getUrl(activityId) {
|
|
129
|
+
return `https://www.strava.com/activities/${activityId}`;
|
|
130
|
+
}
|
|
131
|
+
getStravaFormat(format) {
|
|
132
|
+
switch (format.toLowerCase()) {
|
|
133
|
+
case 'tcx':
|
|
134
|
+
return 'tcx';
|
|
135
|
+
case 'fit':
|
|
136
|
+
return 'fit';
|
|
137
|
+
case 'gox':
|
|
138
|
+
return 'gpx';
|
|
139
|
+
default:
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
ensureInitialized() {
|
|
144
|
+
if (!this.isInitialized)
|
|
145
|
+
this.init();
|
|
146
|
+
return this.isInitialized;
|
|
147
|
+
}
|
|
148
|
+
getStravaAppConnection() {
|
|
149
|
+
return this.connection;
|
|
150
|
+
}
|
|
151
|
+
getApi() {
|
|
152
|
+
return this.getStravaAppConnection().getApi();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
__setFunctionName(_classThis, "StravaUpload");
|
|
156
|
+
(() => {
|
|
157
|
+
var _a;
|
|
158
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create((_a = _classSuper[Symbol.metadata]) !== null && _a !== void 0 ? _a : null) : void 0;
|
|
159
|
+
_getStravaAppConnection_decorators = [Injection_1.Injectable];
|
|
160
|
+
__esDecorate(_classThis, null, _getStravaAppConnection_decorators, { kind: "method", name: "getStravaAppConnection", static: false, private: false, access: { has: obj => "getStravaAppConnection" in obj, get: obj => obj.getStravaAppConnection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
161
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
162
|
+
StravaUpload = _classThis = _classDescriptor.value;
|
|
163
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
164
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
165
|
+
})();
|
|
166
|
+
return StravaUpload = _classThis;
|
|
167
|
+
})();
|
|
168
|
+
exports.StravaUpload = StravaUpload;
|
|
169
|
+
const factory = new factory_1.ActivityUploadFactory();
|
|
170
|
+
factory.add('strava', new StravaUpload());
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Observer } from "../../../../base/types/observer";
|
|
2
|
+
import { AppApiBase } from "../base";
|
|
3
|
+
import { EventLogger } from 'gd-eventlog';
|
|
4
|
+
import { AxiosResponse } from "axios";
|
|
5
|
+
import { IntervalsAthlete, IntervalsConfig, IntervalsUploadProps, IntervalsUploadRequest, IntervalsUploadResult } from "./types";
|
|
6
|
+
export declare class IntervalsApi extends AppApiBase {
|
|
7
|
+
protected config: IntervalsConfig;
|
|
8
|
+
protected logger: EventLogger;
|
|
9
|
+
protected observer: Observer;
|
|
10
|
+
constructor();
|
|
11
|
+
init(config: IntervalsConfig): Observer;
|
|
12
|
+
update(config: Partial<IntervalsConfig>): void;
|
|
13
|
+
isAuthenticated(): boolean;
|
|
14
|
+
upload(fileName: string, props?: IntervalsUploadProps): Promise<IntervalsUploadResult>;
|
|
15
|
+
getLoggedInAthlete(): Promise<IntervalsAthlete>;
|
|
16
|
+
protected verifyAuthentication(): Promise<void>;
|
|
17
|
+
protected createUpload(request: IntervalsUploadRequest): Promise<IntervalsUploadResult>;
|
|
18
|
+
protected get(url: string, config?: object): Promise<AxiosResponse>;
|
|
19
|
+
protected getUploadParams(request: IntervalsUploadRequest): string;
|
|
20
|
+
protected getBaseUrl(): any;
|
|
21
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IntervalsApi = void 0;
|
|
13
|
+
const observer_1 = require("../../../../base/types/observer");
|
|
14
|
+
const valid_1 = require("../../../../utils/valid");
|
|
15
|
+
const base_1 = require("../base");
|
|
16
|
+
const gd_eventlog_1 = require("gd-eventlog");
|
|
17
|
+
const API_BASE_URL = 'https://intervals.icu/api/v1';
|
|
18
|
+
class IntervalsApi extends base_1.AppApiBase {
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.logger = new gd_eventlog_1.EventLogger('IntervalsApi');
|
|
22
|
+
this.observer = new observer_1.Observer();
|
|
23
|
+
}
|
|
24
|
+
init(config) {
|
|
25
|
+
this.config = config;
|
|
26
|
+
return this.observer;
|
|
27
|
+
}
|
|
28
|
+
update(config) {
|
|
29
|
+
if (!this.config)
|
|
30
|
+
throw new Error('update not allowed before init');
|
|
31
|
+
this.config = Object.assign(Object.assign({}, this.config), config);
|
|
32
|
+
}
|
|
33
|
+
isAuthenticated() {
|
|
34
|
+
var _a;
|
|
35
|
+
return (0, valid_1.valid)((_a = this.config) === null || _a === void 0 ? void 0 : _a.accessToken);
|
|
36
|
+
}
|
|
37
|
+
upload(fileName, props) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
yield this.verifyAuthentication();
|
|
40
|
+
const request = {
|
|
41
|
+
file: { type: 'file', fileName },
|
|
42
|
+
name: props === null || props === void 0 ? void 0 : props.name,
|
|
43
|
+
description: props === null || props === void 0 ? void 0 : props.description,
|
|
44
|
+
externalId: props.externalId
|
|
45
|
+
};
|
|
46
|
+
return yield this.createUpload(request);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
getLoggedInAthlete() {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
var _a;
|
|
52
|
+
const response = yield this.get('/athlete/0/profile');
|
|
53
|
+
return (_a = response.data) === null || _a === void 0 ? void 0 : _a.athlete;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
verifyAuthentication() {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
if (!this.isAuthenticated())
|
|
59
|
+
throw new Error('not authenticated');
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
createUpload(request) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
65
|
+
const reqOpts = {
|
|
66
|
+
headers: {
|
|
67
|
+
Authorization: 'Bearer ' + this.config.accessToken
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
let url = `/athlete/0/activities${this.getUploadParams(request)}`;
|
|
71
|
+
const form = yield this.createForm(url, { file: request.file }, reqOpts);
|
|
72
|
+
const response = yield this.postForm(form);
|
|
73
|
+
if (response.data && !response.error && !response.data.error) {
|
|
74
|
+
const result = response.data;
|
|
75
|
+
return {
|
|
76
|
+
externalId: request.externalId,
|
|
77
|
+
intervalsId: result.id
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const result = response.data;
|
|
82
|
+
if (result === null || result === void 0 ? void 0 : result.error)
|
|
83
|
+
throw new Error(result.error);
|
|
84
|
+
throw new Error((_h = (_g = (_d = (_c = (_b = (_a = response.error) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) !== null && _d !== void 0 ? _d : (_f = (_e = response.error) === null || _e === void 0 ? void 0 : _e.response) === null || _f === void 0 ? void 0 : _f.message) !== null && _g !== void 0 ? _g : response.error.message) !== null && _h !== void 0 ? _h : `HTTP error ${response.status}`);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
get(url, config) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
const props = config !== null && config !== void 0 ? config : {};
|
|
91
|
+
const request = Object.assign({ method: 'get', url: this.getBaseUrl() + url, headers: {
|
|
92
|
+
Authorization: 'Bearer ' + this.config.accessToken
|
|
93
|
+
} }, props);
|
|
94
|
+
const response = yield this.getApi().request(request);
|
|
95
|
+
return response;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
getUploadParams(request) {
|
|
99
|
+
const params = [];
|
|
100
|
+
if (request.name)
|
|
101
|
+
params.push(`name=${request.name}`);
|
|
102
|
+
if (request.description)
|
|
103
|
+
params.push(`description=${request.description}`);
|
|
104
|
+
if (params.length === 0)
|
|
105
|
+
return '';
|
|
106
|
+
return '?' + params.join('&');
|
|
107
|
+
}
|
|
108
|
+
getBaseUrl() {
|
|
109
|
+
try {
|
|
110
|
+
return this.getUserSettings().get('INTERVALS_API', API_BASE_URL);
|
|
111
|
+
}
|
|
112
|
+
catch (_a) {
|
|
113
|
+
return API_BASE_URL;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.IntervalsApi = IntervalsApi;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./api"), exports);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type IntervalsConfig = {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
};
|
|
4
|
+
export type IntervalsUploadRequest = {
|
|
5
|
+
file: any;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
externalId?: string;
|
|
9
|
+
};
|
|
10
|
+
export type IntervalsUploadProps = {
|
|
11
|
+
format: IntervalsFormat;
|
|
12
|
+
name?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
externalId?: string;
|
|
15
|
+
};
|
|
16
|
+
export type IntervalsActivity = {
|
|
17
|
+
icu_athlete_id: string;
|
|
18
|
+
id: string;
|
|
19
|
+
};
|
|
20
|
+
export type IntervalsUploadResponse = {
|
|
21
|
+
icu_athlete_id?: string;
|
|
22
|
+
id?: string;
|
|
23
|
+
status?: number;
|
|
24
|
+
error?: string;
|
|
25
|
+
activities?: IntervalsActivity[];
|
|
26
|
+
};
|
|
27
|
+
export type IntervalsUploadResult = {
|
|
28
|
+
intervalsId?: string;
|
|
29
|
+
externalId?: string;
|
|
30
|
+
};
|
|
31
|
+
export type IntervalsAthleteResult = {
|
|
32
|
+
athlete: IntervalsAthlete;
|
|
33
|
+
sharedFolders: any;
|
|
34
|
+
customItems: any;
|
|
35
|
+
};
|
|
36
|
+
export type IntervalsAthlete = {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
profile_medium: string;
|
|
40
|
+
city: string;
|
|
41
|
+
state: string;
|
|
42
|
+
country: string;
|
|
43
|
+
timezone: string;
|
|
44
|
+
sex: string;
|
|
45
|
+
bio: string;
|
|
46
|
+
website: string;
|
|
47
|
+
email: string;
|
|
48
|
+
};
|
|
49
|
+
export type IntervalsFormat = 'fit' | 'fit.gz' | 'tcx' | 'tcx.gz' | 'gpx' | 'gpx.gz';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { IntervalsApi, IntervalsConfig } from "../base/api";
|
|
2
|
+
import { ConnectedAppService } from "../base/app";
|
|
3
|
+
import { IntervalsCredentials } from "./types";
|
|
4
|
+
export declare class IntervalsAppConnection extends ConnectedAppService<IntervalsCredentials> {
|
|
5
|
+
protected config: IntervalsConfig;
|
|
6
|
+
protected api: IntervalsApi;
|
|
7
|
+
constructor();
|
|
8
|
+
connect(credentials: IntervalsCredentials): Promise<boolean>;
|
|
9
|
+
isConnecting(): boolean;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
isConnected(): boolean;
|
|
12
|
+
getCredentials(): IntervalsCredentials;
|
|
13
|
+
getApi(): IntervalsApi;
|
|
14
|
+
protected initAuth(): boolean;
|
|
15
|
+
protected updateConfig(config: IntervalsConfig): void;
|
|
16
|
+
protected saveCredentials(config?: IntervalsConfig): void;
|
|
17
|
+
protected getSecret(key: string): string;
|
|
18
|
+
protected buildConfigFromCredentials(credentials: IntervalsCredentials): {
|
|
19
|
+
accessToken: string;
|
|
20
|
+
};
|
|
21
|
+
protected initApi(config: IntervalsConfig): void;
|
|
22
|
+
protected getSecretBindings(): import("../../api/bindings/secret").ISecretBinding;
|
|
23
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
46
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
47
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.IntervalsAppConnection = void 0;
|
|
51
|
+
const api_1 = require("../../api");
|
|
52
|
+
const decorators_1 = require("../../base/decorators");
|
|
53
|
+
const valid_1 = require("../../utils/valid");
|
|
54
|
+
const api_2 = require("../base/api");
|
|
55
|
+
const app_1 = require("../base/app");
|
|
56
|
+
let IntervalsAppConnection = (() => {
|
|
57
|
+
let _classDecorators = [decorators_1.Singleton];
|
|
58
|
+
let _classDescriptor;
|
|
59
|
+
let _classExtraInitializers = [];
|
|
60
|
+
let _classThis;
|
|
61
|
+
let _classSuper = app_1.ConnectedAppService;
|
|
62
|
+
let _instanceExtraInitializers = [];
|
|
63
|
+
let _getSecretBindings_decorators;
|
|
64
|
+
var IntervalsAppConnection = _classThis = class extends _classSuper {
|
|
65
|
+
constructor() {
|
|
66
|
+
super('IntervalsAppConnection', 'intervals');
|
|
67
|
+
this.config = __runInitializers(this, _instanceExtraInitializers);
|
|
68
|
+
}
|
|
69
|
+
connect(credentials) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
this.ensureInitialized();
|
|
72
|
+
this.logEvent({ message: 'Connect with Intervals.icu' });
|
|
73
|
+
try {
|
|
74
|
+
const isConnected = this.isConnected();
|
|
75
|
+
const config = this.buildConfigFromCredentials(credentials);
|
|
76
|
+
if (isConnected) {
|
|
77
|
+
this.getApi().update(config);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.initApi(config);
|
|
81
|
+
this.saveCredentials(config);
|
|
82
|
+
}
|
|
83
|
+
this.logEvent({ message: 'Connect with Intervals.icu success' });
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
this.logError(err, 'connect');
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
isConnecting() {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
disconnect() {
|
|
96
|
+
try {
|
|
97
|
+
this.config = undefined;
|
|
98
|
+
this.saveCredentials();
|
|
99
|
+
this.getApi().init(undefined);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
this.logError(err, 'disconnect');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
isConnected() {
|
|
106
|
+
if (!this.isInitialized) {
|
|
107
|
+
this.init();
|
|
108
|
+
}
|
|
109
|
+
if (this.getApi().isAuthenticated() && !this.config) {
|
|
110
|
+
this.initAuth();
|
|
111
|
+
}
|
|
112
|
+
return ((0, valid_1.valid)(this.config));
|
|
113
|
+
}
|
|
114
|
+
getCredentials() {
|
|
115
|
+
const userSettings = this.getUserSettings();
|
|
116
|
+
try {
|
|
117
|
+
return userSettings.get('user.auth.intervals', null);
|
|
118
|
+
}
|
|
119
|
+
catch (_a) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
getApi() {
|
|
124
|
+
if (!this.api)
|
|
125
|
+
this.api = new api_2.IntervalsApi();
|
|
126
|
+
return this.api;
|
|
127
|
+
}
|
|
128
|
+
initAuth() {
|
|
129
|
+
let isInitialized = false;
|
|
130
|
+
try {
|
|
131
|
+
const auth = this.getCredentials();
|
|
132
|
+
if (auth) {
|
|
133
|
+
this.logEvent({ message: 'Intervals.icu init done', hasCredentials: true });
|
|
134
|
+
this.config = this.buildConfigFromCredentials(auth);
|
|
135
|
+
this.initApi(this.config);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.logEvent({ message: 'Intervals.icu init done', hasCredentials: false });
|
|
139
|
+
}
|
|
140
|
+
isInitialized = true;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
this.logEvent({ message: 'error', error: err.message, fn: 'init', stack: err.stack });
|
|
144
|
+
isInitialized = false;
|
|
145
|
+
delete this.config;
|
|
146
|
+
}
|
|
147
|
+
return isInitialized;
|
|
148
|
+
}
|
|
149
|
+
updateConfig(config) {
|
|
150
|
+
const { accessToken } = config;
|
|
151
|
+
this.config = Object.assign(Object.assign({}, this.config), { accessToken });
|
|
152
|
+
this.saveCredentials();
|
|
153
|
+
}
|
|
154
|
+
saveCredentials(config) {
|
|
155
|
+
if (config)
|
|
156
|
+
this.config = config;
|
|
157
|
+
try {
|
|
158
|
+
if (!this.isConnected()) {
|
|
159
|
+
this.logEvent({ message: 'Intervals.icu Delete Credentials' });
|
|
160
|
+
this.getUserSettings().set('user.auth.intervals', null);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.logEvent({ message: 'Intervals.icu Save Credentials' });
|
|
164
|
+
this.getUserSettings().set('user.auth.intervals', {
|
|
165
|
+
accesstoken: this.config.accessToken
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
this.logEvent({ message: 'error', fn: 'saveCredentials', error: err.message, stack: err.stack });
|
|
170
|
+
}
|
|
171
|
+
this.logEvent({ message: 'Intervals.icu Save Credentials done' });
|
|
172
|
+
}
|
|
173
|
+
getSecret(key) {
|
|
174
|
+
var _a;
|
|
175
|
+
return (_a = this.getSecretBindings()) === null || _a === void 0 ? void 0 : _a.getSecret(key);
|
|
176
|
+
}
|
|
177
|
+
buildConfigFromCredentials(credentials) {
|
|
178
|
+
return {
|
|
179
|
+
accessToken: credentials === null || credentials === void 0 ? void 0 : credentials.accesstoken
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
initApi(config) {
|
|
183
|
+
this.getApi().init(config);
|
|
184
|
+
}
|
|
185
|
+
getSecretBindings() {
|
|
186
|
+
var _a;
|
|
187
|
+
return (_a = (0, api_1.getBindings)()) === null || _a === void 0 ? void 0 : _a.secret;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
__setFunctionName(_classThis, "IntervalsAppConnection");
|
|
191
|
+
(() => {
|
|
192
|
+
var _a;
|
|
193
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create((_a = _classSuper[Symbol.metadata]) !== null && _a !== void 0 ? _a : null) : void 0;
|
|
194
|
+
_getSecretBindings_decorators = [decorators_1.Injectable];
|
|
195
|
+
__esDecorate(_classThis, null, _getSecretBindings_decorators, { kind: "method", name: "getSecretBindings", static: false, private: false, access: { has: obj => "getSecretBindings" in obj, get: obj => obj.getSecretBindings }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
196
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
197
|
+
IntervalsAppConnection = _classThis = _classDescriptor.value;
|
|
198
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
199
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
200
|
+
})();
|
|
201
|
+
return IntervalsAppConnection = _classThis;
|
|
202
|
+
})();
|
|
203
|
+
exports.IntervalsAppConnection = IntervalsAppConnection;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { StravaApi, StravaConfig } from "../base/api";
|
|
2
|
+
import { ConnectedAppService } from "../base/app";
|
|
3
|
+
import { StravaCredentials } from "./types";
|
|
4
|
+
export declare class StravaAppConnection extends ConnectedAppService<StravaCredentials> {
|
|
5
|
+
protected config: StravaConfig;
|
|
6
|
+
protected api: StravaApi;
|
|
7
|
+
protected tokenUpdateHandler: any;
|
|
8
|
+
constructor();
|
|
9
|
+
connect(credentials: StravaCredentials): Promise<boolean>;
|
|
10
|
+
isConnecting(): boolean;
|
|
11
|
+
disconnect(): void;
|
|
12
|
+
isConnected(): boolean;
|
|
13
|
+
getCredentials(): StravaCredentials;
|
|
14
|
+
getApi(): StravaApi;
|
|
15
|
+
protected initAuth(): boolean;
|
|
16
|
+
protected updateConfig(config: StravaConfig): void;
|
|
17
|
+
protected saveCredentials(config?: StravaConfig): void;
|
|
18
|
+
protected getSecret(key: string): string;
|
|
19
|
+
protected buildConfigFromCredentials(credentials: StravaCredentials): {
|
|
20
|
+
clientId: string;
|
|
21
|
+
clientSecret: string;
|
|
22
|
+
accessToken: any;
|
|
23
|
+
refreshToken: any;
|
|
24
|
+
expiration: Date;
|
|
25
|
+
};
|
|
26
|
+
protected initApi(config: StravaConfig): void;
|
|
27
|
+
protected getSecretBindings(): import("../../api/bindings/secret").ISecretBinding;
|
|
28
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
|
|
46
|
+
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
|
|
47
|
+
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.StravaAppConnection = void 0;
|
|
51
|
+
const api_1 = require("../../api");
|
|
52
|
+
const decorators_1 = require("../../base/decorators");
|
|
53
|
+
const valid_1 = require("../../utils/valid");
|
|
54
|
+
const api_2 = require("../base/api");
|
|
55
|
+
const app_1 = require("../base/app");
|
|
56
|
+
let StravaAppConnection = (() => {
|
|
57
|
+
let _classDecorators = [decorators_1.Singleton];
|
|
58
|
+
let _classDescriptor;
|
|
59
|
+
let _classExtraInitializers = [];
|
|
60
|
+
let _classThis;
|
|
61
|
+
let _classSuper = app_1.ConnectedAppService;
|
|
62
|
+
let _instanceExtraInitializers = [];
|
|
63
|
+
let _getSecretBindings_decorators;
|
|
64
|
+
var StravaAppConnection = _classThis = class extends _classSuper {
|
|
65
|
+
constructor() {
|
|
66
|
+
super('StravaAppConnection', 'strava');
|
|
67
|
+
this.config = __runInitializers(this, _instanceExtraInitializers);
|
|
68
|
+
this.tokenUpdateHandler = this.updateConfig.bind(this);
|
|
69
|
+
}
|
|
70
|
+
connect(credentials) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
this.ensureInitialized();
|
|
73
|
+
this.logEvent({ message: 'Connect with Strava' });
|
|
74
|
+
try {
|
|
75
|
+
const isConnected = this.isConnected();
|
|
76
|
+
const config = this.buildConfigFromCredentials(credentials);
|
|
77
|
+
if (isConnected) {
|
|
78
|
+
this.getApi().update(config);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.initApi(config);
|
|
82
|
+
this.saveCredentials(config);
|
|
83
|
+
}
|
|
84
|
+
this.logEvent({ message: 'Connect with Strava success' });
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
this.logError(err, 'connect');
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
isConnecting() {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
disconnect() {
|
|
97
|
+
try {
|
|
98
|
+
this.config = undefined;
|
|
99
|
+
this.saveCredentials();
|
|
100
|
+
this.getApi().init(undefined);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
this.logError(err, 'disconnect');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
isConnected() {
|
|
107
|
+
if (!this.isInitialized) {
|
|
108
|
+
this.init();
|
|
109
|
+
}
|
|
110
|
+
return ((0, valid_1.valid)(this.config));
|
|
111
|
+
}
|
|
112
|
+
getCredentials() {
|
|
113
|
+
const userSettings = this.getUserSettings();
|
|
114
|
+
try {
|
|
115
|
+
return userSettings.get('user.auth.strava', null);
|
|
116
|
+
}
|
|
117
|
+
catch (_a) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
getApi() {
|
|
122
|
+
if (!this.api)
|
|
123
|
+
this.api = new api_2.StravaApi();
|
|
124
|
+
return this.api;
|
|
125
|
+
}
|
|
126
|
+
initAuth() {
|
|
127
|
+
let isInitialized = false;
|
|
128
|
+
try {
|
|
129
|
+
const auth = this.getCredentials();
|
|
130
|
+
const clientId = this.getSecret('STRAVA_CLIENT_ID');
|
|
131
|
+
const clientSecret = this.getSecret('STRAVA_CLIENT_SECRET');
|
|
132
|
+
if (clientId && clientSecret && auth) {
|
|
133
|
+
this.logEvent({ message: 'Strava init done', hasCredentials: true });
|
|
134
|
+
this.config = this.buildConfigFromCredentials(auth);
|
|
135
|
+
this.initApi(this.config);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.logEvent({ message: 'Strava init done', hasCredentials: false });
|
|
139
|
+
}
|
|
140
|
+
isInitialized = true;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
this.logEvent({ message: 'error', error: err.message, fn: 'init', stack: err.stack });
|
|
144
|
+
isInitialized = false;
|
|
145
|
+
delete this.config;
|
|
146
|
+
}
|
|
147
|
+
return isInitialized;
|
|
148
|
+
}
|
|
149
|
+
updateConfig(config) {
|
|
150
|
+
const { accessToken, refreshToken, expiration } = config;
|
|
151
|
+
this.config = Object.assign(Object.assign({}, this.config), { accessToken, refreshToken, expiration });
|
|
152
|
+
this.saveCredentials();
|
|
153
|
+
}
|
|
154
|
+
saveCredentials(config) {
|
|
155
|
+
var _a;
|
|
156
|
+
if (config)
|
|
157
|
+
this.config = config;
|
|
158
|
+
try {
|
|
159
|
+
if (!this.isConnected()) {
|
|
160
|
+
this.logEvent({ message: 'Strava Delete Credentials' });
|
|
161
|
+
this.getUserSettings().set('user.auth.strava', null);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.logEvent({ message: 'Strava Save Credentials' });
|
|
165
|
+
this.getUserSettings().set('user.auth.strava', {
|
|
166
|
+
accesstoken: this.config.accessToken,
|
|
167
|
+
refreshtoken: this.config.refreshToken,
|
|
168
|
+
expiration: (_a = this.config.expiration) === null || _a === void 0 ? void 0 : _a.toISOString()
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
this.logEvent({ message: 'error', fn: 'saveCredentials', error: err.message, stack: err.stack });
|
|
173
|
+
}
|
|
174
|
+
this.logEvent({ message: 'Strava Save Credentials done' });
|
|
175
|
+
}
|
|
176
|
+
getSecret(key) {
|
|
177
|
+
var _a;
|
|
178
|
+
return (_a = this.getSecretBindings()) === null || _a === void 0 ? void 0 : _a.getSecret(key);
|
|
179
|
+
}
|
|
180
|
+
buildConfigFromCredentials(credentials) {
|
|
181
|
+
return {
|
|
182
|
+
clientId: this.getSecret('STRAVA_CLIENT_ID'),
|
|
183
|
+
clientSecret: this.getSecret('STRAVA_CLIENT_SECRET'),
|
|
184
|
+
accessToken: credentials === null || credentials === void 0 ? void 0 : credentials.accesstoken,
|
|
185
|
+
refreshToken: credentials === null || credentials === void 0 ? void 0 : credentials.refreshtoken,
|
|
186
|
+
expiration: (credentials === null || credentials === void 0 ? void 0 : credentials.expiration) ? new Date(credentials.expiration) : undefined
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
initApi(config) {
|
|
190
|
+
const observer = this.getApi().init(config);
|
|
191
|
+
observer.on('token.updated', this.tokenUpdateHandler);
|
|
192
|
+
}
|
|
193
|
+
getSecretBindings() {
|
|
194
|
+
var _a;
|
|
195
|
+
return (_a = (0, api_1.getBindings)()) === null || _a === void 0 ? void 0 : _a.secret;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
__setFunctionName(_classThis, "StravaAppConnection");
|
|
199
|
+
(() => {
|
|
200
|
+
var _a;
|
|
201
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create((_a = _classSuper[Symbol.metadata]) !== null && _a !== void 0 ? _a : null) : void 0;
|
|
202
|
+
_getSecretBindings_decorators = [decorators_1.Injectable];
|
|
203
|
+
__esDecorate(_classThis, null, _getSecretBindings_decorators, { kind: "method", name: "getSecretBindings", static: false, private: false, access: { has: obj => "getSecretBindings" in obj, get: obj => obj.getSecretBindings }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
204
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
205
|
+
StravaAppConnection = _classThis = _classDescriptor.value;
|
|
206
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
207
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
208
|
+
})();
|
|
209
|
+
return StravaAppConnection = _classThis;
|
|
210
|
+
})();
|
|
211
|
+
exports.StravaAppConnection = StravaAppConnection;
|
|
File without changes
|
|
File without changes
|
package/lib/apps/service.js
CHANGED
|
@@ -54,6 +54,7 @@ const service_1 = require("../base/service");
|
|
|
54
54
|
const types_1 = require("../base/types");
|
|
55
55
|
const settings_1 = require("../settings");
|
|
56
56
|
const base_1 = require("./base");
|
|
57
|
+
const IntervalsAppConnection_1 = require("./intervals/IntervalsAppConnection");
|
|
57
58
|
const komoot_1 = require("./komoot");
|
|
58
59
|
const VeloHeroAppConnection_1 = require("./velohero/VeloHeroAppConnection");
|
|
59
60
|
let AppsService = (() => {
|
|
@@ -69,7 +70,7 @@ let AppsService = (() => {
|
|
|
69
70
|
constructor() {
|
|
70
71
|
super('AppsService');
|
|
71
72
|
this.services = (__runInitializers(this, _instanceExtraInitializers), {
|
|
72
|
-
ActivityUpload: ['strava', 'velohero', 'intervals
|
|
73
|
+
ActivityUpload: ['strava', 'velohero', 'intervals'],
|
|
73
74
|
WorkoutUpload: [],
|
|
74
75
|
WorkoutDownload: [],
|
|
75
76
|
ActivityDownload: [],
|
|
@@ -79,6 +80,7 @@ let AppsService = (() => {
|
|
|
79
80
|
{ name: 'Strava', key: 'strava', iconUrl: 'https://static.cdnlogo.com/logos/s/42/strava-wordmark.svg', connection: new base_1.StravaAppConnection() },
|
|
80
81
|
{ name: 'VeloHero', key: 'velohero', iconUrl: 'images/velo-white.png', connection: new VeloHeroAppConnection_1.VeloHeroAppConnection() },
|
|
81
82
|
{ name: 'Komoot', key: 'komoot', iconUrl: 'https://www.komoot.com/assets/4d8ae313eec53e6e.svg', connection: new komoot_1.KomootAppConnection() },
|
|
83
|
+
{ name: 'Intervals.icu', key: 'intervals', iconUrl: 'images/intervals.png', connection: new IntervalsAppConnection_1.IntervalsAppConnection() },
|
|
82
84
|
];
|
|
83
85
|
}
|
|
84
86
|
openSettings() {
|