pryv 2.4.4 → 2.4.6
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/package.json +2 -2
- package/src/Connection.js +128 -33
- package/src/index.d.ts +67 -13
- package/test/Connection.test.js +12 -0
package/package.json
CHANGED
package/src/Connection.js
CHANGED
|
@@ -81,7 +81,69 @@ class Connection {
|
|
|
81
81
|
function httpHandler (batchCall) {
|
|
82
82
|
return this.post('', batchCall);
|
|
83
83
|
}
|
|
84
|
-
return await this._chunkedBatchCall(
|
|
84
|
+
return await this._chunkedBatchCall(
|
|
85
|
+
arrayOfAPICalls,
|
|
86
|
+
progress,
|
|
87
|
+
httpHandler.bind(this)
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Make one api Api call
|
|
93
|
+
* @param {string} method - methodId
|
|
94
|
+
* @param {Object|Array} [params] - the params associated with this methodId
|
|
95
|
+
* @param {string} [resultKey] - if given, returns the value or throws an error if not present
|
|
96
|
+
* @throws {Error} if .error is present the response
|
|
97
|
+
*/
|
|
98
|
+
async apiOne (method, params = {}, expectedKey) {
|
|
99
|
+
const result = await this.api([{ method, params }]);
|
|
100
|
+
if (
|
|
101
|
+
result[0] == null ||
|
|
102
|
+
result[0].error ||
|
|
103
|
+
(expectedKey != null && result[0][expectedKey] == null)
|
|
104
|
+
) {
|
|
105
|
+
const innerObject = result[0]?.error || result;
|
|
106
|
+
const error = new Error(
|
|
107
|
+
`Error for api method: "${method}" with params: ${JSON.stringify(
|
|
108
|
+
params
|
|
109
|
+
)} >> Result: ${JSON.stringify(innerObject)}"`
|
|
110
|
+
);
|
|
111
|
+
error.innerObject = innerObject;
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
if (expectedKey != null) return result[0][expectedKey];
|
|
115
|
+
return result[0];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Revoke : Delete the accessId
|
|
120
|
+
* - Do not thow error if access is already revoked, just return null;
|
|
121
|
+
* @param {boolean} [throwOnFail = true] - if set to false do not throw Error on failure
|
|
122
|
+
* @param {Connection} [usingConnection] - specify which connection issues the revoke, might be necessary when selfRovke
|
|
123
|
+
*/
|
|
124
|
+
async revoke (throwOnFail = true, usingConnection) {
|
|
125
|
+
usingConnection = usingConnection || this;
|
|
126
|
+
let accessInfo = null;
|
|
127
|
+
// get accessId
|
|
128
|
+
try {
|
|
129
|
+
accessInfo = await this.accessInfo();
|
|
130
|
+
} catch (e) {
|
|
131
|
+
if (e.response?.body?.error?.id === 'invalid-access-token') {
|
|
132
|
+
return null; // Already revoked OK..
|
|
133
|
+
}
|
|
134
|
+
if (throwOnFail) throw e;
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
// delete access
|
|
138
|
+
try {
|
|
139
|
+
const result = usingConnection.apiOne('accesses.delete', {
|
|
140
|
+
id: accessInfo.id
|
|
141
|
+
});
|
|
142
|
+
return result;
|
|
143
|
+
} catch (e) {
|
|
144
|
+
if (throwOnFail) throw e;
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
85
147
|
}
|
|
86
148
|
|
|
87
149
|
/**
|
|
@@ -94,32 +156,52 @@ class Connection {
|
|
|
94
156
|
|
|
95
157
|
const res = [];
|
|
96
158
|
let percent = 0;
|
|
97
|
-
for (
|
|
159
|
+
for (
|
|
160
|
+
let cursor = 0;
|
|
161
|
+
arrayOfAPICalls.length >= cursor;
|
|
162
|
+
cursor += this.options.chunkSize
|
|
163
|
+
) {
|
|
98
164
|
const thisBatch = [];
|
|
99
|
-
const cursorMax = Math.min(
|
|
165
|
+
const cursorMax = Math.min(
|
|
166
|
+
cursor + this.options.chunkSize,
|
|
167
|
+
arrayOfAPICalls.length
|
|
168
|
+
);
|
|
100
169
|
// copy only method and params into a back call to be exuted
|
|
101
170
|
for (let i = cursor; i < cursorMax; i++) {
|
|
102
|
-
thisBatch.push({
|
|
171
|
+
thisBatch.push({
|
|
172
|
+
method: arrayOfAPICalls[i].method,
|
|
173
|
+
params: arrayOfAPICalls[i].params
|
|
174
|
+
});
|
|
103
175
|
}
|
|
104
176
|
const resRequest = await callHandler(thisBatch);
|
|
105
177
|
|
|
106
178
|
// result checks
|
|
107
179
|
if (!resRequest || !Array.isArray(resRequest.results)) {
|
|
108
|
-
throw new Error(
|
|
180
|
+
throw new Error(
|
|
181
|
+
'API call result is not an Array: ' + JSON.stringify(resRequest)
|
|
182
|
+
);
|
|
109
183
|
}
|
|
110
184
|
if (resRequest.results.length !== thisBatch.length) {
|
|
111
|
-
throw new Error(
|
|
185
|
+
throw new Error(
|
|
186
|
+
'API call result Array does not match request: ' +
|
|
187
|
+
JSON.stringify(resRequest)
|
|
188
|
+
);
|
|
112
189
|
}
|
|
113
190
|
|
|
114
191
|
// eventually call handleResult
|
|
115
192
|
for (let i = 0; i < resRequest.results.length; i++) {
|
|
116
193
|
if (arrayOfAPICalls[i + cursor].handleResult) {
|
|
117
|
-
await arrayOfAPICalls[i + cursor].handleResult.call(
|
|
194
|
+
await arrayOfAPICalls[i + cursor].handleResult.call(
|
|
195
|
+
null,
|
|
196
|
+
resRequest.results[i]
|
|
197
|
+
);
|
|
118
198
|
}
|
|
119
199
|
}
|
|
120
200
|
Array.prototype.push.apply(res, resRequest.results);
|
|
121
|
-
percent = Math.round(100 * res.length / arrayOfAPICalls.length);
|
|
122
|
-
if (progress) {
|
|
201
|
+
percent = Math.round((100 * res.length) / arrayOfAPICalls.length);
|
|
202
|
+
if (progress) {
|
|
203
|
+
progress(percent, res);
|
|
204
|
+
}
|
|
123
205
|
}
|
|
124
206
|
return res;
|
|
125
207
|
}
|
|
@@ -146,13 +228,12 @@ class Connection {
|
|
|
146
228
|
* @returns {request.superagent} Promise from superagent's post request
|
|
147
229
|
*/
|
|
148
230
|
async postRaw (path, data, queryParams) {
|
|
149
|
-
return this._post(path)
|
|
150
|
-
.query(queryParams)
|
|
151
|
-
.send(data);
|
|
231
|
+
return this._post(path).query(queryParams).send(data);
|
|
152
232
|
}
|
|
153
233
|
|
|
154
234
|
_post (path) {
|
|
155
|
-
return utils.superagent
|
|
235
|
+
return utils.superagent
|
|
236
|
+
.post(this.endpoint + path)
|
|
156
237
|
.set('Authorization', this.token)
|
|
157
238
|
.set('accept', 'json');
|
|
158
239
|
}
|
|
@@ -178,7 +259,8 @@ class Connection {
|
|
|
178
259
|
*/
|
|
179
260
|
getRaw (path, queryParams) {
|
|
180
261
|
path = path || '';
|
|
181
|
-
return utils.superagent
|
|
262
|
+
return utils.superagent
|
|
263
|
+
.get(this.endpoint + path)
|
|
182
264
|
.set('Authorization', this.token)
|
|
183
265
|
.set('accept', 'json')
|
|
184
266
|
.query(queryParams);
|
|
@@ -189,12 +271,11 @@ class Connection {
|
|
|
189
271
|
* https://api.pryv.com/reference/#add-hf-series-data-points
|
|
190
272
|
*/
|
|
191
273
|
async addPointsToHFEvent (eventId, fields, points) {
|
|
192
|
-
const res = await this.post('events/' + eventId + '/series',
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
});
|
|
274
|
+
const res = await this.post('events/' + eventId + '/series', {
|
|
275
|
+
format: 'flatJSON',
|
|
276
|
+
fields: fields,
|
|
277
|
+
points: points
|
|
278
|
+
});
|
|
198
279
|
if (!res.status === 'ok') {
|
|
199
280
|
throw new Error('Failed loading serie: ' + JSON.stringify(res.status));
|
|
200
281
|
}
|
|
@@ -212,14 +293,22 @@ class Connection {
|
|
|
212
293
|
async getEventsStreamed (queryParams, forEachEvent) {
|
|
213
294
|
const myParser = jsonParser(forEachEvent, queryParams.includeDeletions);
|
|
214
295
|
let res = null;
|
|
215
|
-
if (typeof window === 'undefined') {
|
|
296
|
+
if (typeof window === 'undefined') {
|
|
297
|
+
// node
|
|
216
298
|
res = await this.getRaw('events', queryParams)
|
|
217
299
|
.buffer(false)
|
|
218
300
|
.parse(myParser);
|
|
219
|
-
} else if (
|
|
301
|
+
} else if (
|
|
302
|
+
typeof fetch !== 'undefined' &&
|
|
303
|
+
!(typeof navigator !== 'undefined' && navigator.product === 'ReactNative')
|
|
304
|
+
) {
|
|
305
|
+
// browser supports fetch and it is not react native
|
|
220
306
|
res = await browserGetEventStreamed(this, queryParams, myParser);
|
|
221
|
-
} else {
|
|
222
|
-
|
|
307
|
+
} else {
|
|
308
|
+
// browser no fetch supports
|
|
309
|
+
console.log(
|
|
310
|
+
'WARNING: Browser does not support fetch() required by pryv.Connection.getEventsStreamed()'
|
|
311
|
+
);
|
|
223
312
|
res = await this.getRaw('events', queryParams);
|
|
224
313
|
res.body.eventsCount = 0;
|
|
225
314
|
if (res.body.events) {
|
|
@@ -227,7 +316,8 @@ class Connection {
|
|
|
227
316
|
res.body.eventsCount += res.body.events.length;
|
|
228
317
|
delete res.body.events;
|
|
229
318
|
}
|
|
230
|
-
if (res.body.eventDeletions) {
|
|
319
|
+
if (res.body.eventDeletions) {
|
|
320
|
+
// deletions are in a seprated Array
|
|
231
321
|
res.body.eventDeletions.forEach(forEachEvent);
|
|
232
322
|
res.body.eventsCount += res.body.eventDeletions.length;
|
|
233
323
|
delete res.body.eventDeletions;
|
|
@@ -262,7 +352,8 @@ class Connection {
|
|
|
262
352
|
* @param {string} fileName
|
|
263
353
|
*/
|
|
264
354
|
async createEventWithFileFromBuffer (event, bufferData, filename) {
|
|
265
|
-
if (typeof window === 'undefined') {
|
|
355
|
+
if (typeof window === 'undefined') {
|
|
356
|
+
// node
|
|
266
357
|
const res = await this._post('events')
|
|
267
358
|
.field('event', JSON.stringify(event))
|
|
268
359
|
.attach('file', bufferData, filename);
|
|
@@ -280,11 +371,11 @@ class Connection {
|
|
|
280
371
|
}
|
|
281
372
|
|
|
282
373
|
/**
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
374
|
+
* Create an event with attached formData
|
|
375
|
+
* !! BROWSER ONLY
|
|
376
|
+
* @param {Event} event
|
|
377
|
+
* @param {FormData} formData https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData
|
|
378
|
+
*/
|
|
288
379
|
async createEventWithFormData (event, formData) {
|
|
289
380
|
formData.append('event', JSON.stringify(event));
|
|
290
381
|
const res = await this._post('events').send(formData);
|
|
@@ -313,10 +404,14 @@ class Connection {
|
|
|
313
404
|
// private method that handle meta data parsing
|
|
314
405
|
_handleMeta (res, requestLocalTimestamp) {
|
|
315
406
|
if (!res.meta) throw new Error('Cannot find .meta in response.');
|
|
316
|
-
if (!res.meta.serverTime) throw new Error('Cannot find .meta.serverTime in response.');
|
|
407
|
+
if (!res.meta.serverTime) { throw new Error('Cannot find .meta.serverTime in response.'); }
|
|
317
408
|
|
|
318
409
|
// update deltaTime and weight it
|
|
319
|
-
this._deltaTime.value =
|
|
410
|
+
this._deltaTime.value =
|
|
411
|
+
(this._deltaTime.value * this._deltaTime.weight +
|
|
412
|
+
res.meta.serverTime -
|
|
413
|
+
requestLocalTimestamp) /
|
|
414
|
+
++this._deltaTime.weight;
|
|
320
415
|
}
|
|
321
416
|
}
|
|
322
417
|
|
package/src/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ declare module 'pryv' {
|
|
|
17
17
|
name: string;
|
|
18
18
|
parentId?: Identifier;
|
|
19
19
|
clientData?: KeyValue;
|
|
20
|
-
children:
|
|
20
|
+
children: Stream[];
|
|
21
21
|
trashed?: boolean;
|
|
22
22
|
created: Timestamp;
|
|
23
23
|
createdBy: Identifier;
|
|
@@ -575,8 +575,17 @@ declare module 'pryv' {
|
|
|
575
575
|
username(): Promise<string>;
|
|
576
576
|
api<Calls extends APICall[] = APICall[]>(
|
|
577
577
|
apiCalls: Calls,
|
|
578
|
-
|
|
578
|
+
progress?: APICallProgressHandler,
|
|
579
579
|
): Promise<Array<TypedAPICallResult>>;
|
|
580
|
+
apiOne<T extends keyof APICallMethods>(
|
|
581
|
+
method: T,
|
|
582
|
+
params: APICallMethods[T]['params'],
|
|
583
|
+
): Promise<APICallMethods[T]['res']>;
|
|
584
|
+
apiOne<T extends keyof APICallMethods, U extends keyof APICallMethods[T]['res']>(
|
|
585
|
+
method: T,
|
|
586
|
+
params: APICallMethods[T]['params'],
|
|
587
|
+
expectedKey: U
|
|
588
|
+
): Promise<APICallMethods[T]['res'][U]>;
|
|
580
589
|
getEventsStreamed(
|
|
581
590
|
queryParams: Partial<EventQueryParamsStreamQuery>,
|
|
582
591
|
forEachEvent: StreamedEventsHandler,
|
|
@@ -598,8 +607,11 @@ declare module 'pryv' {
|
|
|
598
607
|
id: Identifier,
|
|
599
608
|
fields: string[],
|
|
600
609
|
values: Array<string | number>,
|
|
601
|
-
): Promise<
|
|
610
|
+
): Promise<any>;
|
|
602
611
|
accessInfo(): Promise<AccessInfo>;
|
|
612
|
+
revoke(throwOnFail?: boolean, usingConnection?: Connection)
|
|
613
|
+
readonly deltaTime: number;
|
|
614
|
+
readonly apiEndpoint: string;
|
|
603
615
|
|
|
604
616
|
post(
|
|
605
617
|
path: string,
|
|
@@ -650,14 +662,27 @@ declare module 'pryv' {
|
|
|
650
662
|
[key: string]: any;
|
|
651
663
|
};
|
|
652
664
|
|
|
665
|
+
export class ServiceAssets {
|
|
666
|
+
static setup(pryvServiceAssetsSourceUrl: string): Promise<ServiceAssets>;
|
|
667
|
+
get(keyPath?: string): any;
|
|
668
|
+
getUrl(keyPath?: string): string;
|
|
669
|
+
relativeURL(url: string): string;
|
|
670
|
+
setAllDefaults(): Promise<void>;
|
|
671
|
+
setFavicon(): void;
|
|
672
|
+
loadCSS(): Promise<void>;
|
|
673
|
+
loginButtonLoadCSS(): Promise<void>;
|
|
674
|
+
loginButtonGetHTML(): Promise<string>;
|
|
675
|
+
loginButtonGetMessages(): Promise<KeyValue>;
|
|
676
|
+
}
|
|
677
|
+
|
|
653
678
|
export class Service {
|
|
654
679
|
constructor (
|
|
655
680
|
serviceInfoUrl: string,
|
|
656
681
|
serviceCustomizations?: serviceCustomizations,
|
|
657
682
|
);
|
|
658
683
|
info(forceFetch?: boolean): Promise<ServiceInfo>;
|
|
659
|
-
setServiceInfo(serviceInfo: Partial<ServiceInfo>):
|
|
660
|
-
assets(forceFetch?: boolean): Promise<
|
|
684
|
+
setServiceInfo(serviceInfo: Partial<ServiceInfo>): void;
|
|
685
|
+
assets(forceFetch?: boolean): Promise<ServiceAssets | null>;
|
|
661
686
|
infoSync(): ServiceInfo | null;
|
|
662
687
|
apiEndpointFor(username: string, token: string): Promise<string>;
|
|
663
688
|
login(
|
|
@@ -666,6 +691,9 @@ declare module 'pryv' {
|
|
|
666
691
|
appId: string,
|
|
667
692
|
originHeader?: string,
|
|
668
693
|
): Promise<Connection>;
|
|
694
|
+
|
|
695
|
+
supportsHF(): Promise<boolean>;
|
|
696
|
+
isDnsLess(): Promise<boolean>;
|
|
669
697
|
}
|
|
670
698
|
|
|
671
699
|
export type AuthRequestedPermission = {
|
|
@@ -755,12 +783,13 @@ declare module 'pryv' {
|
|
|
755
783
|
};
|
|
756
784
|
|
|
757
785
|
export type CustomLoginButton = {
|
|
758
|
-
init?: () => Promise<
|
|
759
|
-
getAuthorizationData():
|
|
786
|
+
init?: () => Promise<Service>;
|
|
787
|
+
getAuthorizationData(): any;
|
|
760
788
|
onStateChange(state: AuthStatePayload): Promise<void>;
|
|
761
789
|
onClick(): void;
|
|
762
|
-
saveAuthorizationData?: (authData:
|
|
790
|
+
saveAuthorizationData?: (authData: any) => void;
|
|
763
791
|
deleteAuthorizationData?: () => Promise<void>;
|
|
792
|
+
finishAuthProcessAfterRedirection?: (authController: AuthController) => Promise<void>;
|
|
764
793
|
}
|
|
765
794
|
|
|
766
795
|
export class AuthController {
|
|
@@ -769,16 +798,15 @@ declare module 'pryv' {
|
|
|
769
798
|
service: Service,
|
|
770
799
|
loginButton: CustomLoginButton,
|
|
771
800
|
);
|
|
772
|
-
init(): Promise<
|
|
801
|
+
init(): Promise<Service>;
|
|
773
802
|
stopAuthRequest(msg: string): void;
|
|
774
803
|
handleClick(): Promise<void>;
|
|
775
804
|
getReturnURL(
|
|
776
805
|
returnURL: string,
|
|
777
|
-
windowLocationForTest
|
|
778
|
-
navigatorForTests
|
|
806
|
+
windowLocationForTest?: string,
|
|
807
|
+
navigatorForTests?: string,
|
|
779
808
|
): string | boolean;
|
|
780
809
|
startAuthRequest(): Promise<any>;
|
|
781
|
-
doPolling(): Promise<void>;
|
|
782
810
|
set state(newState: AuthStatePayload);
|
|
783
811
|
get state(): AuthStatePayload;
|
|
784
812
|
}
|
|
@@ -805,7 +833,7 @@ declare module 'pryv' {
|
|
|
805
833
|
|
|
806
834
|
export type TokenAndAPIEndpoint = {
|
|
807
835
|
endpoint: string;
|
|
808
|
-
token: string;
|
|
836
|
+
token: string | null;
|
|
809
837
|
};
|
|
810
838
|
|
|
811
839
|
export const utils: {
|
|
@@ -820,6 +848,32 @@ declare module 'pryv' {
|
|
|
820
848
|
type version = string;
|
|
821
849
|
|
|
822
850
|
let pryv: {
|
|
851
|
+
Service: typeof Service;
|
|
852
|
+
Connection: typeof Connection;
|
|
853
|
+
Auth: {
|
|
854
|
+
setupAuth: SetupAuth;
|
|
855
|
+
AuthStates: AuthStates;
|
|
856
|
+
AuthController: typeof AuthController;
|
|
857
|
+
};
|
|
858
|
+
Browser: {
|
|
859
|
+
LoginButton: CustomLoginButton;
|
|
860
|
+
CookieUtils: {
|
|
861
|
+
set(cookieKey: string, value: any, expireInDays: number): void;
|
|
862
|
+
get(cookieKey: string): any;
|
|
863
|
+
del(cookieKey: string): void;
|
|
864
|
+
};
|
|
865
|
+
AuthStates: AuthStates;
|
|
866
|
+
setupAuth: SetupAuth;
|
|
867
|
+
serviceInfoFromUrl: getServiceInfoFromURL;
|
|
868
|
+
};
|
|
869
|
+
utils: {
|
|
870
|
+
isBrowser(): boolean;
|
|
871
|
+
extractTokenAndAPIEndpoint(apiEndpoint: string): TokenAndAPIEndpoint;
|
|
872
|
+
buildAPIEndpoint(tokenAndAPI: TokenAndAPIEndpoint): string;
|
|
873
|
+
browserIsMobileOrTablet(navigator: string): boolean;
|
|
874
|
+
cleanURLFromPrYvParams(url: string): string;
|
|
875
|
+
getQueryParamsFromURL(url: string): KeyValue;
|
|
876
|
+
};
|
|
823
877
|
version: version;
|
|
824
878
|
};
|
|
825
879
|
|
package/test/Connection.test.js
CHANGED
|
@@ -89,6 +89,18 @@ describe('Connection', () => {
|
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
+
describe('.apiOne()', function () {
|
|
93
|
+
this.timeout(15000);
|
|
94
|
+
it('.apiOne("events.get")', async () => {
|
|
95
|
+
const res = await conn.apiOne('events.get');
|
|
96
|
+
expect(res.events).to.exist;
|
|
97
|
+
});
|
|
98
|
+
it('.apiOne("events.get")', async () => {
|
|
99
|
+
const res = await conn.apiOne('events.get', {}, 'events');
|
|
100
|
+
expect(Array.isArray(res)).to.equal(true);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
92
104
|
describe('.api()', function () {
|
|
93
105
|
this.timeout(15000);
|
|
94
106
|
it('.api() events.get', async () => {
|