cozy-client 58.2.0 → 58.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.
@@ -3143,7 +3143,7 @@ var CozyClient = /*#__PURE__*/function () {
3143
3143
  CozyClient.hooks = CozyClient.hooks || {};
3144
3144
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
3145
3145
 
3146
- CozyClient.version = "58.2.0";
3146
+ CozyClient.version = "58.3.0";
3147
3147
 
3148
3148
  _microee.default.mixin(CozyClient);
3149
3149
 
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "ensureFirstSlash", {
27
27
  return _urlHelper.ensureFirstSlash;
28
28
  }
29
29
  });
30
+ Object.defineProperty(exports, "fetchRegistrationDetails", {
31
+ enumerable: true,
32
+ get: function get() {
33
+ return _urlHelper.fetchRegistrationDetails;
34
+ }
35
+ });
30
36
  Object.defineProperty(exports, "rootCozyUrl", {
31
37
  enumerable: true,
32
38
  get: function get() {
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.rootCozyUrl = exports.InvalidCozyUrlError = exports.BlockedCozyError = exports.InvalidProtocolError = exports.InvalidRedirectLinkError = exports.deconstructRedirectLink = exports.deconstructCozyWebLinkWithSlug = exports.generateWebLink = exports.ensureFirstSlash = void 0;
8
+ exports.fetchRegistrationDetails = exports.rootCozyUrl = exports.InvalidCozyUrlError = exports.BlockedCozyError = exports.InvalidProtocolError = exports.InvalidRedirectLinkError = exports.deconstructRedirectLink = exports.deconstructCozyWebLinkWithSlug = exports.generateWebLink = exports.ensureFirstSlash = void 0;
9
9
 
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
11
 
@@ -263,7 +263,7 @@ var uri = function uri(_ref2) {
263
263
  port = _ref2.port;
264
264
  return (protocol !== '' ? "".concat(protocol, "//") : 'https://') + hostname + (port !== '' ? ":".concat(port) : '');
265
265
  };
266
- /* wellKnownUrl - Returns a valid URL string to a Well Known password change page
266
+ /* publicPreloginUrl - Returns a valid URL string to the /public/prelogin API endpoint
267
267
  *
268
268
  * The built URL will point to the origin generated from the given protocol,
269
269
  * hostname and port.
@@ -277,8 +277,8 @@ var uri = function uri(_ref2) {
277
277
  */
278
278
 
279
279
 
280
- var wellKnownUrl = function wellKnownUrl(url) {
281
- return uri(url) + '/.well-known/change-password';
280
+ var publicPreloginUrl = function publicPreloginUrl(url) {
281
+ return uri(url) + '/public/prelogin';
282
282
  };
283
283
  /* isValidOrigin - Checks whether a given URL is a valid Cozy origin
284
284
  *
@@ -307,13 +307,13 @@ var wellKnownUrl = function wellKnownUrl(url) {
307
307
 
308
308
  var isValidOrigin = /*#__PURE__*/function () {
309
309
  var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(url) {
310
- var response, status, responseUri, wasRedirected;
310
+ var response, status, responseUri, wasRedirected, contentType;
311
311
  return _regenerator.default.wrap(function _callee$(_context) {
312
312
  while (1) {
313
313
  switch (_context.prev = _context.next) {
314
314
  case 0:
315
315
  _context.next = 2;
316
- return fetch(wellKnownUrl(url));
316
+ return fetch(publicPreloginUrl(url));
317
317
 
318
318
  case 2:
319
319
  response = _context.sent;
@@ -339,10 +339,37 @@ var isValidOrigin = /*#__PURE__*/function () {
339
339
  throw new BlockedCozyError(url);
340
340
 
341
341
  case 10:
342
- wasRedirected = url.origin !== new URL(responseUri).origin;
343
- return _context.abrupt("return", status === 200 && !wasRedirected);
342
+ if (!(status !== 200)) {
343
+ _context.next = 12;
344
+ break;
345
+ }
346
+
347
+ return _context.abrupt("return");
344
348
 
345
349
  case 12:
350
+ wasRedirected = responseUri && url.origin !== new URL(responseUri).origin;
351
+
352
+ if (!wasRedirected) {
353
+ _context.next = 15;
354
+ break;
355
+ }
356
+
357
+ return _context.abrupt("return", false);
358
+
359
+ case 15:
360
+ contentType = response.headers.get('content-type');
361
+
362
+ if (!(!contentType || contentType.indexOf('application/json') === -1)) {
363
+ _context.next = 18;
364
+ break;
365
+ }
366
+
367
+ return _context.abrupt("return", false);
368
+
369
+ case 18:
370
+ return _context.abrupt("return", response.json());
371
+
372
+ case 19:
346
373
  case "end":
347
374
  return _context.stop();
348
375
  }
@@ -399,83 +426,19 @@ var isValidOrigin = /*#__PURE__*/function () {
399
426
 
400
427
  var rootCozyUrl = /*#__PURE__*/function () {
401
428
  var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(url) {
402
- var _url$hostname$split, _url$hostname$split2, subDomain, domain, _hostname, noSlugUrl, hostname, noSubUrl;
403
-
429
+ var detail;
404
430
  return _regenerator.default.wrap(function _callee2$(_context2) {
405
431
  while (1) {
406
432
  switch (_context2.prev = _context2.next) {
407
433
  case 0:
408
- if (['http:', 'https:'].includes(url.protocol)) {
409
- _context2.next = 2;
410
- break;
411
- }
412
-
413
- throw new InvalidProtocolError(url);
434
+ _context2.next = 2;
435
+ return fetchRegistrationDetails(url);
414
436
 
415
437
  case 2:
416
- _context2.next = 4;
417
- return isValidOrigin(url);
438
+ detail = _context2.sent;
439
+ return _context2.abrupt("return", detail.rootUrl);
418
440
 
419
441
  case 4:
420
- if (!_context2.sent) {
421
- _context2.next = 6;
422
- break;
423
- }
424
-
425
- return _context2.abrupt("return", new URL(uri({
426
- protocol: url.protocol,
427
- hostname: url.hostname,
428
- port: url.port
429
- })));
430
-
431
- case 6:
432
- if (!/^[^.-][^.]+-[^.-]+\./.test(url.hostname)) {
433
- _context2.next = 14;
434
- break;
435
- }
436
-
437
- _url$hostname$split = url.hostname.split('.'), _url$hostname$split2 = (0, _toArray2.default)(_url$hostname$split), subDomain = _url$hostname$split2[0], domain = _url$hostname$split2.slice(1);
438
- _hostname = [subDomain.replace(/-.+/, '')].concat((0, _toConsumableArray2.default)(domain)).join('.');
439
- noSlugUrl = new URL(uri({
440
- protocol: url.protocol,
441
- hostname: _hostname,
442
- port: url.port
443
- }));
444
- _context2.next = 12;
445
- return isValidOrigin(noSlugUrl);
446
-
447
- case 12:
448
- if (!_context2.sent) {
449
- _context2.next = 14;
450
- break;
451
- }
452
-
453
- return _context2.abrupt("return", noSlugUrl);
454
-
455
- case 14:
456
- // Try to remove the first sub-domain in case its a nested app name
457
- // eslint-disable-next-line no-unused-vars
458
- hostname = url.hostname.split('.').splice(1).join('.');
459
- noSubUrl = new URL(uri({
460
- protocol: url.protocol,
461
- hostname: hostname,
462
- port: url.port
463
- }));
464
- _context2.next = 18;
465
- return isValidOrigin(noSubUrl);
466
-
467
- case 18:
468
- if (!_context2.sent) {
469
- _context2.next = 20;
470
- break;
471
- }
472
-
473
- return _context2.abrupt("return", noSubUrl);
474
-
475
- case 20:
476
- throw new InvalidCozyUrlError(url);
477
-
478
- case 21:
479
442
  case "end":
480
443
  return _context2.stop();
481
444
  }
@@ -545,4 +508,188 @@ var isResponseAboutBlockedCozy = /*#__PURE__*/function () {
545
508
  return function isResponseAboutBlockedCozy(_x3) {
546
509
  return _ref5.apply(this, arguments);
547
510
  };
548
- }();
511
+ }();
512
+ /**
513
+ * Check if the given url uses the expected protocols (http or https). Throws otherwise
514
+ *
515
+ * @param {URL} url - URL to validate
516
+ */
517
+
518
+
519
+ var throwIfInvalidProtocol = function throwIfInvalidProtocol(url) {
520
+ if (!['http:', 'https:'].includes(url.protocol)) {
521
+ throw new InvalidProtocolError(url);
522
+ }
523
+ };
524
+
525
+ var mayHaveSlug = function mayHaveSlug(url) {
526
+ return /^[^.-][^.]+-[^.-]+\./.test(url.hostname);
527
+ };
528
+
529
+ var removeSlug = function removeSlug(url) {
530
+ var _url$hostname$split = url.hostname.split('.'),
531
+ _url$hostname$split2 = (0, _toArray2.default)(_url$hostname$split),
532
+ subDomain = _url$hostname$split2[0],
533
+ domain = _url$hostname$split2.slice(1);
534
+
535
+ var hostname = [subDomain.replace(/-.+/, '')].concat((0, _toConsumableArray2.default)(domain)).join('.');
536
+ var noSlugUrl = new URL(uri({
537
+ protocol: url.protocol,
538
+ hostname: hostname,
539
+ port: url.port
540
+ }));
541
+ return noSlugUrl;
542
+ };
543
+
544
+ var removeSubdomain = function removeSubdomain(url) {
545
+ var hostname = url.hostname.split('.').splice(1).join('.');
546
+ var noSubUrl = new URL(uri({
547
+ protocol: url.protocol,
548
+ hostname: hostname,
549
+ port: url.port
550
+ }));
551
+ return noSubUrl;
552
+ };
553
+ /**
554
+ * @typedef {object} RegistrationDetails
555
+ * @property {URL} rootUrl - The Cozy's root URL
556
+ * @property {boolean} isOIDC - True if the Cozy's uses OIDC for login
557
+ */
558
+
559
+ /**
560
+ * registrationDetails - Get the root URL and prelogin info of a Cozy from more
561
+ * precise ones
562
+ *
563
+ * The goal is to allow users to use any URL copied from their browser as their
564
+ * Cozy URL rather than trying to explain to them what we expect (e.g. when
565
+ * requesting the Cozy URL to connect an app).
566
+ * If we can't get the root URL either because there's no Cozy or the domain
567
+ * does not exist or anything else, we'll throw an InvalidCozyUrlError.
568
+ * Also, since we communicate only via HTTP or HTTPS, we'll throw an
569
+ * InvalidProtocolError if any other protocol is used.
570
+ *
571
+ * This function expects a fully qualified URL thus with a protocol and a valid
572
+ * hostname. If your application accepts Cozy intances as input (e.g. `claude`
573
+ * when the Cozy can be found at `https://claude.mycozy.cloud`), it is your
574
+ * responsibility to add the appropriate domain to the hostname before calling
575
+ * this function.
576
+ *
577
+ * Examples:
578
+ *
579
+ * 1. getting the root URL when your user gives you its instance name
580
+ *
581
+ * const userInput = 'claude'
582
+ * const details = await fetchRegistrationDetails(new URL(`https://${userInput}.mycozy.cloud`))
583
+ * // → returns { rootUrl: new URL('https://claude.mycozy.cloud'), isOIDC: false }
584
+ *
585
+ * 2. getting the root URL when your user gives you a Cozy Drive URL
586
+ *
587
+ * const userInput = 'https://claude-drive.mycozy.cloud/#/folder/io.cozy.files.root-dir'
588
+ * const rootUrl = await fetchRegistrationDetails(new URL(userInput))
589
+ * // → returns { rootUrl: new URL('https://claude.mycozy.cloud'), isOIDC: false }
590
+ *
591
+ * 3. getting the root URL when the Cozy uses nested sub-domains
592
+ *
593
+ * const userInput = 'http://photos.camille.nimbus.com:8080/#/album/1234567890'
594
+ * const rootCozyUrl = await fetchRegistrationDetails(new URL(userInput))
595
+ * // → returns { rootUrl: new URL('http://camille.nimbus.com:8080'), isOIDC: false }
596
+ *
597
+ * 4. getting the root URL when your user gives you an instance from OIDC partners
598
+ *
599
+ * const details = await fetchRegistrationDetails(new URL(`https://alice.someoidcpartener.com`))
600
+ * // → returns { rootUrl: new URL('https://alice.someoidcpartener.com'), isOIDC: true }
601
+ *
602
+ * @param {URL} url The URL from which we'll try to get the root Cozy URL
603
+ *
604
+ * @returns {Promise<RegistrationDetails>} The root Cozy URL
605
+ */
606
+
607
+
608
+ var fetchRegistrationDetails = /*#__PURE__*/function () {
609
+ var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(url) {
610
+ var preloginData, noSlugUrl, noSlugPreloginData, noSubUrl, noSubPreloginData;
611
+ return _regenerator.default.wrap(function _callee4$(_context4) {
612
+ while (1) {
613
+ switch (_context4.prev = _context4.next) {
614
+ case 0:
615
+ throwIfInvalidProtocol(url);
616
+ _context4.next = 3;
617
+ return isValidOrigin(url);
618
+
619
+ case 3:
620
+ preloginData = _context4.sent;
621
+
622
+ if (!preloginData) {
623
+ _context4.next = 6;
624
+ break;
625
+ }
626
+
627
+ return _context4.abrupt("return", {
628
+ rootUrl: new URL(uri({
629
+ protocol: url.protocol,
630
+ hostname: url.hostname,
631
+ port: url.port
632
+ })),
633
+ isOIDC: preloginData.OIDC
634
+ });
635
+
636
+ case 6:
637
+ if (!mayHaveSlug(url)) {
638
+ _context4.next = 13;
639
+ break;
640
+ }
641
+
642
+ noSlugUrl = removeSlug(url);
643
+ _context4.next = 10;
644
+ return isValidOrigin(noSlugUrl);
645
+
646
+ case 10:
647
+ noSlugPreloginData = _context4.sent;
648
+
649
+ if (!noSlugPreloginData) {
650
+ _context4.next = 13;
651
+ break;
652
+ }
653
+
654
+ return _context4.abrupt("return", {
655
+ rootUrl: noSlugUrl,
656
+ isOIDC: noSlugPreloginData.OIDC
657
+ });
658
+
659
+ case 13:
660
+ // Try to remove the first sub-domain in case its a nested app name
661
+ // eslint-disable-next-line no-unused-vars
662
+ noSubUrl = removeSubdomain(url);
663
+ _context4.next = 16;
664
+ return isValidOrigin(noSubUrl);
665
+
666
+ case 16:
667
+ noSubPreloginData = _context4.sent;
668
+
669
+ if (!noSubPreloginData) {
670
+ _context4.next = 19;
671
+ break;
672
+ }
673
+
674
+ return _context4.abrupt("return", {
675
+ rootUrl: noSubUrl,
676
+ isOIDC: noSubPreloginData.OIDC
677
+ });
678
+
679
+ case 19:
680
+ throw new InvalidCozyUrlError(url);
681
+
682
+ case 20:
683
+ case "end":
684
+ return _context4.stop();
685
+ }
686
+ }
687
+ }, _callee4);
688
+ }));
689
+
690
+ return function fetchRegistrationDetails(_x4) {
691
+ return _ref6.apply(this, arguments);
692
+ };
693
+ }();
694
+
695
+ exports.fetchRegistrationDetails = fetchRegistrationDetails;
@@ -4,6 +4,7 @@ import {
4
4
  deconstructCozyWebLinkWithSlug,
5
5
  deconstructRedirectLink,
6
6
  generateWebLink,
7
+ fetchRegistrationDetails,
7
8
  rootCozyUrl,
8
9
  InvalidRedirectLinkError,
9
10
  InvalidCozyUrlError,
@@ -203,11 +204,14 @@ describe('rootCozyUrl', () => {
203
204
 
204
205
  it('should handle cozy-hosted https', async () => {
205
206
  fetch.mockOnceIf(
206
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
207
- {},
207
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
208
+ fakeCozyPrelogin(),
208
209
  {
209
210
  status: 200,
210
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
211
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
212
+ headers: {
213
+ 'content-type': 'application/json'
214
+ }
211
215
  }
212
216
  )
213
217
 
@@ -218,11 +222,14 @@ describe('rootCozyUrl', () => {
218
222
 
219
223
  it('should handle cozy-hosted https trailing slash', async () => {
220
224
  fetch.mockOnceIf(
221
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
222
- {},
225
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
226
+ fakeCozyPrelogin(),
223
227
  {
224
228
  status: 200,
225
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
229
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
230
+ headers: {
231
+ 'content-type': 'application/json'
232
+ }
226
233
  }
227
234
  )
228
235
 
@@ -233,11 +240,14 @@ describe('rootCozyUrl', () => {
233
240
 
234
241
  it('should handle cozy-hosted https trailing path', async () => {
235
242
  fetch.mockOnceIf(
236
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
237
- {},
243
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
244
+ fakeCozyPrelogin(),
238
245
  {
239
246
  status: 200,
240
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
247
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
248
+ headers: {
249
+ 'content-type': 'application/json'
250
+ }
241
251
  }
242
252
  )
243
253
 
@@ -248,20 +258,22 @@ describe('rootCozyUrl', () => {
248
258
 
249
259
  it('should handle cozy-hosted drive web app url', async () => {
250
260
  fetch.mockOnceIf(
251
- 'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password',
261
+ 'https://camillenimbus-drive.mycozy.cloud/public/prelogin',
252
262
  {},
253
263
  {
254
264
  status: 401,
255
- url:
256
- 'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password'
265
+ url: 'https://camillenimbus-drive.mycozy.cloud/public/prelogin'
257
266
  }
258
267
  )
259
268
  fetch.mockOnceIf(
260
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
261
- {},
269
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
270
+ fakeCozyPrelogin(),
262
271
  {
263
272
  status: 200,
264
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
273
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
274
+ headers: {
275
+ 'content-type': 'application/json'
276
+ }
265
277
  }
266
278
  )
267
279
 
@@ -272,20 +284,22 @@ describe('rootCozyUrl', () => {
272
284
 
273
285
  it('should handle cozy-hosted photos album url', async () => {
274
286
  fetch.mockOnceIf(
275
- 'https://camillenimbus-photos.mycozy.cloud/.well-known/change-password',
287
+ 'https://camillenimbus-photos.mycozy.cloud/public/prelogin',
276
288
  {},
277
289
  {
278
290
  status: 401,
279
- url:
280
- 'https://camillenimbus-photos.mycozy.cloud/.well-known/change-password'
291
+ url: 'https://camillenimbus-photos.mycozy.cloud/public/prelogin'
281
292
  }
282
293
  )
283
294
  fetch.mockOnceIf(
284
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
285
- {},
295
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
296
+ fakeCozyPrelogin(),
286
297
  {
287
298
  status: 200,
288
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
299
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
300
+ headers: {
301
+ 'content-type': 'application/json'
302
+ }
289
303
  }
290
304
  )
291
305
 
@@ -300,20 +314,22 @@ describe('rootCozyUrl', () => {
300
314
 
301
315
  it('should handle cozy-hosted app name', async () => {
302
316
  fetch.mockOnceIf(
303
- 'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password',
317
+ 'https://camillenimbus-drive.mycozy.cloud/public/prelogin',
304
318
  {},
305
319
  {
306
320
  status: 401,
307
- url:
308
- 'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password'
321
+ url: 'https://camillenimbus-drive.mycozy.cloud/public/prelogin'
309
322
  }
310
323
  )
311
324
  fetch.mockOnceIf(
312
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
313
- {},
325
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
326
+ fakeCozyPrelogin(),
314
327
  {
315
328
  status: 200,
316
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
329
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
330
+ headers: {
331
+ 'content-type': 'application/json'
332
+ }
317
333
  }
318
334
  )
319
335
 
@@ -327,7 +343,7 @@ describe('rootCozyUrl', () => {
327
343
  // `onboarding`) to the Home app (via the login page if the user is not
328
344
  // logged in).
329
345
  fetch.mockOnceIf(
330
- 'https://camillenimbus-onboarding.mycozy.cloud/.well-known/change-password',
346
+ 'https://camillenimbus-onboarding.mycozy.cloud/public/prelogin',
331
347
  {},
332
348
  {
333
349
  status: 200,
@@ -336,11 +352,14 @@ describe('rootCozyUrl', () => {
336
352
  }
337
353
  )
338
354
  fetch.mockOnceIf(
339
- 'https://camillenimbus.mycozy.cloud/.well-known/change-password',
340
- {},
355
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
356
+ fakeCozyPrelogin(),
341
357
  {
342
358
  status: 200,
343
- url: 'https://camillenimbus.mycozy.cloud/.well-known/change-password'
359
+ url: 'https://camillenimbus.mycozy.cloud/public/prelogin',
360
+ headers: {
361
+ 'content-type': 'application/json'
362
+ }
344
363
  }
345
364
  )
346
365
 
@@ -351,11 +370,14 @@ describe('rootCozyUrl', () => {
351
370
 
352
371
  it('should handle self-hosted https', async () => {
353
372
  fetch.mockOnceIf(
354
- 'https://camillenimbus.com/.well-known/change-password',
355
- {},
373
+ 'https://camillenimbus.com/public/prelogin',
374
+ fakeCozyPrelogin(),
356
375
  {
357
376
  status: 200,
358
- url: 'https://camillenimbus.com/.well-known/change-password'
377
+ url: 'https://camillenimbus.com/public/prelogin',
378
+ headers: {
379
+ 'content-type': 'application/json'
380
+ }
359
381
  }
360
382
  )
361
383
 
@@ -366,11 +388,14 @@ describe('rootCozyUrl', () => {
366
388
 
367
389
  it('should handle self-hosted with dash', async () => {
368
390
  fetch.mockOnceIf(
369
- 'https://camille-nimbus.com/.well-known/change-password',
370
- {},
391
+ 'https://camille-nimbus.com/public/prelogin',
392
+ fakeCozyPrelogin(),
371
393
  {
372
394
  status: 200,
373
- url: 'https://camille-nimbus.com/.well-known/change-password'
395
+ url: 'https://camille-nimbus.com/public/prelogin',
396
+ headers: {
397
+ 'content-type': 'application/json'
398
+ }
374
399
  }
375
400
  )
376
401
 
@@ -381,11 +406,14 @@ describe('rootCozyUrl', () => {
381
406
 
382
407
  it('should handle self-hosted http', async () => {
383
408
  fetch.mockOnceIf(
384
- 'http://camille-nimbus.com/.well-known/change-password',
385
- {},
409
+ 'http://camille-nimbus.com/public/prelogin',
410
+ fakeCozyPrelogin(),
386
411
  {
387
412
  status: 200,
388
- url: 'http://camille-nimbus.com/.well-known/change-password'
413
+ url: 'http://camille-nimbus.com/public/prelogin',
414
+ headers: {
415
+ 'content-type': 'application/json'
416
+ }
389
417
  }
390
418
  )
391
419
 
@@ -396,11 +424,14 @@ describe('rootCozyUrl', () => {
396
424
 
397
425
  it('should handle self-hosted https with port', async () => {
398
426
  fetch.mockOnceIf(
399
- 'https://camillenimbus.com:666/.well-known/change-password',
400
- {},
427
+ 'https://camillenimbus.com:666/public/prelogin',
428
+ fakeCozyPrelogin(),
401
429
  {
402
430
  status: 200,
403
- url: 'https://camillenimbus.com:666/.well-known/change-password'
431
+ url: 'https://camillenimbus.com:666/public/prelogin',
432
+ headers: {
433
+ 'content-type': 'application/json'
434
+ }
404
435
  }
405
436
  )
406
437
 
@@ -411,19 +442,22 @@ describe('rootCozyUrl', () => {
411
442
 
412
443
  it('should handle self-hosted nested drive web app url', async () => {
413
444
  fetch.mockOnceIf(
414
- 'https://drive.camillenimbus.com/.well-known/change-password',
445
+ 'https://drive.camillenimbus.com/public/prelogin',
415
446
  {},
416
447
  {
417
448
  status: 401,
418
- url: 'https://drive.camillenimbus.com/.well-known/change-password'
449
+ url: 'https://drive.camillenimbus.com/public/prelogin'
419
450
  }
420
451
  )
421
452
  fetch.mockOnceIf(
422
- 'https://camillenimbus.com/.well-known/change-password',
423
- {},
453
+ 'https://camillenimbus.com/public/prelogin',
454
+ fakeCozyPrelogin(),
424
455
  {
425
456
  status: 200,
426
- url: 'https://camillenimbus.com/.well-known/change-password'
457
+ url: 'https://camillenimbus.com/public/prelogin',
458
+ headers: {
459
+ 'content-type': 'application/json'
460
+ }
427
461
  }
428
462
  )
429
463
 
@@ -434,19 +468,22 @@ describe('rootCozyUrl', () => {
434
468
 
435
469
  it('should handle self-hosted flat drive web app url', async () => {
436
470
  fetch.mockOnceIf(
437
- 'https://camille-drive.nimbus.com/.well-known/change-password',
471
+ 'https://camille-drive.nimbus.com/public/prelogin',
438
472
  {},
439
473
  {
440
474
  status: 401,
441
- url: 'https://camille-drive.nimbus.com/.well-known/change-password'
475
+ url: 'https://camille-drive.nimbus.com/public/prelogin'
442
476
  }
443
477
  )
444
478
  fetch.mockOnceIf(
445
- 'https://camille.nimbus.com/.well-known/change-password',
446
- {},
479
+ 'https://camille.nimbus.com/public/prelogin',
480
+ fakeCozyPrelogin(),
447
481
  {
448
482
  status: 200,
449
- url: 'https://camille.nimbus.com/.well-known/change-password'
483
+ url: 'https://camille.nimbus.com/public/prelogin',
484
+ headers: {
485
+ 'content-type': 'application/json'
486
+ }
450
487
  }
451
488
  )
452
489
 
@@ -457,11 +494,14 @@ describe('rootCozyUrl', () => {
457
494
 
458
495
  it('should handle cozy.localhost', async () => {
459
496
  fetch.mockOnceIf(
460
- 'http://cozy.localhost:8080/.well-known/change-password',
461
- {},
497
+ 'http://cozy.localhost:8080/public/prelogin',
498
+ fakeCozyPrelogin(),
462
499
  {
463
500
  status: 200,
464
- url: 'http://cozy.localhost:8080/.well-known/change-password'
501
+ url: 'http://cozy.localhost:8080/public/prelogin',
502
+ headers: {
503
+ 'content-type': 'application/json'
504
+ }
465
505
  }
466
506
  )
467
507
  await expect(
@@ -471,11 +511,11 @@ describe('rootCozyUrl', () => {
471
511
 
472
512
  it('expects an http or https protocol', async () => {
473
513
  fetch.mockOnceIf(
474
- 'ftp://camillenimbus.com/.well-known/change-password',
514
+ 'ftp://camillenimbus.com/public/prelogin',
475
515
  {},
476
516
  {
477
517
  status: 200,
478
- url: 'ftp://camillenimbus.com/.well-known/change-password'
518
+ url: 'ftp://camillenimbus.com/public/prelogin'
479
519
  }
480
520
  )
481
521
 
@@ -486,11 +526,11 @@ describe('rootCozyUrl', () => {
486
526
 
487
527
  it('rejects if URL points to a valid cozy-stack but no valid Cozy instance', async () => {
488
528
  fetch.mockOnceIf(
489
- 'https://missing.mycozy.cloud/.well-known/change-password',
529
+ 'https://missing.mycozy.cloud/public/prelogin',
490
530
  {},
491
531
  {
492
532
  status: 404,
493
- url: 'https://missing.mycozy.cloud/.well-known/change-password'
533
+ url: 'https://missing.mycozy.cloud/public/prelogin'
494
534
  }
495
535
  )
496
536
 
@@ -518,7 +558,7 @@ describe('rootCozyUrl', () => {
518
558
  status: 503,
519
559
  statusText: '',
520
560
  type: 'default',
521
- url: 'https://camillenimbus.com/.well-known/change-password'
561
+ url: 'https://camillenimbus.com/public/prelogin'
522
562
  })
523
563
  })
524
564
 
@@ -546,7 +586,7 @@ describe('rootCozyUrl', () => {
546
586
  status: 503,
547
587
  statusText: '',
548
588
  type: 'default',
549
- url: 'https://camillenimbus.com/.well-known/change-password'
589
+ url: 'https://camillenimbus.com/public/prelogin'
550
590
  })
551
591
  })
552
592
 
@@ -555,3 +595,431 @@ describe('rootCozyUrl', () => {
555
595
  ).rejects.toBeInstanceOf(InvalidCozyUrlError)
556
596
  })
557
597
  })
598
+
599
+ describe('fetchRegistrationDetails', () => {
600
+ beforeAll(() => {
601
+ enableFetchMocks()
602
+ })
603
+
604
+ beforeEach(() => {
605
+ fetch.resetMocks()
606
+ })
607
+
608
+ afterAll(() => {
609
+ disableFetchMocks()
610
+ })
611
+
612
+ it('should handle cozy-hosted https', async () => {
613
+ mockFetchJsonOnce(
614
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
615
+ fakeCozyPrelogin()
616
+ )
617
+
618
+ await expect(
619
+ fetchRegistrationDetails(new URL('https://camillenimbus.mycozy.cloud'))
620
+ ).resolves.toStrictEqual({
621
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
622
+ isOIDC: false
623
+ })
624
+ })
625
+
626
+ it('should handle cozy-hosted https trailing slash', async () => {
627
+ mockFetchJsonOnce(
628
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
629
+ fakeCozyPrelogin()
630
+ )
631
+
632
+ await expect(
633
+ fetchRegistrationDetails(new URL('https://camillenimbus.mycozy.cloud/'))
634
+ ).resolves.toStrictEqual({
635
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
636
+ isOIDC: false
637
+ })
638
+ })
639
+
640
+ it('should handle cozy-hosted https trailing path', async () => {
641
+ mockFetchJsonOnce(
642
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
643
+ fakeCozyPrelogin()
644
+ )
645
+
646
+ await expect(
647
+ fetchRegistrationDetails(
648
+ new URL('https://camillenimbus.mycozy.cloud/some-path')
649
+ )
650
+ ).resolves.toStrictEqual({
651
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
652
+ isOIDC: false
653
+ })
654
+ })
655
+
656
+ it('should handle cozy-hosted drive web app url', async () => {
657
+ mockUnauthorizedOnce(
658
+ 'https://camillenimbus-drive.mycozy.cloud/public/prelogin'
659
+ )
660
+ mockFetchJsonOnce(
661
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
662
+ fakeCozyPrelogin()
663
+ )
664
+
665
+ await expect(
666
+ fetchRegistrationDetails(
667
+ new URL('https://camillenimbus-drive.mycozy.cloud/#/folder')
668
+ )
669
+ ).resolves.toStrictEqual({
670
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
671
+ isOIDC: false
672
+ })
673
+ })
674
+
675
+ it('should handle cozy-hosted photos album url', async () => {
676
+ mockUnauthorizedOnce(
677
+ 'https://camillenimbus-photos.mycozy.cloud/public/prelogin'
678
+ )
679
+ mockFetchJsonOnce(
680
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
681
+ fakeCozyPrelogin()
682
+ )
683
+
684
+ await expect(
685
+ fetchRegistrationDetails(
686
+ new URL(
687
+ 'https://camillenimbus-photos.mycozy.cloud/#/albums/68b5cda502ae29f5fa73fd89f1be4f92'
688
+ )
689
+ )
690
+ ).resolves.toStrictEqual({
691
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
692
+ isOIDC: false
693
+ })
694
+ })
695
+
696
+ it('should handle cozy-hosted app name', async () => {
697
+ mockUnauthorizedOnce(
698
+ 'https://camillenimbus-someslug.mycozy.cloud/public/prelogin'
699
+ )
700
+ mockFetchJsonOnce(
701
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
702
+ fakeCozyPrelogin()
703
+ )
704
+
705
+ await expect(
706
+ fetchRegistrationDetails(
707
+ new URL('https://camillenimbus-someslug.mycozy.cloud')
708
+ )
709
+ ).resolves.toStrictEqual({
710
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
711
+ isOIDC: false
712
+ })
713
+ })
714
+
715
+ it('should handle cozy-hosted special app name', async () => {
716
+ // XXX: `cozy-stack` redirects requests for deprecated apps (e.g.
717
+ // `onboarding`) to the Home app (via the login page if the user is not
718
+ // logged in).
719
+ mockRedirectOnce(
720
+ 'https://camillenimbus-onboarding.mycozy.cloud/public/prelogin',
721
+ 'https://camillenimbus.mycozy.cloud/auth/login?redirect=https%3A%2F%2Fcamillenimbus-home.mycozy.cloud%2F'
722
+ )
723
+ mockFetchJsonOnce(
724
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
725
+ fakeCozyPrelogin()
726
+ )
727
+
728
+ await expect(
729
+ fetchRegistrationDetails(
730
+ new URL('https://camillenimbus-onboarding.mycozy.cloud')
731
+ )
732
+ ).resolves.toStrictEqual({
733
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
734
+ isOIDC: false
735
+ })
736
+ })
737
+
738
+ it('should handle self-hosted https', async () => {
739
+ mockFetchJsonOnce(
740
+ 'https://camillenimbus.com/public/prelogin',
741
+ fakeCozyPrelogin()
742
+ )
743
+
744
+ await expect(
745
+ fetchRegistrationDetails(new URL('https://camillenimbus.com'))
746
+ ).resolves.toStrictEqual({
747
+ rootUrl: new URL('https://camillenimbus.com/'),
748
+ isOIDC: false
749
+ })
750
+ })
751
+
752
+ it('should handle self-hosted with dash', async () => {
753
+ mockFetchJsonOnce(
754
+ 'https://camille-nimbus.com/public/prelogin',
755
+ fakeCozyPrelogin()
756
+ )
757
+
758
+ await expect(
759
+ fetchRegistrationDetails(new URL('https://camille-nimbus.com'))
760
+ ).resolves.toStrictEqual({
761
+ rootUrl: new URL('https://camille-nimbus.com/'),
762
+ isOIDC: false
763
+ })
764
+ })
765
+
766
+ it('should handle self-hosted http', async () => {
767
+ mockFetchJsonOnce(
768
+ 'http://camille-nimbus.com/public/prelogin',
769
+ fakeCozyPrelogin()
770
+ )
771
+
772
+ await expect(
773
+ fetchRegistrationDetails(new URL('http://camille-nimbus.com'))
774
+ ).resolves.toStrictEqual({
775
+ rootUrl: new URL('http://camille-nimbus.com/'),
776
+ isOIDC: false
777
+ })
778
+ })
779
+
780
+ it('should handle self-hosted https with port', async () => {
781
+ mockFetchJsonOnce(
782
+ 'https://camillenimbus.com:666/public/prelogin',
783
+ fakeCozyPrelogin()
784
+ )
785
+
786
+ await expect(
787
+ fetchRegistrationDetails(new URL('https://camillenimbus.com:666'))
788
+ ).resolves.toStrictEqual({
789
+ rootUrl: new URL('https://camillenimbus.com:666/'),
790
+ isOIDC: false
791
+ })
792
+ })
793
+
794
+ it('should handle self-hosted nested drive web app url', async () => {
795
+ mockUnauthorizedOnce('https://drive.camillenimbus.com/public/prelogin')
796
+ mockFetchJsonOnce(
797
+ 'https://camillenimbus.com/public/prelogin',
798
+ fakeCozyPrelogin()
799
+ )
800
+
801
+ await expect(
802
+ fetchRegistrationDetails(
803
+ new URL('https://drive.camillenimbus.com/#/folder')
804
+ )
805
+ ).resolves.toStrictEqual({
806
+ rootUrl: new URL('https://camillenimbus.com/'),
807
+ isOIDC: false
808
+ })
809
+ })
810
+
811
+ it('should handle self-hosted flat drive web app url', async () => {
812
+ mockUnauthorizedOnce('https://camille-drive.nimbus.com/public/prelogin')
813
+ mockFetchJsonOnce(
814
+ 'https://camille.nimbus.com/public/prelogin',
815
+ fakeCozyPrelogin()
816
+ )
817
+
818
+ await expect(
819
+ fetchRegistrationDetails(
820
+ new URL('https://camille-drive.nimbus.com/#/folder')
821
+ )
822
+ ).resolves.toStrictEqual({
823
+ rootUrl: new URL('https://camille.nimbus.com/'),
824
+ isOIDC: false
825
+ })
826
+ })
827
+
828
+ it('should handle cozy.localhost', async () => {
829
+ mockFetchJsonOnce(
830
+ 'http://cozy.localhost:8080/public/prelogin',
831
+ fakeCozyPrelogin()
832
+ )
833
+ await expect(
834
+ fetchRegistrationDetails(new URL('http://cozy.localhost:8080'))
835
+ ).resolves.toStrictEqual({
836
+ rootUrl: new URL('http://cozy.localhost:8080/'),
837
+ isOIDC: false
838
+ })
839
+ })
840
+
841
+ it('expects an http or https protocol', async () => {
842
+ mockFetchJsonOnce(
843
+ 'ftp://camillenimbus.com/public/prelogin',
844
+ fakeCozyPrelogin()
845
+ )
846
+
847
+ await expect(
848
+ fetchRegistrationDetails(new URL('ftp://camillenimbus.com'))
849
+ ).rejects.toBeInstanceOf(InvalidProtocolError)
850
+ })
851
+
852
+ it('rejects if URL points to a valid cozy-stack but no valid Cozy instance', async () => {
853
+ mockNotFoundOnce('https://missing.mycozy.cloud/public/prelogin')
854
+
855
+ await expect(
856
+ fetchRegistrationDetails(new URL('https://missing.mycozy.cloud/'))
857
+ ).rejects.toBeInstanceOf(InvalidCozyUrlError)
858
+ })
859
+
860
+ it('should reject if Blocked cozy', async () => {
861
+ mockBlockedCozy('https://camillenimbus.com/public/prelogin')
862
+
863
+ await expect(
864
+ fetchRegistrationDetails(new URL('https://camillenimbus.com'))
865
+ ).rejects.toBeInstanceOf(BlockedCozyError)
866
+ })
867
+
868
+ it('should reject on 503 error (if not Blocked)', async () => {
869
+ mock503Error('https://camillenimbus.com/public/prelogin')
870
+
871
+ await expect(
872
+ fetchRegistrationDetails(new URL('https://camillenimbus.com'))
873
+ ).rejects.toBeInstanceOf(InvalidCozyUrlError)
874
+ })
875
+
876
+ it('should handle OIDC cozy', async () => {
877
+ mockFetchJsonOnce(
878
+ 'https://camillenimbus.mycozy.cloud/public/prelogin',
879
+ fakeOidcPrelogin()
880
+ )
881
+
882
+ await expect(
883
+ fetchRegistrationDetails(new URL('https://camillenimbus.mycozy.cloud'))
884
+ ).resolves.toStrictEqual({
885
+ rootUrl: new URL('https://camillenimbus.mycozy.cloud/'),
886
+ isOIDC: true
887
+ })
888
+ })
889
+
890
+ it('should reject if non Json response', async () => {
891
+ mockFetchHtmlOnce(
892
+ 'https://camillenimbus.com/public/prelogin',
893
+ '<html>Some HTML content</html>'
894
+ )
895
+
896
+ await expect(
897
+ fetchRegistrationDetails(new URL('https://camillenimbus.com'))
898
+ ).rejects.toBeInstanceOf(InvalidCozyUrlError)
899
+ })
900
+ })
901
+
902
+ const mockFetchHtmlOnce = (url, response) => {
903
+ fetch.mockOnceIf(url, response, {
904
+ status: 200,
905
+ url: url,
906
+ headers: {
907
+ 'content-type': 'text/html; charset=UTF-8'
908
+ }
909
+ })
910
+ }
911
+
912
+ const mockFetchJsonOnce = (url, response) => {
913
+ fetch.mockOnceIf(url, response, {
914
+ status: 200,
915
+ url: url,
916
+ headers: {
917
+ 'content-type': 'application/json'
918
+ }
919
+ })
920
+ }
921
+
922
+ const mockRedirectOnce = (url, redirectedUrl) => {
923
+ fetch.mockOnceIf(
924
+ url,
925
+ {},
926
+ {
927
+ status: 200,
928
+ url: redirectedUrl
929
+ }
930
+ )
931
+ }
932
+
933
+ const mockUnauthorizedOnce = url => {
934
+ fetch.mockOnceIf(
935
+ url,
936
+ {},
937
+ {
938
+ status: 401,
939
+ url: url
940
+ }
941
+ )
942
+ }
943
+
944
+ const mockNotFoundOnce = url => {
945
+ fetch.mockOnceIf(
946
+ url,
947
+ {},
948
+ {
949
+ status: 404,
950
+ url: url
951
+ }
952
+ )
953
+ }
954
+
955
+ const mockBlockedCozy = url => {
956
+ fetch.mockResponse(() => {
957
+ return Promise.resolve({
958
+ headers: {
959
+ 'content-type': 'application/json; charset=UTF-8'
960
+ },
961
+ body: JSON.stringify([
962
+ {
963
+ status: '503',
964
+ title: 'Blocked',
965
+ code: 'UNKNOWN',
966
+ detail: 'The Cozy is blocked for an unknown reason',
967
+ source: {}
968
+ }
969
+ ]),
970
+ ok: false,
971
+ status: 503,
972
+ statusText: '',
973
+ type: 'default',
974
+ url: url
975
+ })
976
+ })
977
+ }
978
+
979
+ const mock503Error = url => {
980
+ fetch.mockResponse(() => {
981
+ return Promise.resolve({
982
+ headers: {
983
+ 'content-type': 'application/json; charset=UTF-8'
984
+ },
985
+ body: JSON.stringify([
986
+ {
987
+ status: '503',
988
+ title: 'Some error',
989
+ code: 'UNKNOWN',
990
+ detail: 'Some error description',
991
+ source: {}
992
+ }
993
+ ]),
994
+ ok: false,
995
+ status: 503,
996
+ statusText: '',
997
+ type: 'default',
998
+ url: url
999
+ })
1000
+ })
1001
+ }
1002
+
1003
+ const fakeOidcPrelogin = () => {
1004
+ return JSON.stringify({
1005
+ FranceConnect: false,
1006
+ Kdf: 0,
1007
+ KdfIterations: 100000,
1008
+ OIDC: true,
1009
+ locale: 'fr',
1010
+ magic_link: false,
1011
+ name: 'claude'
1012
+ })
1013
+ }
1014
+
1015
+ const fakeCozyPrelogin = () => {
1016
+ return JSON.stringify({
1017
+ FranceConnect: false,
1018
+ Kdf: 0,
1019
+ KdfIterations: 100000,
1020
+ OIDC: false,
1021
+ locale: 'fr',
1022
+ magic_link: false,
1023
+ name: 'claude'
1024
+ })
1025
+ }
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ var _exportNames = {
33
33
  dehydrate: true,
34
34
  generateWebLink: true,
35
35
  ensureFirstSlash: true,
36
+ fetchRegistrationDetails: true,
36
37
  rootCozyUrl: true,
37
38
  InvalidRedirectLinkError: true,
38
39
  InvalidCozyUrlError: true,
@@ -219,6 +220,12 @@ Object.defineProperty(exports, "ensureFirstSlash", {
219
220
  return _helpers2.ensureFirstSlash;
220
221
  }
221
222
  });
223
+ Object.defineProperty(exports, "fetchRegistrationDetails", {
224
+ enumerable: true,
225
+ get: function get() {
226
+ return _helpers2.fetchRegistrationDetails;
227
+ }
228
+ });
222
229
  Object.defineProperty(exports, "rootCozyUrl", {
223
230
  enumerable: true,
224
231
  get: function get() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "58.2.0",
3
+ "version": "58.3.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.node.js",
6
6
  "browser": "dist/index.js",
@@ -74,5 +74,5 @@
74
74
  "react-native-ios11-devicecheck": "^0.0.3"
75
75
  },
76
76
  "sideEffects": false,
77
- "gitHead": "3a6e5104325605d3d9c74ae5a1738e16289b659d"
77
+ "gitHead": "648e72735558114a377f9d3afc2b549bdb6de463"
78
78
  }
@@ -1,3 +1,3 @@
1
1
  export { dehydrate } from "./dehydrateHelper";
2
- export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, generateWebLink, ensureFirstSlash, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./urlHelper";
2
+ export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, generateWebLink, ensureFirstSlash, fetchRegistrationDetails, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./urlHelper";
3
3
  export { editSettings, getQuery, getSettings, normalizeSettings, saveAfterFetchSettings } from "./settings";
@@ -26,3 +26,14 @@ export class InvalidCozyUrlError extends Error {
26
26
  url: any;
27
27
  }
28
28
  export function rootCozyUrl(url: URL): Promise<URL>;
29
+ export function fetchRegistrationDetails(url: URL): Promise<RegistrationDetails>;
30
+ export type RegistrationDetails = {
31
+ /**
32
+ * - The Cozy's root URL
33
+ */
34
+ rootUrl: URL;
35
+ /**
36
+ * - True if the Cozy's uses OIDC for login
37
+ */
38
+ isOIDC: boolean;
39
+ };
package/types/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export { manifest, models };
22
22
  export { QueryDefinition, Q, Mutations, MutationTypes, getDoctypeFromOperation } from "./queries/dsl";
23
23
  export { Association, HasMany, HasOne, HasOneInPlace, HasManyInPlace, HasManyTriggers } from "./associations";
24
24
  export { isReferencedBy, isReferencedById, getReferencedBy, getReferencedById } from "./associations/helpers";
25
- export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, dehydrate, generateWebLink, ensureFirstSlash, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./helpers";
25
+ export { deconstructCozyWebLinkWithSlug, deconstructRedirectLink, dehydrate, generateWebLink, ensureFirstSlash, fetchRegistrationDetails, rootCozyUrl, InvalidRedirectLinkError, InvalidCozyUrlError, InvalidProtocolError, BlockedCozyError } from "./helpers";
26
26
  export { cancelable, isQueryLoading, hasQueryBeenLoaded, isQueriesLoading, hasQueriesBeenLoaded } from "./utils";
27
27
  export { getQueryFromState, dispatchCreate, dispatchUpdate, dispatchDelete } from "./store";
28
28
  export { queryConnect, queryConnectFlat, withClient } from "./hoc";