pryv 2.2.0 → 2.3.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/package.json +11 -45
- package/src/Auth/AuthController.js +43 -50
- package/src/Auth/AuthStates.js +12 -12
- package/src/Auth/LoginMessages.js +17 -14
- package/src/Auth/index.js +18 -15
- package/src/Browser/CookieUtils.js +37 -27
- package/src/Browser/LoginButton.js +42 -37
- package/src/Browser/index.js +16 -42
- package/src/Connection.js +102 -95
- package/src/Service.js +47 -45
- package/src/ServiceAssets.js +42 -34
- package/src/browser-index-bundle.js +8 -0
- package/src/browser-index.js +7 -0
- package/src/index.d.ts +36 -48
- package/src/index.js +20 -3
- package/src/lib/browser-getEventStreamed.js +21 -19
- package/src/lib/json-parser.js +23 -24
- package/src/utils.js +55 -43
- package/test/Browser.AuthController.test.js +19 -21
- package/test/Browser.test.js +23 -26
- package/test/Connection.test.js +135 -151
- package/test/Service.test.js +30 -44
- package/test/ServiceAssets.test.js +16 -22
- package/test/browser-index.html +26 -0
- package/test/utils.test.js +30 -35
- package/.jsdoc-conf.json +0 -29
- package/.mocharc.js +0 -13
- package/LICENSE.md +0 -27
- package/README.md +0 -742
- package/scripts/setup-environment-dev.sh +0 -28
- package/scripts/upload.sh +0 -15
- package/src/Pryv.js +0 -19
- package/src/index-socket.io-monitor.js +0 -4
- package/src/index.html +0 -17
- package/test/browser-index.js +0 -11
- package/test/browser-tests.html +0 -31
- package/test/helpers.js +0 -8
- package/test/load-test-account.js +0 -108
- package/test/test-data.js +0 -95
- package/web-demos/auth-with-redirection.html +0 -72
- package/web-demos/auth.html +0 -77
- package/web-demos/custom-login-button.html +0 -158
- package/web-demos/index.html +0 -186
- package/web-demos/service-info.json +0 -13
- package/web-demos/stream-examples.html +0 -80
- package/webpack.config.js +0 -83
package/README.md
DELETED
|
@@ -1,742 +0,0 @@
|
|
|
1
|
-
# JavaScript library for Pryv.io
|
|
2
|
-
|
|
3
|
-
This JavaScript library is meant to facilitate writing NodeJS and browser apps for a Pryv.io platform, it follows the [Pryv.io App Guidelines](https://api.pryv.com/guides/app-guidelines/).
|
|
4
|
-
|
|
5
|
-
## Contribute
|
|
6
|
-
|
|
7
|
-
*Prerequisites*: Node 12
|
|
8
|
-
|
|
9
|
-
- Setup: `npm run setup`
|
|
10
|
-
|
|
11
|
-
- Build pryv.js library for browsers: `npm run build`, the result is published in `./dist`
|
|
12
|
-
|
|
13
|
-
- Build documentation: `npm run doc`, the result is published in `./dist/docs`
|
|
14
|
-
|
|
15
|
-
Note: as per v2.1.7 `jsdoc` dev dependency has been removed from package.json .. it should be installed with `npm install jsoc --dev`
|
|
16
|
-
|
|
17
|
-
- Node Tests: `npm run test`
|
|
18
|
-
|
|
19
|
-
- Coverage: `npm run cover`, the result is visible in `./coverage`
|
|
20
|
-
|
|
21
|
-
- Browser tests: **build**, then `npm run webserver` and open [https://l.rec.la:9443/tests/browser-tests.html?pryvServiceInfoUrl=https://zouzou.com/service/info](https://l.rec.la:9443/tests/browser-tests.html?pryvServiceInfoUrl=https://zouzou.com/service/info)
|
|
22
|
-
|
|
23
|
-
- Update on CDN: After running **setup** and **build** scripts, run `npm run gh-pages ${COMMIT_MESSAGE}`. If this fails, run `npm run clear` to rebuild a fresh `dist/` folder
|
|
24
|
-
|
|
25
|
-
## Usage
|
|
26
|
-
|
|
27
|
-
### Table of Contents
|
|
28
|
-
|
|
29
|
-
+ [Import](#import)
|
|
30
|
-
- [Browser](#browser)
|
|
31
|
-
- [Node.js](#nodejs)
|
|
32
|
-
+ [Obtaining a Pryv.Connection](#obtaining-a-pryvconnection)
|
|
33
|
-
- [Using an API endpoint](#using-an-api-endpoint)
|
|
34
|
-
- [Using a Username & Token (knowing the service information URL)](#using-a-username--token-knowing-the-service-information-url)
|
|
35
|
-
- [Within a WebPage with a login button](#within-a-webpage-with-a-login-button)
|
|
36
|
-
- [Fetch access info](#fetch-access-info)
|
|
37
|
-
- [Using Service.login() *(trusted apps only)*](#using-servicelogin-trusted-apps-only)
|
|
38
|
-
- [Performing the authentication request with your own UI](#customize-auth-process)
|
|
39
|
-
+ [API calls](#api-calls)
|
|
40
|
-
+ [Advanced usage of API calls with optional individual result and progress callbacks](#advanced-usage-of-api-calls-with-optional-individual-result-and-progress-callbacks)
|
|
41
|
-
+ [Get Events Streamed](#get-events-streamed)
|
|
42
|
-
- [Example](#example)
|
|
43
|
-
- [result](#result)
|
|
44
|
-
+ [Events with Attachments](#events-with-attachments)
|
|
45
|
-
- [Node.js](#nodejs-1)
|
|
46
|
-
- [Browser](#browser-1)
|
|
47
|
-
+ [High Frequency Events](#high-frequency-events)
|
|
48
|
-
+ [Service Information and assets](#service-information-and-assets)
|
|
49
|
-
- [Pryv.Service](#pryvservice)
|
|
50
|
-
* [Initizalization with a service info URL](#initizalization-with-a-service-info-url)
|
|
51
|
-
* [Usage of Pryv.Service.](#usage-of-pryvservice)
|
|
52
|
-
+ [Pryv.Browser & Visual assets](#pryvbrowser--visual-assets)
|
|
53
|
-
- [Pryv.Browser - retrieve serviceInfo from query URL](#pryvbrowser---retrieve-serviceinfo-from-query-url)
|
|
54
|
-
- [Visual assets](#visual-assets)
|
|
55
|
-
+ [Customize Auth process](#customize-auth-process)
|
|
56
|
-
- [Using a custom login button](using-a-custom-login-button)
|
|
57
|
-
- [Redirect user to the authentication page](#redirect-user-to-the-authentication-page)
|
|
58
|
-
+ [Launch web demos locally](#launch-web-demos-locally)
|
|
59
|
-
|
|
60
|
-
### Import
|
|
61
|
-
|
|
62
|
-
#### Browser
|
|
63
|
-
|
|
64
|
-
```html
|
|
65
|
-
<script src="https://api.pryv.com/lib-js/pryv.js"></script>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
#### Others distributions for browsers & extensions:
|
|
69
|
-
|
|
70
|
-
- ES6: `https://api.pryv.com/lib-js/pryv-es6.js`
|
|
71
|
-
- Bundle: (Socket.io + Monitor + Lib-js) `https://api.pryv.com/lib-js/pryv-socket.io-monitor.js`.
|
|
72
|
-
This library can be extended with two packages:
|
|
73
|
-
- Socket.io extension: [https://github.com/pryv/lib-js-socket.io](https://github.com/pryv/lib-js-socket.io)
|
|
74
|
-
- Monitor extension: [https://github.com/pryv/lib-js-monitor](https://github.com/pryv/lib-js-monitor)
|
|
75
|
-
|
|
76
|
-
#### Example on code pen:
|
|
77
|
-
|
|
78
|
-
- Save notes and measure simple form: [Example on codepen.io](https://codepen.io/pryv/pen/ExVYemE)
|
|
79
|
-
|
|
80
|
-
#### Node.js
|
|
81
|
-
|
|
82
|
-
Install with: `npm install pryv --save `
|
|
83
|
-
|
|
84
|
-
```javascript
|
|
85
|
-
const Pryv = require('pryv');
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Obtaining a Pryv.Connection
|
|
89
|
-
|
|
90
|
-
A connection is an authenticated link to a Pryv.io account.
|
|
91
|
-
|
|
92
|
-
#### Using an API endpoint
|
|
93
|
-
|
|
94
|
-
The format of the API endpoint can be found in your platform's [service information](https://api.pryv.com/reference/#service-info) under the `api` property. The most frequent one has the following format: `https://{token}@{api-endpoint}`
|
|
95
|
-
|
|
96
|
-
```javascript
|
|
97
|
-
const apiEndpoint = 'https://ck6bwmcar00041ep87c8ujf90@drtom.pryv.me';
|
|
98
|
-
const connection = new Pryv.Connection(apiEndpoint);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
#### Using a Username & Token (knowing the service information URL)
|
|
102
|
-
|
|
103
|
-
```javascript
|
|
104
|
-
const service = new Pryv.Service('https://reg.pryv.me/service/info');
|
|
105
|
-
const apiEndpoint = await service.apiEndpointFor(username, token);
|
|
106
|
-
const connection = new Pryv.Connection(apiEndpoint);
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
#### Within a WebPage with a login button
|
|
110
|
-
|
|
111
|
-
The following code is an implementation of the [Pryv.io Authentication process](https://api.pryv.com/reference/#authenticate-your-app).
|
|
112
|
-
|
|
113
|
-
```html
|
|
114
|
-
<!doctype html>
|
|
115
|
-
<html>
|
|
116
|
-
<head>
|
|
117
|
-
<title>Pryv - Javascript Lib</title>
|
|
118
|
-
<script src="https://api.pryv.com/lib-js/pryv.js"></script>
|
|
119
|
-
</head>
|
|
120
|
-
<body>
|
|
121
|
-
<span id="pryv-button"></span>
|
|
122
|
-
<script>
|
|
123
|
-
var connection = null;
|
|
124
|
-
|
|
125
|
-
var authSettings = {
|
|
126
|
-
spanButtonID: 'pryv-button', // span id the DOM that will be replaced by the Service specific button
|
|
127
|
-
onStateChange: pryvAuthStateChange, // event Listener for Authentication steps
|
|
128
|
-
authRequest: { // See: https://api.pryv.com/reference/#auth-request
|
|
129
|
-
requestingAppId: 'lib-js-test',
|
|
130
|
-
languageCode: 'fr', // optional (default english)
|
|
131
|
-
requestedPermissions: [
|
|
132
|
-
{
|
|
133
|
-
streamId: 'test',
|
|
134
|
-
defaultName: 'test',
|
|
135
|
-
level: 'manage'
|
|
136
|
-
}
|
|
137
|
-
],
|
|
138
|
-
clientData: {
|
|
139
|
-
'app-web-auth:description': {
|
|
140
|
-
'type': 'note/txt', 'content': 'This is a consent message.'
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
// referer: 'my test with lib-js', // optional string to track registration source
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
function pryvAuthStateChange(state) { // called each time the authentication state changed
|
|
148
|
-
console.log('##pryvAuthStateChange', state);
|
|
149
|
-
if (state.id === Pryv.Auth.AuthStates.AUTHORIZED) {
|
|
150
|
-
connection = new Pryv.Connection(state.apiEndpoint);
|
|
151
|
-
logToConsole('# Browser succeeded for user ' + connection.apiEndpoint);
|
|
152
|
-
}
|
|
153
|
-
if (state.id === Pryv.Auth.AuthStates.SIGNOUT) {
|
|
154
|
-
connection = null;
|
|
155
|
-
logToConsole('# Logout');
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
var serviceInfoUrl = 'https://api.pryv.com/lib-js/demos/service-info.json';
|
|
159
|
-
(async function () {
|
|
160
|
-
var service = await Pryv.Auth.setupAuth(authSettings, serviceInfoUrl);
|
|
161
|
-
})();
|
|
162
|
-
</script>
|
|
163
|
-
</body>
|
|
164
|
-
</html>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### Fetch access info
|
|
168
|
-
|
|
169
|
-
Implementation of [access info](https://api.pryv.com/reference/#access-info).
|
|
170
|
-
|
|
171
|
-
```js
|
|
172
|
-
const apiEndpoint = 'https://ck6bwmcar00041ep87c8ujf90@drtom.pryv.me';
|
|
173
|
-
const connection = new Pryv.Connection(apiEndpoint);
|
|
174
|
-
const accessInfo = await connection.accessInfo();
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
#### Using Service.login() *(trusted apps only)*
|
|
178
|
-
|
|
179
|
-
[auth.login reference](https://api.pryv.com/reference-full/#login-user)
|
|
180
|
-
|
|
181
|
-
```javascript
|
|
182
|
-
const serviceInfoUrl = 'https://reg.pryv.me/service/info';
|
|
183
|
-
const appId = 'lib-js-sample';
|
|
184
|
-
const service = new Pryv.Service(serviceInfoUrl);
|
|
185
|
-
const connection = await service.login(username, password, appId);
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### API calls
|
|
189
|
-
|
|
190
|
-
Api calls are based on the `batch` call specifications: [Call batch API reference](https://api.pryv.com/reference/#call-batch)
|
|
191
|
-
|
|
192
|
-
```javascript
|
|
193
|
-
const apiCalls = [
|
|
194
|
-
{
|
|
195
|
-
"method": "streams.create",
|
|
196
|
-
"params": { "id": "heart", "name": "Heart" }
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
"method": "events.create",
|
|
200
|
-
"params": { "time": 1385046854.282, "streamId": "heart", "type": "frequency/bpm", "content": 90 }
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
"method": "events.create",
|
|
204
|
-
"params": { "time": 1385046854.283, "streamId": "heart", "type": "frequency/bpm", "content": 120 }
|
|
205
|
-
}
|
|
206
|
-
]
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
const result = await connection.api(apiCalls)
|
|
210
|
-
} catch (e) {
|
|
211
|
-
// handle error
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Advanced usage of API calls with optional individual result and progress callbacks
|
|
216
|
-
|
|
217
|
-
```javascript
|
|
218
|
-
let count = 0;
|
|
219
|
-
// the following will be called on each API method result it was provided for
|
|
220
|
-
function handleResult(result) { console.log('Got result ' + count++ + ': ' + JSON.stringify(result)); }
|
|
221
|
-
|
|
222
|
-
function progress(percentage) { console.log('Processed: ' + percentage + '%'); }
|
|
223
|
-
|
|
224
|
-
const apiCalls = [
|
|
225
|
-
{
|
|
226
|
-
method: 'streams.create',
|
|
227
|
-
params: { id: 'heart', name: 'Heart' }
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
method: 'events.create',
|
|
231
|
-
params: { time: 1385046854.282, streamId: 'heart', type: 'frequency/bpm', content: 90 },
|
|
232
|
-
handleResult: handleResult
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
method: 'events.create',
|
|
236
|
-
params: { time: 1385046854.283, streamId: 'heart', type: 'frequency/bpm', content: 120 },
|
|
237
|
-
handleResult: handleResult
|
|
238
|
-
}
|
|
239
|
-
]
|
|
240
|
-
|
|
241
|
-
try {
|
|
242
|
-
const result = await connection.api(apiCalls, progress)
|
|
243
|
-
} catch (e) {
|
|
244
|
-
// handle error
|
|
245
|
-
}
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Get Events Streamed
|
|
249
|
-
|
|
250
|
-
When `events.get` will provide a large result set, it is recommended to use a method that streams the result instead of the batch API call.
|
|
251
|
-
|
|
252
|
-
`Pryv.Connection.getEventsStreamed()` parses the response JSON as soon as data is available and calls the `forEachEvent()` callback on each event object.
|
|
253
|
-
|
|
254
|
-
The callback is meant to store the events data, as the function does not return the API call result, which could overflow memory in case of JSON deserialization of a very large data set.
|
|
255
|
-
Instead, the function returns an events count and eventually event deletions count as well as the [common metadata](https://api.pryv.com/reference/#common-metadata).
|
|
256
|
-
|
|
257
|
-
#### Example:
|
|
258
|
-
|
|
259
|
-
`````` javascript
|
|
260
|
-
const now = (new Date()).getTime() / 1000;
|
|
261
|
-
const queryParams = { fromTime: 0, toTime: now, limit: 10000};
|
|
262
|
-
const events = [];
|
|
263
|
-
function forEachEvent(event) {
|
|
264
|
-
events.push(event);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
const result = await connection.getEventsStreamed(queryParams, forEachEvent);
|
|
269
|
-
} catch (e) {
|
|
270
|
-
// handle error
|
|
271
|
-
}
|
|
272
|
-
``````
|
|
273
|
-
|
|
274
|
-
#### result:
|
|
275
|
-
|
|
276
|
-
```javascript
|
|
277
|
-
{
|
|
278
|
-
eventsCount: 10000,
|
|
279
|
-
meta:
|
|
280
|
-
{
|
|
281
|
-
apiVersion: '1.4.26',
|
|
282
|
-
serverTime: 1580728336.864,
|
|
283
|
-
serial: '2019061301'
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
#### Example with Includes deletion:
|
|
289
|
-
|
|
290
|
-
`````` javascript
|
|
291
|
-
const now = (new Date()).getTime() / 1000;
|
|
292
|
-
const queryParams = { fromTime: 0, toTime: now, includeDeletions: true, modifiedSince: 0};
|
|
293
|
-
const events = [];
|
|
294
|
-
function forEachEvent(event) {
|
|
295
|
-
events.push(event);
|
|
296
|
-
// events with .deleted or/and .trashed properties can be tracked here
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
try {
|
|
300
|
-
const result = await connection.getEventsStreamed(queryParams, forEachEvent);
|
|
301
|
-
} catch (e) {
|
|
302
|
-
// handle error
|
|
303
|
-
}
|
|
304
|
-
``````
|
|
305
|
-
|
|
306
|
-
#### result:
|
|
307
|
-
|
|
308
|
-
```javascript
|
|
309
|
-
{
|
|
310
|
-
eventDeletionsCount: 150,
|
|
311
|
-
eventsCount: 10000,
|
|
312
|
-
meta:
|
|
313
|
-
{
|
|
314
|
-
apiVersion: '1.4.26',
|
|
315
|
-
serverTime: 1580728336.864,
|
|
316
|
-
serial: '2019061301'
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
### Events with Attachments
|
|
326
|
-
|
|
327
|
-
This shortcut allows to create an event with an attachment in a single API call.
|
|
328
|
-
|
|
329
|
-
#### Node.js
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
const filePath = './test/my_image.png';
|
|
333
|
-
const result = await connection.createEventWithFile(
|
|
334
|
-
{
|
|
335
|
-
type: 'picture/attached',
|
|
336
|
-
streamId: 'data'
|
|
337
|
-
},
|
|
338
|
-
filePath
|
|
339
|
-
);
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
or from a Buffer
|
|
343
|
-
|
|
344
|
-
```javascript
|
|
345
|
-
const filePath = './test/my_image.png';
|
|
346
|
-
const bufferData = fs.readFileSync(filePath);
|
|
347
|
-
|
|
348
|
-
const result = await connection.createEventWithFileFromBuffer(
|
|
349
|
-
{
|
|
350
|
-
type: 'picture/attached',
|
|
351
|
-
streamId: 'data'
|
|
352
|
-
},
|
|
353
|
-
bufferData,
|
|
354
|
-
'my_image.png' // filename
|
|
355
|
-
);
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
#### Browser
|
|
359
|
-
|
|
360
|
-
From an Input field
|
|
361
|
-
|
|
362
|
-
```html
|
|
363
|
-
<input type="file" id="file-upload"><button onClick='uploadFile()'>Save Value</button>
|
|
364
|
-
|
|
365
|
-
<script>
|
|
366
|
-
var formData = new FormData();
|
|
367
|
-
formData.append(
|
|
368
|
-
'file0',
|
|
369
|
-
document.getElementById('create-file').files[0]
|
|
370
|
-
) ;
|
|
371
|
-
|
|
372
|
-
connection.createEventWithFormData(
|
|
373
|
-
{
|
|
374
|
-
type: 'file/attached',
|
|
375
|
-
streamId: 'test'
|
|
376
|
-
},
|
|
377
|
-
formData)
|
|
378
|
-
.then(function (res, err) {
|
|
379
|
-
// handle result here
|
|
380
|
-
}
|
|
381
|
-
);
|
|
382
|
-
</script>
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
Progamatically created content:
|
|
386
|
-
|
|
387
|
-
```javascript
|
|
388
|
-
var formData = new FormData();
|
|
389
|
-
var blob = new Blob(
|
|
390
|
-
['Hello'],
|
|
391
|
-
{ type: "text/txt" }
|
|
392
|
-
);
|
|
393
|
-
formData.append("webmasterfile", blob);
|
|
394
|
-
|
|
395
|
-
connect.createEventWithFormData(
|
|
396
|
-
{
|
|
397
|
-
type: 'file/attached',
|
|
398
|
-
streamId: 'data'
|
|
399
|
-
},
|
|
400
|
-
formData)
|
|
401
|
-
.then(function (res, err) {
|
|
402
|
-
// handle result here
|
|
403
|
-
}
|
|
404
|
-
);
|
|
405
|
-
|
|
406
|
-
// -- alternative with a filename
|
|
407
|
-
|
|
408
|
-
connect.createEventWithFileFromBuffer(
|
|
409
|
-
{
|
|
410
|
-
type: 'file/attached',
|
|
411
|
-
streamId: 'data'
|
|
412
|
-
},
|
|
413
|
-
blob, 'filename.txt') // here we can directly use the blob
|
|
414
|
-
.then(function (res, err) {
|
|
415
|
-
// handle result here
|
|
416
|
-
}
|
|
417
|
-
);
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### High Frequency Events
|
|
423
|
-
|
|
424
|
-
Reference: [https://api.pryv.com/reference/#hf-events](https://api.pryv.com/reference/#hf-events)
|
|
425
|
-
|
|
426
|
-
```javascript
|
|
427
|
-
function generateSerie() {
|
|
428
|
-
const serie = [];
|
|
429
|
-
for (let t = 0; t < 100000, t++) { // t will be the deltaTime in seconds
|
|
430
|
-
serie.push([t, Math.sin(t/1000)]);
|
|
431
|
-
}
|
|
432
|
-
return serie;
|
|
433
|
-
}
|
|
434
|
-
const pointsA = generateSerie();
|
|
435
|
-
const pointsB = generateSerie();
|
|
436
|
-
|
|
437
|
-
function postHFData(points) { // must return a Promise
|
|
438
|
-
return async function (result) { // will be called each time an HF event is created
|
|
439
|
-
return await connection.addPointsToHFEvent(result.event.id, ['deltaTime', 'value'], points);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const apiCalls = [
|
|
444
|
-
{
|
|
445
|
-
method: 'streams.create',
|
|
446
|
-
params: { id: 'signal1', name: 'Signal1' }
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
method: 'streams.create',
|
|
450
|
-
params: { id: 'signal2', name: 'Signal2' }
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
method: 'events.create',
|
|
454
|
-
params: { streamId: 'signal1', type: 'serie:frequency/bpm' },
|
|
455
|
-
handleResult: postHFData(pointsA)
|
|
456
|
-
},
|
|
457
|
-
{
|
|
458
|
-
method: 'events.create',
|
|
459
|
-
params: { streamId: 'signal2', type: 'serie:frequency/bpm' },
|
|
460
|
-
handleResult: postHFData(pointsB)
|
|
461
|
-
}
|
|
462
|
-
]
|
|
463
|
-
|
|
464
|
-
try {
|
|
465
|
-
const result = await connection.api(apiCalls)
|
|
466
|
-
} catch (e) {
|
|
467
|
-
// handle error
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### Service Information and assets
|
|
473
|
-
|
|
474
|
-
A Pryv.io deployment is a unique "Service", as an example **Pryv Lab** is a service, deployed on the **pryv.me** domain name.
|
|
475
|
-
|
|
476
|
-
It relies on the content of a **service information** configuration, See: [Service Information API reference](https://api.pryv.com/reference/#service-info)
|
|
477
|
-
|
|
478
|
-
#### Pryv.Service
|
|
479
|
-
|
|
480
|
-
Exposes tools to interact with Pryv.io at a "Platform" level.
|
|
481
|
-
|
|
482
|
-
##### Initizalization with a service info URL
|
|
483
|
-
|
|
484
|
-
```javascript
|
|
485
|
-
const service = new Pryv.Service('https://reg.pryv.me/service/info');
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
##### Initialization with the content of a service info configuration
|
|
489
|
-
|
|
490
|
-
Service information properties can be overriden with specific values. This might be useful to test new designs on production platforms.
|
|
491
|
-
|
|
492
|
-
```javascript
|
|
493
|
-
const serviceInfoUrl = 'https://reg.pryv.me/service/info';
|
|
494
|
-
const serviceCustomizations = {
|
|
495
|
-
name: 'Pryv Lab 2',
|
|
496
|
-
assets: {
|
|
497
|
-
definitions: 'https://pryv.github.io/assets-pryv.me/index.json'
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
const service = new Pryv.Service(serviceInfoUrl, serviceCustomizations);
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
##### Usage of Pryv.Service.
|
|
504
|
-
|
|
505
|
-
See: [Pryv.Service](https://pryv.github.io/js-lib/docs/Pryv.Service.html) for more details
|
|
506
|
-
|
|
507
|
-
- `service.info()` - returns the content of the serviceInfo in a Promise
|
|
508
|
-
|
|
509
|
-
```javascript
|
|
510
|
-
// example: get the name of the platform
|
|
511
|
-
const serviceName = await service.info().name
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
- `service.infoSync()`: returns the cached content of the serviceInfo, requires `service.info()` to be called first.
|
|
515
|
-
|
|
516
|
-
- `service.apiEndpointFor(username, token)` Will return the corresponding API endpoint for the provided credentials, `token` can be omitted.
|
|
517
|
-
|
|
518
|
-
### Pryv.Browser & Visual assets
|
|
519
|
-
|
|
520
|
-
#### Pryv.Browser - retrieve serviceInfo from query URL
|
|
521
|
-
|
|
522
|
-
A single Web App might need to be run on different Pryv.io platforms. This is the case of most Pryv.io demonstrators.
|
|
523
|
-
|
|
524
|
-
The corresponding Pryv.io platform can be specified by providing the Service Information URL as query parameter `pryvServiceInfoUrl` as per the [Pryv App Guidelines](https://api.pryv.com/guides/app-guidelines/). It can be extracted using `Pryv.Browser.serviceInfoFromUrl()` .
|
|
525
|
-
|
|
526
|
-
Example of usage for web App with the url https://api.pryv.com/app-web-access/?pryvServiceInfoUrl=https://reg.pryv.me/service/info
|
|
527
|
-
|
|
528
|
-
```javascript
|
|
529
|
-
let defaultServiceInfoUrl = 'https://reg.pryv.me/service/info';
|
|
530
|
-
// if present override serviceInfoURL from URL query param "?pryvServiceInfoUrl=.."
|
|
531
|
-
serviceInfoUrl = Pryv.Browser.serviceInfoFromUrl() || defaultServiceInfoUrl;
|
|
532
|
-
|
|
533
|
-
(async function () {
|
|
534
|
-
var service = await Pryv.Auth.setupAuth(authSettings, serviceInfoUrl, serviceCustomizations);
|
|
535
|
-
})();
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
#### Visual assets
|
|
539
|
-
|
|
540
|
-
To customize assets and visuals refer to: [pryv.me assets github](https://github.com/pryv/assets-pryv.me)
|
|
541
|
-
|
|
542
|
-
To customize the Sign in Button refer to: [sign in button in pryv.me assets](https://github.com/pryv/assets-pryv.me/tree/master/lib-js/)
|
|
543
|
-
|
|
544
|
-
`(service.assets()).setAllDefaults()`: loads the `css` and `favicon` properties of assets definitions.
|
|
545
|
-
|
|
546
|
-
```javascript
|
|
547
|
-
(async function () {
|
|
548
|
-
const service = await Pryv.Auth.setupAuth(authSettings, serviceInfoUrl);
|
|
549
|
-
(await service.assets()).setAllDefaults(); // will load the default Favicon and CSS for this platform
|
|
550
|
-
})();
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
### Customize Auth process
|
|
554
|
-
|
|
555
|
-
You can customize the authentication process at different levels:
|
|
556
|
-
|
|
557
|
-
1. [Using a custom login button](#using-your-own-login-button) to launch the [Pryv.io Authentication process](https://api.pryv.com/reference/#authenticate-your-app).
|
|
558
|
-
2. Using a custom UI for the [Pryv.io Authentication process](https://api.pryv.com/reference/#authenticate-your-app), including the flow of [app-web-auth3](https://github.com/pryv/app-web-auth3).
|
|
559
|
-
|
|
560
|
-
#### Using a custom login button
|
|
561
|
-
|
|
562
|
-
You will need to implement a class that instanciates an [AuthController](src/Auth/AuthController.js) object and implements a few methods. We will go through this guide using the Browser's default [Login Button](src/Browser/LoginButton.js) provided with this library as example.
|
|
563
|
-
|
|
564
|
-
##### Initialization
|
|
565
|
-
|
|
566
|
-
You should provide it `authSettings` (See [Obtain a Pryv.Connection](#within-a-webpage-with-a-login-button)) and an instance of [Service](src/Service.js) at initialization. As this phase might contain asynchronous calls, we like to split it between the constructor and an `async init()` function. In particular, you will need to instanciate an [AuthController](src/Auth/AuthController.js) object.
|
|
567
|
-
|
|
568
|
-
```javascript
|
|
569
|
-
constructor(authSettings, service) {
|
|
570
|
-
this.authSettings = authSettings;
|
|
571
|
-
this.service = service;
|
|
572
|
-
this.serviceInfo = service.infoSync();
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
async init () {
|
|
576
|
-
// initialize button visuals
|
|
577
|
-
// ...
|
|
578
|
-
|
|
579
|
-
// set cookie key for authorization data - browser only
|
|
580
|
-
this._cookieKey = 'pryv-libjs-' + this.authSettings.authRequest.requestingAppId;
|
|
581
|
-
|
|
582
|
-
// initialize controller
|
|
583
|
-
this.auth = new AuthController(this.authSettings, this.service, this);
|
|
584
|
-
await this.auth.init();
|
|
585
|
-
}
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
##### Authorization data
|
|
589
|
-
|
|
590
|
-
At initialization, the [AuthController](src/Auth/AuthController.js) will attempt to fetch some persisted authorization credentials, using `LoginButton.getAuthorizationData()`. In the browser case, we are using a client-side cookie. For other frameworks, use an appropriate secure storage.
|
|
591
|
-
|
|
592
|
-
```javascript
|
|
593
|
-
getAuthorizationData () {
|
|
594
|
-
return Cookies.get(this._cookieKey);
|
|
595
|
-
}
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
##### Authentication lifecycle
|
|
599
|
-
|
|
600
|
-
The [authentication process](https://api.pryv.com/reference/#authenticate-your-app) implementation on the frontend is defined in the following states:
|
|
601
|
-
|
|
602
|
-
1. Loading: while the visual assets are loading
|
|
603
|
-
2. Initialized: visuals assets are loaded, or when [polling](https://api.pryv.com/reference/#poll-request) concludes with **Result: Refused**
|
|
604
|
-
3. Need sign in: From the response of the [auth request](https://api.pryv.com/reference/#auth-request) through [polling](https://api.pryv.com/reference/#poll-request)
|
|
605
|
-
4. Authorized: When [polling](https://api.pryv.com/reference/#poll-request) concludes with **Result: Accepted**
|
|
606
|
-
5. Sign out: When the user triggers a deletion of the client-side authorization credentials, usually by clicking the button after being signed in
|
|
607
|
-
6. Error: See message for more information
|
|
608
|
-
|
|
609
|
-
You will need to provide a function to act depending on the state. The states`NEED_SIGNIN` and `AUTHORIZED` contain the same fields as the [auth process polling responses](https://api.pryv.com/reference/#poll-request). `LOADING`, `INITIALIZED` and `SIGNOUT` only contain `status`. The `ERROR` state carries a `message` property.
|
|
610
|
-
|
|
611
|
-
```javascript
|
|
612
|
-
async onStateChange (state) {
|
|
613
|
-
switch (state.status) {
|
|
614
|
-
case AuthStates.LOADING:
|
|
615
|
-
this.text = getLoadingMessage(this);
|
|
616
|
-
break;
|
|
617
|
-
case AuthStates.INITIALIZED:
|
|
618
|
-
this.text = getInitializedMessage(this, this.serviceInfo.name);
|
|
619
|
-
break;
|
|
620
|
-
case AuthStates.NEED_SIGNIN:
|
|
621
|
-
const loginUrl = state.authUrl || state.url; // .url is deprecated
|
|
622
|
-
if (this.authSettings.authRequest.returnURL) { // open on same page (no Popup)
|
|
623
|
-
location.href = loginUrl;
|
|
624
|
-
return;
|
|
625
|
-
} else {
|
|
626
|
-
startLoginScreen(this, loginUrl);
|
|
627
|
-
}
|
|
628
|
-
break;
|
|
629
|
-
case AuthStates.AUTHORIZED:
|
|
630
|
-
this.text = state.username;
|
|
631
|
-
this.saveAuthorizationData({
|
|
632
|
-
apiEndpoint: state.apiEndpoint,
|
|
633
|
-
username: state.username
|
|
634
|
-
});
|
|
635
|
-
break;
|
|
636
|
-
case AuthStates.SIGNOUT:
|
|
637
|
-
const message = this.messages.SIGNOUT_CONFIRM ? this.messages.SIGNOUT_CONFIRM : 'Logout ?';
|
|
638
|
-
if (confirm(message)) {
|
|
639
|
-
this.deleteAuthorizationData();
|
|
640
|
-
this.auth.init();
|
|
641
|
-
}
|
|
642
|
-
break;
|
|
643
|
-
case AuthStates.ERROR:
|
|
644
|
-
this.text = getErrorMessage(this, state.message);
|
|
645
|
-
break;
|
|
646
|
-
default:
|
|
647
|
-
console.log('WARNING Unhandled state for Login: ' + state.status);
|
|
648
|
-
}
|
|
649
|
-
if (this.loginButtonText) {
|
|
650
|
-
this.loginButtonText.innerHTML = this.text;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
##### Button actions
|
|
656
|
-
|
|
657
|
-
The button actions should be handled by the [AuthController](src/Auth/AuthController.js) in the following way:
|
|
658
|
-
|
|
659
|
-
```javascript
|
|
660
|
-
// LoginButton.js
|
|
661
|
-
onClick () {
|
|
662
|
-
this.auth.handleClick();
|
|
663
|
-
}
|
|
664
|
-
```
|
|
665
|
-
|
|
666
|
-
```javascript
|
|
667
|
-
// AuthController.js
|
|
668
|
-
async handleClick () {
|
|
669
|
-
if (isAuthorized.call(this)) {
|
|
670
|
-
this.state = { status: AuthStates.SIGNOUT };
|
|
671
|
-
} else if (isInitialized.call(this)) {
|
|
672
|
-
this.startAuthRequest();
|
|
673
|
-
} else if (isNeedSignIn.call(this)) {
|
|
674
|
-
// reopen popup
|
|
675
|
-
this.state = this.state;
|
|
676
|
-
} else {
|
|
677
|
-
console.log('Unhandled action in "handleClick()" for status:', this.state.status);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
##### Custom button usage
|
|
683
|
-
|
|
684
|
-
You must then provide this class as following:
|
|
685
|
-
|
|
686
|
-
```javascript
|
|
687
|
-
let service = await Pryv.Auth.setupAuth(
|
|
688
|
-
authSettings, // See https://github.com/pryv/lib-js#within-a-webpage-with-a-login-button
|
|
689
|
-
serviceInfoUrl,
|
|
690
|
-
serviceCustomizations,
|
|
691
|
-
MyLoginButton,
|
|
692
|
-
);
|
|
693
|
-
```
|
|
694
|
-
|
|
695
|
-
You will find a working example in [`./web-demos/custom-login-button.html`](./web-demos/custom-login-button.html). You can run this code at [https://api.pryv.com/lib-js/demos/custom-login-button.html](https://api.pryv.com/lib-js/demos/custom-login-button.html).
|
|
696
|
-
|
|
697
|
-
Follow the instructions below on [how to run these examples locally](#launch-web-demos-locally).
|
|
698
|
-
|
|
699
|
-
For a more advanced scenario, you can check the default button implementation at [`./src/Browser/LoginButton.js`](/src/Browser/LoginButton.js).
|
|
700
|
-
|
|
701
|
-
#### Redirect user to the authentication page
|
|
702
|
-
|
|
703
|
-
There is a possibility that you would like to register the user in another page. You can check the [`./web-demos/auth-with-redirection.html`](./web-demos/auth-with-redirection.html) example.
|
|
704
|
-
Also you can try the same code in [https://api.pryv.com/lib-js/demos/auth-with-redirection.html](https://api.pryv.com/lib-js/demos/auth-with-redirection.html).
|
|
705
|
-
Here is the explanation how to [launch web-demos locally](#launch-web-demos-locally)
|
|
706
|
-
|
|
707
|
-
### Launch web demos locally
|
|
708
|
-
|
|
709
|
-
You can find html examples in the [`./web-demos`](/web-demos) directory. You can launch them in 2 ways:
|
|
710
|
-
|
|
711
|
-
1. using [rec-la](https://github.com/pryv/rec-la) that allows to run your code with a valid SSL certificate (this requires to have run `npm run build` prior). To launch the server you simply need to run:
|
|
712
|
-
|
|
713
|
-
```bash
|
|
714
|
-
npm run webserver
|
|
715
|
-
```
|
|
716
|
-
|
|
717
|
-
and open an example with the following URL **https://l.rec.la:9443/demos/EXAMPLE_NAME.html**, like: [https://l.rec.la:9443/demos/auth.html](https://l.rec.la:9443/demos/auth.html)
|
|
718
|
-
|
|
719
|
-
2. as a simple html file (service information must be passed as JSON to avoid CORS problem).
|
|
720
|
-
|
|
721
|
-
# Change Log
|
|
722
|
-
|
|
723
|
-
## 2.2.0
|
|
724
|
-
|
|
725
|
-
- Added TypeScript typings – contribution from @ovesco
|
|
726
|
-
|
|
727
|
-
## 2.1.7
|
|
728
|
-
|
|
729
|
-
- Removed JSDOC dev dependency for security reason
|
|
730
|
-
|
|
731
|
-
## 2.1.0
|
|
732
|
-
|
|
733
|
-
- UI separated from the Authentication logic
|
|
734
|
-
- Extendable UI feature was added
|
|
735
|
-
|
|
736
|
-
## 2.0.3
|
|
737
|
-
|
|
738
|
-
- Added Connection.username()
|
|
739
|
-
- Various dependencies upgrades
|
|
740
|
-
- Fixing Origin header in Browser distribution
|
|
741
|
-
|
|
742
|
-
## 2.0.1 Initial Release
|