pryv 2.3.0 → 2.3.1

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.
Files changed (2) hide show
  1. package/README.md +734 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,734 @@
1
+ # `pryv`: JS library for Pryv.io
2
+
3
+ JavaScript library and add-ons for writing Node.js and browser apps connecting to a Pryv.io platform. It follows the [Pryv.io app guidelines](https://api.pryv.com/guides/app-guidelines/).
4
+
5
+
6
+ ## Table of Contents <!-- omit in toc -->
7
+
8
+ 1. [Usage](#usage)
9
+ 1. [Importing](#importing)
10
+ 2. [Quick example](#quick-example)
11
+ 3. [Obtaining a `pryv.Connection`](#obtaining-a-pryvconnection)
12
+ 4. [API calls](#api-calls)
13
+ 5. [Get events streamed](#get-events-streamed)
14
+ 6. [Events with attachments](#events-with-attachments)
15
+ 7. [High Frequency (HF) events](#high-frequency-hf-events)
16
+ 8. [Service information and assets](#service-information-and-assets)
17
+ 9. [`pryv.Browser` & visual assets](#pryvbrowser--visual-assets)
18
+ 10. [Customize the authentication process](#customize-the-authentication-process)
19
+ 11. [Running examples locally](#running-examples-locally)
20
+ 2. [Contributing](#contributing)
21
+ 1. [Installation](#installation)
22
+ 2. [Dev environment basics](#dev-environment-basics)
23
+ 3. [Building for the browser](#building-for-the-browser)
24
+ 4. [Testing](#testing)
25
+ 5. [Publishing](#publishing)
26
+ 3. [Changelog](#changelog)
27
+ 4. [License](#license)
28
+
29
+
30
+ ## Usage
31
+
32
+
33
+ ### Importing
34
+
35
+ #### NPM
36
+
37
+ `npm install --save pryv`, then in your code:
38
+
39
+ ```js
40
+ const pryv = require('pryv');
41
+ ```
42
+
43
+ #### `<script>` tag
44
+
45
+ ```html
46
+ <script src="https://api.pryv.com/lib-js/pryv.js"></script>
47
+ ```
48
+
49
+ Other distributions available:
50
+
51
+ - ES6: `https://api.pryv.com/lib-js/pryv-es6.js`
52
+ - Library bundled with Socket.IO and Monitor add-ons: `https://api.pryv.com/lib-js/pryv-socket.io-monitor.js`.
53
+
54
+ #### Add-ons
55
+
56
+ - Socket.IO: [NPM package](https://www.npmjs.com/package/@pryv/socket.io), [README](https://github.com/pryv/lib-js/tree/master/components/pryv-socket.io#readme)
57
+ - Monitor: [NPM package](https://www.npmjs.com/package/@pryv/monitor), [README](https://github.com/pryv/lib-js/tree/master/components/pryv-monitor#readme)
58
+
59
+
60
+ ### Quick example
61
+
62
+ - [A simple form to save notes and measurements (CodePen)](https://codepen.io/pryv/pen/ExVYemE)
63
+
64
+
65
+ ### Obtaining a `pryv.Connection`
66
+
67
+ A connection is an authenticated link to a Pryv.io account.
68
+
69
+ #### With an API endpoint
70
+
71
+ 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. It usually looks like: `https://{token}@{hostname}`
72
+
73
+ ```js
74
+ const apiEndpoint = 'https://ck6bwmcar00041ep87c8ujf90@drtom.pryv.me';
75
+ const connection = new pryv.Connection(apiEndpoint);
76
+ ```
77
+
78
+ #### With username & token (knowing the service information URL)
79
+
80
+ ```js
81
+ const service = new pryv.Service('https://reg.pryv.me/service/info');
82
+ const apiEndpoint = await service.apiEndpointFor(username, token);
83
+ const connection = new pryv.Connection(apiEndpoint);
84
+ ```
85
+
86
+ #### Within a web page with a login button
87
+
88
+ Here is an implementation of the [Pryv.io authentication process](https://api.pryv.com/reference/#authenticate-your-app):
89
+
90
+ ```html
91
+ <!doctype html>
92
+ <html>
93
+ <head>
94
+ <title>Pryv authentication example</title>
95
+ <script src="https://api.pryv.com/lib-js/pryv.js"></script>
96
+ </head>
97
+ <body>
98
+ <span id="pryv-button"></span>
99
+ <script>
100
+ var connection = null;
101
+
102
+ var authSettings = {
103
+ spanButtonID: 'pryv-button', // id of the <span> that will be replaced by the service-specific button
104
+ onStateChange: authStateChanged, // event listener for authentication steps
105
+ authRequest: { // See: https://api.pryv.com/reference/#auth-request
106
+ requestingAppId: 'lib-js-test',
107
+ languageCode: 'fr', // optional (default: 'en')
108
+ requestedPermissions: [
109
+ {
110
+ streamId: 'test',
111
+ defaultName: 'test',
112
+ level: 'manage'
113
+ }
114
+ ],
115
+ clientData: {
116
+ 'app-web-auth:description': {
117
+ 'type': 'note/txt', 'content': 'This is a consent message.'
118
+ }
119
+ },
120
+ // referer: 'my test with lib-js', // optional string to track registration source
121
+ }
122
+ };
123
+ var serviceInfoUrl = 'https://api.pryv.com/lib-js/examples/service-info.json';
124
+ (async function () {
125
+ var service = await pryv.Auth.setupAuth(authSettings, serviceInfoUrl);
126
+ })();
127
+
128
+ function authStateChanged(state) { // called each time the authentication state changes
129
+ console.log('# Auth state changed:', state);
130
+ if (state.id === pryv.Auth.AuthStates.AUTHORIZED) {
131
+ connection = new pryv.Connection(state.apiEndpoint);
132
+ logToConsole('# Browser succeeded for user ' + connection.apiEndpoint);
133
+ }
134
+ if (state.id === pryv.Auth.AuthStates.SIGNOUT) {
135
+ connection = null;
136
+ logToConsole('# Signed out');
137
+ }
138
+ }
139
+ </script>
140
+ </body>
141
+ </html>
142
+ ```
143
+
144
+ #### Fetching access info
145
+
146
+ [API reference](https://api.pryv.com/reference/#access-info).
147
+
148
+ ```js
149
+ const apiEndpoint = 'https://ck6bwmcar00041ep87c8ujf90@drtom.pryv.me';
150
+ const connection = new pryv.Connection(apiEndpoint);
151
+ const accessInfo = await connection.accessInfo();
152
+ ```
153
+
154
+ #### Using `pryv.Service.login()` _(trusted apps only)_
155
+
156
+ [API reference](https://api.pryv.com/reference-full/#login-user)
157
+
158
+ ```js
159
+ const serviceInfoUrl = 'https://reg.pryv.me/service/info';
160
+ const appId = 'lib-js-sample';
161
+ const service = new pryv.Service(serviceInfoUrl);
162
+ const connection = await service.login(username, password, appId);
163
+ ```
164
+
165
+
166
+ ### API calls
167
+
168
+ API calls are based on the "batch" call specification: [Call batch API reference](https://api.pryv.com/reference/#call-batch)
169
+
170
+ #### Simple usage
171
+
172
+ ```js
173
+ const apiCalls = [
174
+ {
175
+ "method": "streams.create",
176
+ "params": { "id": "heart", "name": "Heart" }
177
+ },
178
+ {
179
+ "method": "events.create",
180
+ "params": { "time": 1385046854.282, "streamIds": ["heart"], "type": "frequency/bpm", "content": 90 }
181
+ },
182
+ {
183
+ "method": "events.create",
184
+ "params": { "time": 1385046854.283, "streamIds": ["heart"], "type": "frequency/bpm", "content": 120 }
185
+ }
186
+ ]
187
+
188
+ try {
189
+ const result = await connection.api(apiCalls)
190
+ } catch (e) {
191
+ // handle error
192
+ }
193
+ ```
194
+
195
+ #### Advanced usage with optional individual result and progress callbacks
196
+
197
+ ```js
198
+ let count = 0;
199
+ // the following will be called on each API method result it was provided for
200
+ function handleResult(result) { console.log('Got result ' + count++ + ': ' + JSON.stringify(result)); }
201
+
202
+ function progress(percentage) { console.log('Processed: ' + percentage + '%'); }
203
+
204
+ const apiCalls = [
205
+ {
206
+ method: 'streams.create',
207
+ params: { id: 'heart', name: 'Heart' }
208
+ },
209
+ {
210
+ method: 'events.create',
211
+ params: { time: 1385046854.282, streamIds: ['heart'], type: 'frequency/bpm', content: 90 },
212
+ handleResult: handleResult
213
+ },
214
+ {
215
+ method: 'events.create',
216
+ params: { time: 1385046854.283, streamIds: ['heart'], type: 'frequency/bpm', content: 120 },
217
+ handleResult: handleResult
218
+ }
219
+ ]
220
+
221
+ try {
222
+ const result = await connection.api(apiCalls, progress)
223
+ } catch (e) {
224
+ // handle error
225
+ }
226
+ ```
227
+
228
+
229
+ ### Get events streamed
230
+
231
+ 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.
232
+
233
+ `pryv.Connection.getEventsStreamed()` parses the response JSON as soon as data is available and calls the `forEachEvent` callback for each event object.
234
+
235
+ 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. Instead, the function returns an events count and possibly event deletions count as well as the [common metadata](https://api.pryv.com/reference/#common-metadata).
236
+
237
+ #### Example
238
+
239
+ ```js
240
+ const now = (new Date()).getTime() / 1000;
241
+ const queryParams = { fromTime: 0, toTime: now, limit: 10000};
242
+ const events = [];
243
+ function forEachEvent(event) {
244
+ events.push(event);
245
+ }
246
+
247
+ try {
248
+ const result = await connection.getEventsStreamed(queryParams, forEachEvent);
249
+ } catch (e) {
250
+ // handle error
251
+ }
252
+ ```
253
+
254
+ `result`:
255
+
256
+ ```js
257
+ {
258
+ eventsCount: 10000,
259
+ meta:
260
+ {
261
+ apiVersion: '1.4.26',
262
+ serverTime: 1580728336.864,
263
+ serial: '2019061301'
264
+ }
265
+ }
266
+ ```
267
+
268
+ #### Example including deletions
269
+
270
+ ```js
271
+ const now = (new Date()).getTime() / 1000;
272
+ const queryParams = { fromTime: 0, toTime: now, includeDeletions: true, modifiedSince: 0};
273
+ const events = [];
274
+ function forEachEvent(event) {
275
+ events.push(event);
276
+ // events with `deleted` or/and `trashed` properties can be tracked here
277
+ }
278
+
279
+ try {
280
+ const result = await connection.getEventsStreamed(queryParams, forEachEvent);
281
+ } catch (e) {
282
+ // handle error
283
+ }
284
+ ```
285
+
286
+ `result`:
287
+
288
+ ```js
289
+ {
290
+ eventDeletionsCount: 150,
291
+ eventsCount: 10000,
292
+ meta:
293
+ {
294
+ apiVersion: '1.4.26',
295
+ serverTime: 1580728336.864,
296
+ serial: '2019061301'
297
+ }
298
+ }
299
+ ```
300
+
301
+
302
+ ### Events with attachments
303
+
304
+ You can create an event with an attachment in a single API call.
305
+
306
+ #### Node.js
307
+
308
+ ```js
309
+ const filePath = './test/my_image.png';
310
+ const result = await connection.createEventWithFile({
311
+ type: 'picture/attached',
312
+ streamIds: ['data']
313
+ }, filePath);
314
+ ```
315
+
316
+ Or from a `Buffer`:
317
+
318
+ ```js
319
+ const filePath = './test/my_image.png';
320
+ const bufferData = fs.readFileSync(filePath);
321
+
322
+ const result = await connection.createEventWithFileFromBuffer({
323
+ type: 'picture/attached',
324
+ streamIds: ['data']
325
+ }, bufferData, 'my_image.png' /* ← filename */);
326
+ ```
327
+
328
+ #### Browser
329
+
330
+ From an `<input>`:
331
+
332
+ ```html
333
+ <input type="file" id="file-upload"><button onClick='uploadFile()'>Save Value</button>
334
+
335
+ <script>
336
+ var formData = new FormData();
337
+ formData.append('file0', document.getElementById('create-file').files[0]) ;
338
+
339
+ connection.createEventWithFormData({
340
+ type: 'file/attached',
341
+ streamIds: ['test']
342
+ }, formData).then(function (res, err) {
343
+ // handle result
344
+ });
345
+ </script>
346
+ ```
347
+
348
+ Programmatically created content:
349
+
350
+ ```js
351
+ var formData = new FormData();
352
+ var blob = new Blob(['Hello'], { type: "text/txt" });
353
+ formData.append("file", blob);
354
+
355
+ connect.createEventWithFormData({
356
+ type: 'file/attached',
357
+ streamIds: ['data']
358
+ }, formData).then(function (res, err) {
359
+ // handle result
360
+ });
361
+
362
+ // Alternative with a filename
363
+
364
+ connect.createEventWithFileFromBuffer({
365
+ type: 'file/attached',
366
+ streamIds: ['data']
367
+ }, blob /* ← here we can directly use the blob*/, 'filename.txt').then(function (res, err) {
368
+ // handle result
369
+ });
370
+ ```
371
+
372
+
373
+ ### High Frequency (HF) events
374
+
375
+ [API reference](https://api.pryv.com/reference/#hf-events)
376
+
377
+ ```js
378
+ function generateSeries() {
379
+ const series = [];
380
+ for (let t = 0; t < 100000, t++) { // t will be the deltaTime in seconds
381
+ series.push([t, Math.sin(t/1000)]);
382
+ }
383
+ return series;
384
+ }
385
+ const pointsA = generateSeries();
386
+ const pointsB = generateSeries();
387
+
388
+ function postHFData(points) { // must return a Promise
389
+ return async function (result) { // will be called each time an HF event is created
390
+ return await connection.addPointsToHFEvent(result.event.id, ['deltaTime', 'value'], points);
391
+ }
392
+ }
393
+
394
+ const apiCalls = [
395
+ {
396
+ method: 'streams.create',
397
+ params: { id: 'signal1', name: 'Signal1' }
398
+ },
399
+ {
400
+ method: 'streams.create',
401
+ params: { id: 'signal2', name: 'Signal2' }
402
+ },
403
+ {
404
+ method: 'events.create',
405
+ params: { streamIds: ['signal1'], type: 'series:frequency/bpm' },
406
+ handleResult: postHFData(pointsA)
407
+ },
408
+ {
409
+ method: 'events.create',
410
+ params: { streamIds: ['signal2'], type: 'series:frequency/bpm' },
411
+ handleResult: postHFData(pointsB)
412
+ }
413
+ ];
414
+
415
+ try {
416
+ const result = await connection.api(apiCalls);
417
+ } catch (e) {
418
+ // handle error
419
+ }
420
+ ```
421
+
422
+
423
+ ### Service information and assets
424
+
425
+ Each Pryv.io platform is considered a "service"; for example **Pryv Lab**, which is deployed on the **pryv.me** domain.
426
+ It is described by a **service information** settings object (see the [service info API reference](https://api.pryv.com/reference/#service-info)).
427
+
428
+ `pryv.Service` exposes tools to interact with Pryv.io at the "platform" level.
429
+
430
+ #### Initializing with a service info URL
431
+
432
+ ```js
433
+ const service = new pryv.Service('https://reg.pryv.me/service/info');
434
+ ```
435
+
436
+ #### Initializing with a service info settings object
437
+
438
+ Service information properties can be overridden, which can be useful to test new designs on production platforms.
439
+
440
+ ```js
441
+ const serviceInfoUrl = 'https://reg.pryv.me/service/info';
442
+ const overrides = {
443
+ name: 'Pryv Lab 2',
444
+ assets: {
445
+ definitions: 'https://pryv.github.io/assets-pryv.me/index.json'
446
+ }
447
+ }
448
+ const service = new pryv.Service(serviceInfoUrl, overrides);
449
+ ```
450
+
451
+ #### Methods
452
+
453
+ - `service.info()` returns the service information in a Promise
454
+ ```js
455
+ // get the name of the platform
456
+ const serviceName = await service.info().name
457
+ ```
458
+ - `service.infoSync()` returns the cached service info; requires `service.info()` to be called beforehand
459
+ - `service.apiEndpointFor(username, token)` returns the corresponding API endpoint for the provided credentials (`token` is optional)
460
+
461
+
462
+ ### `pryv.Browser` & visual assets
463
+
464
+ #### Retrieving the service info from a query parameter
465
+
466
+ A single web app might need to run on different Pryv.io platforms (this is the case of most Pryv.io example apps).
467
+
468
+ The Pryv.io platform can be specified by passing the service information URL in a query parameter `pryvServiceInfoUrl` (as per the [Pryv app guidelines](https://api.pryv.com/guides/app-guidelines/)), which can be extracted with `pryv.Browser.serviceInfoFromUrl()`.
469
+
470
+ For example: `https://api.pryv.com/app-web-access/?pryvServiceInfoUrl=https://reg.pryv.me/service/info`
471
+
472
+ ```js
473
+ let defaultServiceInfoUrl = 'https://reg.pryv.me/service/info';
474
+ // if present, override serviceInfoURL from query param `pryvServiceInfoUrl`
475
+ serviceInfoUrl = pryv.Browser.serviceInfoFromUrl() || defaultServiceInfoUrl;
476
+
477
+ (async function () {
478
+ var service = await pryv.Auth.setupAuth(authSettings, serviceInfoUrl, serviceCustomizations);
479
+ })();
480
+ ```
481
+
482
+ #### Visual assets
483
+
484
+ To customize visual assets, please refer to the [pryv.me assets repository](https://github.com/pryv/assets-pryv.me). For example, see [how to customize the sign-in button](https://github.com/pryv/assets-pryv.me/tree/master/lib-js/).
485
+
486
+ `(await service.assets()).setAllDefaults()` loads the `css` and `favicon` properties of assets definitions:
487
+
488
+ ```js
489
+ (async function () {
490
+ const service = await pryv.Auth.setupAuth(authSettings, serviceInfoUrl);
491
+ (await service.assets()).setAllDefaults(); // will load the default favicon and CSS for this platform
492
+ })();
493
+ ```
494
+
495
+
496
+ ### Customize the authentication process
497
+
498
+ You can customize the authentication process ([API reference](https://api.pryv.com/reference/#authenticate-your-app)) at different levels:
499
+
500
+ - Using a custom login button
501
+ - Using a custom UI, including the flow of [app-web-auth3](https://github.com/pryv/app-web-auth3)
502
+
503
+ #### Using a custom login button
504
+
505
+ 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.
506
+
507
+ ##### Initialization
508
+
509
+ You should provide auth settings (see [obtaining a `pryv.Connection`](#within-a-webpage-with-a-login-button)) and an instance of [pryv.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.
510
+
511
+ ```js
512
+ constructor(authSettings, service) {
513
+ this.authSettings = authSettings;
514
+ this.service = service;
515
+ this.serviceInfo = service.infoSync();
516
+ }
517
+
518
+ async init () {
519
+ // initialize button visuals
520
+ // ...
521
+
522
+ // set cookie key for authorization data - browser only
523
+ this._cookieKey = 'pryv-libjs-' + this.authSettings.authRequest.requestingAppId;
524
+
525
+ // initialize controller
526
+ this.auth = new AuthController(this.authSettings, this.service, this);
527
+ await this.auth.init();
528
+ }
529
+ ```
530
+
531
+ ##### Authorization data
532
+
533
+ At initialization, the [AuthController](src/Auth/AuthController.js) will attempt to fetch persisted authorization credentials, using `LoginButton.getAuthorizationData()`. In the browser, we are using a client-side cookie. For other frameworks, use an appropriate secure storage.
534
+
535
+ ```js
536
+ getAuthorizationData () {
537
+ return Cookies.get(this._cookieKey);
538
+ }
539
+ ```
540
+
541
+ ##### Authentication lifecycle
542
+
543
+ The [authentication process](https://api.pryv.com/reference/#authenticate-your-app) implementation on the frontend can go through the following states:
544
+
545
+ 1. `LOADING`: while the visual assets are loading
546
+ 2. `INITIALIZED`: visuals assets are loaded, or when [polling](https://api.pryv.com/reference/#poll-request) concludes with **Result: Refused**
547
+ 3. `NEED_SIGNIN`: from the response of the [auth request](https://api.pryv.com/reference/#auth-request) through [polling](https://api.pryv.com/reference/#poll-request)
548
+ 4. `AUTHORIZED`: When [polling](https://api.pryv.com/reference/#poll-request) concludes with **Result: Accepted**
549
+ 5. `SIGNOUT`: when the user triggers a deletion of the client-side authorization credentials, usually by clicking the button after being signed in
550
+ 6. `ERROR`: see message for more information
551
+
552
+ You will need to provide a function to react depending on the state. The states `NEED_SIGNIN` and `AUTHORIZED` carry the same properties as the [auth process polling responses](https://api.pryv.com/reference/#poll-request). `LOADING`, `INITIALIZED` and `SIGNOUT` only have `status`. The `ERROR` state carries a `message` property.
553
+
554
+ ```js
555
+ async onStateChange (state) {
556
+ switch (state.status) {
557
+ case AuthStates.LOADING:
558
+ this.text = getLoadingMessage(this);
559
+ break;
560
+ case AuthStates.INITIALIZED:
561
+ this.text = getInitializedMessage(this, this.serviceInfo.name);
562
+ break;
563
+ case AuthStates.NEED_SIGNIN:
564
+ const loginUrl = state.authUrl || state.url; // .url is deprecated
565
+ if (this.authSettings.authRequest.returnURL) { // open on same page (no Popup)
566
+ location.href = loginUrl;
567
+ return;
568
+ } else {
569
+ startLoginScreen(this, loginUrl);
570
+ }
571
+ break;
572
+ case AuthStates.AUTHORIZED:
573
+ this.text = state.username;
574
+ this.saveAuthorizationData({
575
+ apiEndpoint: state.apiEndpoint,
576
+ username: state.username
577
+ });
578
+ break;
579
+ case AuthStates.SIGNOUT:
580
+ const message = this.messages.SIGNOUT_CONFIRM ? this.messages.SIGNOUT_CONFIRM : 'Logout ?';
581
+ if (confirm(message)) {
582
+ this.deleteAuthorizationData();
583
+ this.auth.init();
584
+ }
585
+ break;
586
+ case AuthStates.ERROR:
587
+ this.text = getErrorMessage(this, state.message);
588
+ break;
589
+ default:
590
+ console.log('WARNING Unhandled state for Login: ' + state.status);
591
+ }
592
+ if (this.loginButtonText) {
593
+ this.loginButtonText.innerHTML = this.text;
594
+ }
595
+ }
596
+ ```
597
+
598
+ ##### Button actions
599
+
600
+ The button actions should be handled by the [AuthController](src/Auth/AuthController.js) in the following way:
601
+
602
+ ```js
603
+ // LoginButton.js
604
+ onClick () {
605
+ this.auth.handleClick();
606
+ }
607
+ ```
608
+
609
+ ```js
610
+ // AuthController.js
611
+ async handleClick () {
612
+ if (isAuthorized.call(this)) {
613
+ this.state = { status: AuthStates.SIGNOUT };
614
+ } else if (isInitialized.call(this)) {
615
+ this.startAuthRequest();
616
+ } else if (isNeedSignIn.call(this)) {
617
+ // reopen popup
618
+ this.state = this.state;
619
+ } else {
620
+ console.log('Unhandled action in "handleClick()" for status:', this.state.status);
621
+ }
622
+ }
623
+ ```
624
+
625
+ ##### Custom button usage
626
+
627
+ You must then provide this class as follows:
628
+
629
+ ```js
630
+ let service = await pryv.Auth.setupAuth(
631
+ authSettings, // See https://github.com/pryv/lib-js#within-a-webpage-with-a-login-button
632
+ serviceInfoUrl,
633
+ serviceCustomizations,
634
+ MyLoginButton,
635
+ );
636
+ ```
637
+
638
+ You will find a working example [here](https://github.com/pryv/lib-js/blob/master/examples/custom-login-button.html), and try it running [there](https://api.pryv.com/lib-js/examples/custom-login-button.html). To run these examples locally, see below.
639
+
640
+ For a more advanced scenario, you can check the default button implementation in [`./src/Browser/LoginButton.js`](/src/Browser/LoginButton.js).
641
+
642
+ #### Redirect user to the authentication page
643
+
644
+ There is a possibility that you would like to register the user in another page. You can find an example [here](https://github.com/pryv/lib-js/blob/master/examples/auth-with-redirection.html), and try it running [there](https://api.pryv.com/lib-js/examples/auth-with-redirection.html). Again, to run these examples locally, see below.
645
+
646
+
647
+ ### Running examples locally
648
+
649
+ You can find HTML examples in the [`./examples`](https://github.com/pryv/lib-js/blob/master/examples) directory. You can run them in two ways:
650
+
651
+ 1. With [rec.la](https://github.com/pryv/rec.la), which allows to run local code with a valid SSL certificate (you must have run `just build` beforehand):
652
+ ```
653
+ just serve
654
+ ```
655
+ then open the desired example page (e.g. [https://l.rec.la:9443/examples/auth.html](https://l.rec.la:9443/examples/auth.html)
656
+ 2. As a simple HTML file, passing service information as JSON to avoid CORS issues
657
+
658
+
659
+ ## Contributing
660
+
661
+ ### Installation
662
+
663
+ Prerequisites: [Node.js](https://nodejs.org/en/download/) 16, [just](https://github.com/casey/just#installation)
664
+
665
+ Then:
666
+ 1. `just setup-dev-env`
667
+ 2. `just install` to install node modules
668
+ 3. `just build` for the initial webpack build
669
+
670
+ Running `just` with no argument displays the available commands (defined in `justfile`).
671
+
672
+ ### Dev environment basics
673
+
674
+ The project is structured as a monorepo with components (a.k.a. workspaces in NPM), each component defining its `package.json`, tests, etc. in `components/`:
675
+ - `pryv`: the library
676
+ - `pryv-socket.io`: Socket.IO add-on
677
+ - `pryv-monitor`: Monitor add-on
678
+
679
+ The code follows the [Semi-Standard](https://github.com/standard/semistandard) style.
680
+
681
+ ### Building for the browser
682
+
683
+ ```
684
+ just build[-watch]
685
+ ```
686
+ to build the library, add-ons and examples into `dist/`, and the browser tests into `test-browser/`
687
+
688
+ ### Testing
689
+
690
+ #### Node.js
691
+
692
+ ```
693
+ just test <component> [...params]
694
+ ```
695
+ - `component` is an existing component's name, or `all` to run tests on all components
696
+ - Extra parameters at the end are passed on to [Mocha](https://mochajs.org/) (default settings are defined in `.mocharc.js` files)
697
+ - Replace `test` with `test-debug`, `test-cover` for common presets
698
+
699
+ #### Browser
700
+
701
+ Assuming browser files have been built (see above):
702
+ ```
703
+ just test-browser
704
+ ```
705
+ to run the tests in a browser window.
706
+
707
+ - 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
708
+
709
+ ### Publishing
710
+
711
+ Assuming browser files are built and everything is up-to-date, including the READMEs and [changelog](https://github.com/pryv/lib-js/blob/master/CHANGELOG.md):
712
+
713
+ ```
714
+ just version <version>
715
+ ```
716
+ to update the version number of the lib and add-ons in lockstep, git commit and tag included
717
+
718
+ ```
719
+ just publish-npm
720
+ ```
721
+ to publish the new versions of the lib and add-ons to NPM
722
+
723
+ ```
724
+ just publish-browser
725
+ ```
726
+ to commit and push the `gh-pages` branch from `dist/`, publishing the browser files to be served via CDN on `api.pryv.com/lib-js`
727
+
728
+
729
+ ## [Changelog](CHANGELOG.md)
730
+
731
+
732
+ ## License
733
+
734
+ [BSD-3-Clause](https://github.com/pryv/lib-js/blob/master/LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pryv",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "Pryv JavaScript library",
5
5
  "keywords": [
6
6
  "Pryv",