pryv 2.4.7 → 3.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pryv",
3
- "version": "2.4.7",
3
+ "version": "3.0.0",
4
4
  "description": "Pryv JavaScript library",
5
5
  "keywords": [
6
6
  "Pryv",
@@ -18,7 +18,8 @@
18
18
  "author": "Pryv S.A. <info@pryv.com> (https://pryv.com)",
19
19
  "main": "src/index.js",
20
20
  "types": "src/index.d.ts",
21
- "dependencies": {
22
- "superagent": "^9.0.0"
21
+ "dependencies": {},
22
+ "engines": {
23
+ "node": ">=20.0.0"
23
24
  }
24
25
  }
@@ -7,13 +7,15 @@ const AuthStates = require('./AuthStates');
7
7
  const Messages = require('./LoginMessages');
8
8
 
9
9
  /**
10
- * @private
10
+ * Controller for authentication flow
11
+ * @memberof pryv.Auth
11
12
  */
12
13
  class AuthController {
13
14
  /**
14
- *
15
- * @param {*} settings
16
- * @param {*} service
15
+ * Create an AuthController
16
+ * @param {AuthSettings} settings - Authentication settings
17
+ * @param {Service} service - Pryv service instance
18
+ * @param {CustomLoginButton} loginButton - Login button implementation
17
19
  */
18
20
  constructor (settings, service, loginButton) {
19
21
  this.settings = settings;
@@ -50,9 +52,8 @@ class AuthController {
50
52
  }
51
53
 
52
54
  /**
53
- * async function to call right after instanciating object
54
- *
55
- * @returns {Service}
55
+ * Initialize the auth controller. Call this right after instantiation.
56
+ * @returns {Promise<Service>} Promise resolving to the Service instance
56
57
  */
57
58
  async init () {
58
59
  this.serviceInfo = this.service.infoSync();
@@ -73,6 +74,7 @@ class AuthController {
73
74
  }
74
75
 
75
76
  if (loginButton != null && loginButton.finishAuthProcessAfterRedirection != null) {
77
+ // @ts-ignore - this is a valid AuthController
76
78
  await loginButton.finishAuthProcessAfterRedirection(this);
77
79
  }
78
80
 
@@ -87,7 +89,8 @@ class AuthController {
87
89
  }
88
90
 
89
91
  /**
90
- * Triggered when button is pressed
92
+ * Handle button click - triggers appropriate action based on current state
93
+ * @returns {Promise<void>}
91
94
  */
92
95
  async handleClick () {
93
96
  if (isAuthorized.call(this)) {
@@ -113,11 +116,12 @@ class AuthController {
113
116
  }
114
117
 
115
118
  /**
116
- * Used only to retrieve returnUrl in browser environments
117
- *
118
- * @param {*} returnURL
119
- * @param {*} windowLocationForTest
120
- * @param {*} navigatorForTests
119
+ * Compute the return URL for authentication redirect.
120
+ * Used only in browser environments.
121
+ * @param {string} [returnURL] - The return URL setting ('auto#', 'self#', or custom URL)
122
+ * @param {string} [windowLocationForTest] - Mock window.location.href for testing
123
+ * @param {string|Navigator} [navigatorForTests] - Mock navigator for testing
124
+ * @returns {string|boolean} The computed return URL, or false if using popup mode
121
125
  */
122
126
  getReturnURL (
123
127
  returnURL,
@@ -154,17 +158,30 @@ class AuthController {
154
158
  }
155
159
  }
156
160
 
161
+ /**
162
+ * Start the authentication request and polling process
163
+ * @returns {Promise<void>}
164
+ * @see https://pryv.github.io/reference/#auth-request
165
+ */
157
166
  async startAuthRequest () {
167
+ // @ts-ignore - postAccess uses .call(this) for context
158
168
  this.state = await postAccess.call(this);
159
169
 
160
170
  await doPolling.call(this);
161
171
 
172
+ /** @this {AuthController} */
162
173
  async function postAccess () {
163
174
  try {
164
- const res = await utils.superagent
165
- .post(this.serviceInfo.access)
166
- .send(this.settings.authRequest);
167
- return res.body;
175
+ const { response, body } = await utils.fetchPost(
176
+ // @ts-ignore - this is bound via .call()
177
+ this.serviceInfo.access,
178
+ // @ts-ignore - this is bound via .call()
179
+ this.settings.authRequest
180
+ );
181
+ if (!response.ok) {
182
+ throw new Error('Access request failed: ' + JSON.stringify(body));
183
+ }
184
+ return body;
168
185
  } catch (e) {
169
186
  this.state = {
170
187
  status: AuthStates.ERROR,
@@ -175,31 +192,31 @@ class AuthController {
175
192
  }
176
193
  }
177
194
 
195
+ /** @this {AuthController} */
178
196
  async function doPolling () {
179
- if (this.state.status !== AuthStates.NEED_SIGNIN) {
197
+ // @ts-ignore - this is bound via .call()
198
+ if (this.state?.status !== AuthStates.NEED_SIGNIN) {
180
199
  return;
181
200
  }
182
- const pollResponse = await pollAccess(this.state.poll);
201
+ // @ts-ignore - this is bound via .call()
202
+ const pollResponse = await pollAccess(this.state?.poll);
183
203
 
184
204
  if (pollResponse.status === AuthStates.NEED_SIGNIN) {
185
- setTimeout(await doPolling.bind(this), this.state.poll_rate_ms);
205
+ // @ts-ignore - this is bound via .call()
206
+ setTimeout(await doPolling.bind(this), this.state?.poll_rate_ms);
186
207
  } else {
187
208
  this.state = pollResponse;
188
209
  }
189
210
 
190
211
  async function pollAccess (pollUrl) {
191
212
  try {
192
- const res = await utils.superagent.get(pollUrl);
193
- return res.body;
194
- } catch (e) {
195
- if (e.response &&
196
- e.response.status === 403 &&
197
- e.response.body &&
198
- e.response.body.status === 'REFUSED') {
213
+ const { response, body } = await utils.fetchGet(pollUrl);
214
+ if (response.status === 403 && body?.status === 'REFUSED') {
199
215
  return { status: AuthStates.INITIALIZED };
200
- } else {
201
- return { status: AuthStates.ERROR, message: 'Error while polling for auth request', error: e };
202
216
  }
217
+ return body;
218
+ } catch (e) {
219
+ return { status: AuthStates.ERROR, message: 'Error while polling for auth request', error: e };
203
220
  }
204
221
  }
205
222
  }
package/src/Auth/index.js CHANGED
@@ -29,11 +29,11 @@ module.exports = {
29
29
  * @param {string | boolean} settings.authRequest.returnURL : false, // set this if you don't want a popup
30
30
  * @param {string} [settings.authRequest.referer] To track registration source
31
31
  * @param {string} settings.spanButtonID set and <span> id in DOM to insert default login button or null for custom
32
- * @param {Browser.AuthStateChangeHandler} settings.onStateChange
33
- * @param {string} [settings.returnURL=auto#] Set to "self#" to disable popup and force using the same page. Set a custom url when process is finished (specific use cases). Should always end by # ? or &
32
+ * @param {Function} settings.onStateChange
33
+ * @param {string} [settings.returnURL] Set to "self#" to disable popup and force using the same page
34
34
  * @param {string} serviceInfoUrl
35
35
  * @param {Object} [serviceCustomizations] override properties of serviceInfoUrl
36
- * @returns {pryv.Service}
36
+ * @returns {Promise<Service>}
37
37
  */
38
38
  async function setupAuth (settings, serviceInfoUrl, serviceCustomizations, HumanInteraction = LoginButton) {
39
39
  const service = new Service(serviceInfoUrl, serviceCustomizations);
@@ -18,9 +18,10 @@ module.exports = {
18
18
  /**
19
19
  * Set a local cookie
20
20
  * @memberof pryv.Browser.CookieUtils
21
+ * @template T
21
22
  * @param {string} cookieKey - The key for the cookie
22
- * @param {mixed} value - The Value
23
- * @param {number} expireInDays - Expiration date in days from now
23
+ * @param {T} value - The value (will be JSON stringified)
24
+ * @param {number} [expireInDays=365] - Expiration date in days from now
24
25
  */
25
26
  function set (cookieKey, value, expireInDays) {
26
27
  if (!utils.isBrowser()) return;
@@ -31,7 +32,7 @@ function set (cookieKey, value, expireInDays) {
31
32
  myDate.setDate(myDate.getDate() + expireInDays);
32
33
  let cookieStr = encodeURIComponent(cookieKey) + '=' +
33
34
  encodeURIComponent(JSON.stringify(value)) +
34
- ';expires=' + myDate.toGMTString() +
35
+ ';expires=' + myDate.toUTCString() +
35
36
  ';domain=.' + hostName + ';path=' + path;
36
37
  // do not add SameSite when removing a cookie
37
38
  if (expireInDays >= 0) cookieStr += ';SameSite=Strict';
@@ -41,7 +42,9 @@ function set (cookieKey, value, expireInDays) {
41
42
  /**
42
43
  * Return the value of a local cookie
43
44
  * @memberof pryv.Browser.CookieUtils
44
- * @param cookieKey - The key
45
+ * @template T
46
+ * @param {string} cookieKey - The key
47
+ * @returns {T|undefined} The parsed cookie value or undefined if not found
45
48
  */
46
49
  function get (cookieKey) {
47
50
  const name = encodeURIComponent(cookieKey);
@@ -54,7 +57,7 @@ function get (cookieKey) {
54
57
  /**
55
58
  * Delete a local cookie
56
59
  * @memberof pryv.Browser.CookieUtils
57
- * @param cookieKey - The key
60
+ * @param {string} cookieKey - The key
58
61
  */
59
62
  function del (cookieKey) {
60
63
  set(cookieKey, { deleted: true }, -1);
@@ -28,6 +28,7 @@ class LoginButton {
28
28
  setupButton(this);
29
29
  this.languageCode = this.authSettings.authRequest.languageCode || 'en';
30
30
  this.messages = Messages(this.languageCode);
31
+ // @ts-ignore - loginButtonText is set by setupButton
31
32
  if (this.loginButtonText) {
32
33
  await loadAssets(this);
33
34
  }
@@ -84,7 +85,9 @@ class LoginButton {
84
85
  default:
85
86
  console.log('WARNING Unhandled state for Login: ' + state.status);
86
87
  }
88
+ // @ts-ignore - loginButtonText is set by setupButton
87
89
  if (this.loginButtonText) {
90
+ // @ts-ignore
88
91
  this.loginButtonText.innerHTML = this.text;
89
92
  }
90
93
  }
@@ -114,8 +117,8 @@ class LoginButton {
114
117
  const pollUrl = retrievePollUrl(url);
115
118
  if (pollUrl !== null) {
116
119
  try {
117
- const res = await utils.superagent.get(pollUrl);
118
- authController.state = res.body;
120
+ const { body } = await utils.fetchGet(pollUrl);
121
+ authController.state = body;
119
122
  } catch (e) {
120
123
  authController.state = {
121
124
  status: AuthStates.ERROR,
@@ -148,8 +151,8 @@ async function startLoginScreen (loginButton, authUrl) {
148
151
  const outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
149
152
  const width = 400;
150
153
  const height = 620;
151
- const left = parseInt(screenX + ((outerWidth - width) / 2), 10);
152
- const top = parseInt(screenY + ((outerHeight - height) / 2.5), 10);
154
+ const left = Math.floor(screenX + ((outerWidth - width) / 2));
155
+ const top = Math.floor(screenY + ((outerHeight - height) / 2.5));
153
156
  const features = (
154
157
  'width=' + width +
155
158
  ',height=' + height +