@dronedeploy/rocos-js-sdk 4.4.11 → 4.4.13
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/cjs/services/AuthService.d.ts +3 -0
- package/cjs/services/AuthService.js +40 -17
- package/cjs/services/ProfileService.d.ts +3 -2
- package/cjs/services/ProfileService.js +7 -3
- package/esm/services/AuthService.d.ts +3 -0
- package/esm/services/AuthService.js +40 -17
- package/esm/services/ProfileService.d.ts +3 -2
- package/esm/services/ProfileService.js +7 -3
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ export declare class AuthService extends BaseServiceAbstract implements IBaseSer
|
|
|
6
6
|
private token?;
|
|
7
7
|
private tokenRefreshTimeoutId?;
|
|
8
8
|
private tokenSubject$;
|
|
9
|
+
private pendingTokenRequest?;
|
|
9
10
|
constructor(config: IRocosSDKConfig);
|
|
10
11
|
/** Observable for token updates
|
|
11
12
|
*
|
|
@@ -54,6 +55,8 @@ export declare class AuthService extends BaseServiceAbstract implements IBaseSer
|
|
|
54
55
|
* This will return the current token if it is not expired, otherwise it will get a new token based on your config.
|
|
55
56
|
*/
|
|
56
57
|
getToken(): Promise<Token>;
|
|
58
|
+
private getOrRequestToken;
|
|
59
|
+
private fetchNewToken;
|
|
57
60
|
/**
|
|
58
61
|
* Refresh the authentication token
|
|
59
62
|
*
|
|
@@ -50,25 +50,27 @@ class AuthService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
50
50
|
if (expiresIn !== undefined) {
|
|
51
51
|
this.logger.warn('setToken(value, expiresIn) is deprecated. Use setToken(value) instead');
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
else {
|
|
57
|
-
this.token = value;
|
|
53
|
+
const token = typeof value === 'string' ? new models_1.Token(value) : value;
|
|
54
|
+
if (token.value !== this.token?.value) {
|
|
55
|
+
this.pendingTokenRequest = undefined;
|
|
58
56
|
}
|
|
57
|
+
this.token = token;
|
|
59
58
|
this.config.token = this.token.value;
|
|
60
59
|
// output a message for token change
|
|
61
60
|
if (this.isTokenValid(this.token)) {
|
|
62
61
|
this.tokenSubject$.next(this.token);
|
|
63
62
|
}
|
|
64
63
|
else {
|
|
65
|
-
void this.getToken()
|
|
64
|
+
void this.getToken().catch((error) => {
|
|
65
|
+
this.logger.error('Failed to initialize auth token', error);
|
|
66
|
+
});
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
70
|
* Clear token
|
|
70
71
|
*/
|
|
71
72
|
clearToken() {
|
|
73
|
+
this.pendingTokenRequest = undefined;
|
|
72
74
|
this.token = undefined;
|
|
73
75
|
this.config.token = undefined;
|
|
74
76
|
}
|
|
@@ -125,15 +127,38 @@ class AuthService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
125
127
|
* This will return the current token if it is not expired, otherwise it will get a new token based on your config.
|
|
126
128
|
*/
|
|
127
129
|
async getToken() {
|
|
128
|
-
if (this.token && this.isTokenValid(this.token)) {
|
|
129
|
-
if (this.token.isExpiredIn(15, 'minutes')) {
|
|
130
|
-
this.logger.info('Token expires within 15 minutes. Refreshing.');
|
|
131
|
-
const newToken = await this.refreshToken();
|
|
132
|
-
this.setToken(newToken);
|
|
133
|
-
return newToken;
|
|
134
|
-
}
|
|
130
|
+
if (this.token && this.isTokenValid(this.token) && !this.token.isExpiredIn(15, 'minutes')) {
|
|
135
131
|
return this.token;
|
|
136
132
|
}
|
|
133
|
+
return this.getOrRequestToken(() => this.fetchNewToken());
|
|
134
|
+
}
|
|
135
|
+
getOrRequestToken(fetchToken) {
|
|
136
|
+
if (this.pendingTokenRequest) {
|
|
137
|
+
return this.pendingTokenRequest;
|
|
138
|
+
}
|
|
139
|
+
const request = fetchToken()
|
|
140
|
+
.then((token) => {
|
|
141
|
+
if (this.pendingTokenRequest === request) {
|
|
142
|
+
this.setToken(token);
|
|
143
|
+
}
|
|
144
|
+
else if (this.token) {
|
|
145
|
+
return this.getToken();
|
|
146
|
+
}
|
|
147
|
+
return token;
|
|
148
|
+
})
|
|
149
|
+
.finally(() => {
|
|
150
|
+
if (this.pendingTokenRequest === request) {
|
|
151
|
+
this.pendingTokenRequest = undefined;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
this.pendingTokenRequest = request;
|
|
155
|
+
return request;
|
|
156
|
+
}
|
|
157
|
+
async fetchNewToken() {
|
|
158
|
+
if (this.token && this.isTokenValid(this.token)) {
|
|
159
|
+
this.logger.info('Token expires within 15 minutes. Refreshing.');
|
|
160
|
+
return this.refreshToken();
|
|
161
|
+
}
|
|
137
162
|
let token;
|
|
138
163
|
try {
|
|
139
164
|
if ('appId' in this.config && 'appKey' in this.config) {
|
|
@@ -159,7 +184,6 @@ class AuthService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
159
184
|
this.logger.error(message);
|
|
160
185
|
throw new models_1.RocosError(message, models_1.errorCodes.AUTH_ERROR);
|
|
161
186
|
}
|
|
162
|
-
this.setToken(token);
|
|
163
187
|
return token;
|
|
164
188
|
}
|
|
165
189
|
/**
|
|
@@ -192,9 +216,8 @@ class AuthService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
192
216
|
*/
|
|
193
217
|
async refreshTokenIfExpired(minutes) {
|
|
194
218
|
if (this.token?.isExpiredIn(minutes, 'minutes')) {
|
|
195
|
-
this.logger.info(
|
|
196
|
-
|
|
197
|
-
this.setToken(newToken);
|
|
219
|
+
this.logger.info(`Token expires in ${minutes} minutes. Refreshing.`);
|
|
220
|
+
await this.getOrRequestToken(() => this.refreshToken());
|
|
198
221
|
return true;
|
|
199
222
|
}
|
|
200
223
|
return false;
|
|
@@ -247,16 +247,17 @@ export declare class ProfileService extends BaseServiceAbstract implements IBase
|
|
|
247
247
|
* @param profileData - Robot definition data
|
|
248
248
|
* @param newName - Optional new name for the robot definition. If not provided, the name from the imported definition will be used.
|
|
249
249
|
* @param newDescription - Optional new description for the robot definition. If not provided, the description from the imported definition will be used.
|
|
250
|
+
* @param replaceExisting - Move robots from same-named definitions to the import and delete those definitions.
|
|
250
251
|
*
|
|
251
252
|
* @see export
|
|
252
253
|
*/
|
|
253
|
-
import(projectId: string, profileData: Blob | File, newName?: string, newDescription?: string): Promise<{
|
|
254
|
+
import(projectId: string, profileData: Blob | File, newName?: string, newDescription?: string, replaceExisting?: boolean): Promise<{
|
|
254
255
|
profileId: string;
|
|
255
256
|
}>;
|
|
256
257
|
getLibraryProfiles(): Promise<(RobotProfile & {
|
|
257
258
|
last_modified: Date;
|
|
258
259
|
})[]>;
|
|
259
|
-
importFromLibrary(projectId: string, profileId: string, name?: string, description?: string): Promise<{
|
|
260
|
+
importFromLibrary(projectId: string, profileId: string, name?: string, description?: string, replaceExisting?: boolean): Promise<{
|
|
260
261
|
profileId: string;
|
|
261
262
|
}>;
|
|
262
263
|
/**
|
|
@@ -343,10 +343,11 @@ class ProfileService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
343
343
|
* @param profileData - Robot definition data
|
|
344
344
|
* @param newName - Optional new name for the robot definition. If not provided, the name from the imported definition will be used.
|
|
345
345
|
* @param newDescription - Optional new description for the robot definition. If not provided, the description from the imported definition will be used.
|
|
346
|
+
* @param replaceExisting - Move robots from same-named definitions to the import and delete those definitions.
|
|
346
347
|
*
|
|
347
348
|
* @see export
|
|
348
349
|
*/
|
|
349
|
-
async import(projectId, profileData, newName, newDescription) {
|
|
350
|
+
async import(projectId, profileData, newName, newDescription, replaceExisting) {
|
|
350
351
|
const formData = new FormData();
|
|
351
352
|
if (newName) {
|
|
352
353
|
formData.append('name', newName);
|
|
@@ -354,6 +355,9 @@ class ProfileService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
354
355
|
if (newDescription) {
|
|
355
356
|
formData.append('description', newDescription);
|
|
356
357
|
}
|
|
358
|
+
if (replaceExisting) {
|
|
359
|
+
formData.append('replaceExisting', 'true');
|
|
360
|
+
}
|
|
357
361
|
formData.append('file', profileData);
|
|
358
362
|
return this.callPost((0, formatServiceUrl_1.formatServiceUrl)(api_1.API_PROJECT_DEFINITION_IMPORT, { url: this.config.url, projectId }, this.config.insecure), formData, `Failed to import robot definition for ${projectId}.`);
|
|
359
363
|
}
|
|
@@ -364,8 +368,8 @@ class ProfileService extends BaseServiceAbstract_1.BaseServiceAbstract {
|
|
|
364
368
|
last_modified: new Date(profile.last_modified),
|
|
365
369
|
}));
|
|
366
370
|
}
|
|
367
|
-
async importFromLibrary(projectId, profileId, name, description) {
|
|
368
|
-
return this.callPost((0, formatServiceUrl_1.formatServiceUrl)(api_1.API_PROJECT_DEFINITION_IMPORT_LIBRARY, { url: this.config.url, projectId, profileId }, this.config.insecure), { name, description }, `Failed to import library profile ${profileId} into project ${projectId}.`);
|
|
371
|
+
async importFromLibrary(projectId, profileId, name, description, replaceExisting) {
|
|
372
|
+
return this.callPost((0, formatServiceUrl_1.formatServiceUrl)(api_1.API_PROJECT_DEFINITION_IMPORT_LIBRARY, { url: this.config.url, projectId, profileId }, this.config.insecure), { name, description, ...(replaceExisting ? { replaceExisting } : {}) }, `Failed to import library profile ${profileId} into project ${projectId}.`);
|
|
369
373
|
}
|
|
370
374
|
/**
|
|
371
375
|
* Update gamepads for a robot definition
|
|
@@ -6,6 +6,7 @@ export declare class AuthService extends BaseServiceAbstract implements IBaseSer
|
|
|
6
6
|
private token?;
|
|
7
7
|
private tokenRefreshTimeoutId?;
|
|
8
8
|
private tokenSubject$;
|
|
9
|
+
private pendingTokenRequest?;
|
|
9
10
|
constructor(config: IRocosSDKConfig);
|
|
10
11
|
/** Observable for token updates
|
|
11
12
|
*
|
|
@@ -54,6 +55,8 @@ export declare class AuthService extends BaseServiceAbstract implements IBaseSer
|
|
|
54
55
|
* This will return the current token if it is not expired, otherwise it will get a new token based on your config.
|
|
55
56
|
*/
|
|
56
57
|
getToken(): Promise<Token>;
|
|
58
|
+
private getOrRequestToken;
|
|
59
|
+
private fetchNewToken;
|
|
57
60
|
/**
|
|
58
61
|
* Refresh the authentication token
|
|
59
62
|
*
|
|
@@ -47,25 +47,27 @@ export class AuthService extends BaseServiceAbstract {
|
|
|
47
47
|
if (expiresIn !== undefined) {
|
|
48
48
|
this.logger.warn('setToken(value, expiresIn) is deprecated. Use setToken(value) instead');
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
else {
|
|
54
|
-
this.token = value;
|
|
50
|
+
const token = typeof value === 'string' ? new Token(value) : value;
|
|
51
|
+
if (token.value !== this.token?.value) {
|
|
52
|
+
this.pendingTokenRequest = undefined;
|
|
55
53
|
}
|
|
54
|
+
this.token = token;
|
|
56
55
|
this.config.token = this.token.value;
|
|
57
56
|
// output a message for token change
|
|
58
57
|
if (this.isTokenValid(this.token)) {
|
|
59
58
|
this.tokenSubject$.next(this.token);
|
|
60
59
|
}
|
|
61
60
|
else {
|
|
62
|
-
void this.getToken()
|
|
61
|
+
void this.getToken().catch((error) => {
|
|
62
|
+
this.logger.error('Failed to initialize auth token', error);
|
|
63
|
+
});
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
/**
|
|
66
67
|
* Clear token
|
|
67
68
|
*/
|
|
68
69
|
clearToken() {
|
|
70
|
+
this.pendingTokenRequest = undefined;
|
|
69
71
|
this.token = undefined;
|
|
70
72
|
this.config.token = undefined;
|
|
71
73
|
}
|
|
@@ -122,15 +124,38 @@ export class AuthService extends BaseServiceAbstract {
|
|
|
122
124
|
* This will return the current token if it is not expired, otherwise it will get a new token based on your config.
|
|
123
125
|
*/
|
|
124
126
|
async getToken() {
|
|
125
|
-
if (this.token && this.isTokenValid(this.token)) {
|
|
126
|
-
if (this.token.isExpiredIn(15, 'minutes')) {
|
|
127
|
-
this.logger.info('Token expires within 15 minutes. Refreshing.');
|
|
128
|
-
const newToken = await this.refreshToken();
|
|
129
|
-
this.setToken(newToken);
|
|
130
|
-
return newToken;
|
|
131
|
-
}
|
|
127
|
+
if (this.token && this.isTokenValid(this.token) && !this.token.isExpiredIn(15, 'minutes')) {
|
|
132
128
|
return this.token;
|
|
133
129
|
}
|
|
130
|
+
return this.getOrRequestToken(() => this.fetchNewToken());
|
|
131
|
+
}
|
|
132
|
+
getOrRequestToken(fetchToken) {
|
|
133
|
+
if (this.pendingTokenRequest) {
|
|
134
|
+
return this.pendingTokenRequest;
|
|
135
|
+
}
|
|
136
|
+
const request = fetchToken()
|
|
137
|
+
.then((token) => {
|
|
138
|
+
if (this.pendingTokenRequest === request) {
|
|
139
|
+
this.setToken(token);
|
|
140
|
+
}
|
|
141
|
+
else if (this.token) {
|
|
142
|
+
return this.getToken();
|
|
143
|
+
}
|
|
144
|
+
return token;
|
|
145
|
+
})
|
|
146
|
+
.finally(() => {
|
|
147
|
+
if (this.pendingTokenRequest === request) {
|
|
148
|
+
this.pendingTokenRequest = undefined;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
this.pendingTokenRequest = request;
|
|
152
|
+
return request;
|
|
153
|
+
}
|
|
154
|
+
async fetchNewToken() {
|
|
155
|
+
if (this.token && this.isTokenValid(this.token)) {
|
|
156
|
+
this.logger.info('Token expires within 15 minutes. Refreshing.');
|
|
157
|
+
return this.refreshToken();
|
|
158
|
+
}
|
|
134
159
|
let token;
|
|
135
160
|
try {
|
|
136
161
|
if ('appId' in this.config && 'appKey' in this.config) {
|
|
@@ -156,7 +181,6 @@ export class AuthService extends BaseServiceAbstract {
|
|
|
156
181
|
this.logger.error(message);
|
|
157
182
|
throw new RocosError(message, errorCodes.AUTH_ERROR);
|
|
158
183
|
}
|
|
159
|
-
this.setToken(token);
|
|
160
184
|
return token;
|
|
161
185
|
}
|
|
162
186
|
/**
|
|
@@ -189,9 +213,8 @@ export class AuthService extends BaseServiceAbstract {
|
|
|
189
213
|
*/
|
|
190
214
|
async refreshTokenIfExpired(minutes) {
|
|
191
215
|
if (this.token?.isExpiredIn(minutes, 'minutes')) {
|
|
192
|
-
this.logger.info(
|
|
193
|
-
|
|
194
|
-
this.setToken(newToken);
|
|
216
|
+
this.logger.info(`Token expires in ${minutes} minutes. Refreshing.`);
|
|
217
|
+
await this.getOrRequestToken(() => this.refreshToken());
|
|
195
218
|
return true;
|
|
196
219
|
}
|
|
197
220
|
return false;
|
|
@@ -247,16 +247,17 @@ export declare class ProfileService extends BaseServiceAbstract implements IBase
|
|
|
247
247
|
* @param profileData - Robot definition data
|
|
248
248
|
* @param newName - Optional new name for the robot definition. If not provided, the name from the imported definition will be used.
|
|
249
249
|
* @param newDescription - Optional new description for the robot definition. If not provided, the description from the imported definition will be used.
|
|
250
|
+
* @param replaceExisting - Move robots from same-named definitions to the import and delete those definitions.
|
|
250
251
|
*
|
|
251
252
|
* @see export
|
|
252
253
|
*/
|
|
253
|
-
import(projectId: string, profileData: Blob | File, newName?: string, newDescription?: string): Promise<{
|
|
254
|
+
import(projectId: string, profileData: Blob | File, newName?: string, newDescription?: string, replaceExisting?: boolean): Promise<{
|
|
254
255
|
profileId: string;
|
|
255
256
|
}>;
|
|
256
257
|
getLibraryProfiles(): Promise<(RobotProfile & {
|
|
257
258
|
last_modified: Date;
|
|
258
259
|
})[]>;
|
|
259
|
-
importFromLibrary(projectId: string, profileId: string, name?: string, description?: string): Promise<{
|
|
260
|
+
importFromLibrary(projectId: string, profileId: string, name?: string, description?: string, replaceExisting?: boolean): Promise<{
|
|
260
261
|
profileId: string;
|
|
261
262
|
}>;
|
|
262
263
|
/**
|
|
@@ -340,10 +340,11 @@ export class ProfileService extends BaseServiceAbstract {
|
|
|
340
340
|
* @param profileData - Robot definition data
|
|
341
341
|
* @param newName - Optional new name for the robot definition. If not provided, the name from the imported definition will be used.
|
|
342
342
|
* @param newDescription - Optional new description for the robot definition. If not provided, the description from the imported definition will be used.
|
|
343
|
+
* @param replaceExisting - Move robots from same-named definitions to the import and delete those definitions.
|
|
343
344
|
*
|
|
344
345
|
* @see export
|
|
345
346
|
*/
|
|
346
|
-
async import(projectId, profileData, newName, newDescription) {
|
|
347
|
+
async import(projectId, profileData, newName, newDescription, replaceExisting) {
|
|
347
348
|
const formData = new FormData();
|
|
348
349
|
if (newName) {
|
|
349
350
|
formData.append('name', newName);
|
|
@@ -351,6 +352,9 @@ export class ProfileService extends BaseServiceAbstract {
|
|
|
351
352
|
if (newDescription) {
|
|
352
353
|
formData.append('description', newDescription);
|
|
353
354
|
}
|
|
355
|
+
if (replaceExisting) {
|
|
356
|
+
formData.append('replaceExisting', 'true');
|
|
357
|
+
}
|
|
354
358
|
formData.append('file', profileData);
|
|
355
359
|
return this.callPost(formatServiceUrl(API_PROJECT_DEFINITION_IMPORT, { url: this.config.url, projectId }, this.config.insecure), formData, `Failed to import robot definition for ${projectId}.`);
|
|
356
360
|
}
|
|
@@ -361,8 +365,8 @@ export class ProfileService extends BaseServiceAbstract {
|
|
|
361
365
|
last_modified: new Date(profile.last_modified),
|
|
362
366
|
}));
|
|
363
367
|
}
|
|
364
|
-
async importFromLibrary(projectId, profileId, name, description) {
|
|
365
|
-
return this.callPost(formatServiceUrl(API_PROJECT_DEFINITION_IMPORT_LIBRARY, { url: this.config.url, projectId, profileId }, this.config.insecure), { name, description }, `Failed to import library profile ${profileId} into project ${projectId}.`);
|
|
368
|
+
async importFromLibrary(projectId, profileId, name, description, replaceExisting) {
|
|
369
|
+
return this.callPost(formatServiceUrl(API_PROJECT_DEFINITION_IMPORT_LIBRARY, { url: this.config.url, projectId, profileId }, this.config.insecure), { name, description, ...(replaceExisting ? { replaceExisting } : {}) }, `Failed to import library profile ${profileId} into project ${projectId}.`);
|
|
366
370
|
}
|
|
367
371
|
/**
|
|
368
372
|
* Update gamepads for a robot definition
|