cozy-client 27.13.0 → 27.14.3
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/CHANGELOG.md +38 -0
- package/dist/CozyClient.js +2 -1
- package/dist/CozyClient.spec.js +56 -54
- package/dist/assets/qualifications.json +1 -1
- package/dist/associations.spec.js +1 -1
- package/dist/helpers.js +295 -2
- package/dist/helpers.spec.js +240 -1
- package/dist/hooks/useQuery.spec.jsx +1 -1
- package/dist/index.js +21 -0
- package/dist/index.node.js +21 -0
- package/dist/utils.spec.js +1 -0
- package/package.json +3 -3
- package/types/CozyClient.d.ts +1 -0
- package/types/helpers.d.ts +9 -0
- package/types/index.d.ts +1 -1
- package/types/index.node.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,44 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [27.14.3](https://github.com/cozy/cozy-client/compare/v27.14.2...v27.14.3) (2022-01-28)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **qualification:** Fix typo in identity ([e89aa8d](https://github.com/cozy/cozy-client/commit/e89aa8de0b6b25d5eecd8dc1ba41baa80dff5ec2))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## [27.14.2](https://github.com/cozy/cozy-client/compare/v27.14.1...v27.14.2) (2022-01-28)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package cozy-client
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## [27.14.1](https://github.com/cozy/cozy-client/compare/v27.14.0...v27.14.1) (2022-01-28)
|
|
26
|
+
|
|
27
|
+
**Note:** Version bump only for package cozy-client
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# [27.14.0](https://github.com/cozy/cozy-client/compare/v27.13.0...v27.14.0) (2022-01-25)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Features
|
|
37
|
+
|
|
38
|
+
* Add rootCozyUrl helper ([ca09e71](https://github.com/cozy/cozy-client/commit/ca09e71a7b687bf28055ed0764d08c4dbd7e70cc))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
6
44
|
# [27.13.0](https://github.com/cozy/cozy-client/compare/v27.12.0...v27.13.0) (2022-01-24)
|
|
7
45
|
|
|
8
46
|
|
package/dist/CozyClient.js
CHANGED
|
@@ -2293,6 +2293,7 @@ var CozyClient = /*#__PURE__*/function () {
|
|
|
2293
2293
|
* At any time put an error function
|
|
2294
2294
|
*
|
|
2295
2295
|
* @param {Function} [onError] - Set a callback for queries which are errored
|
|
2296
|
+
* @throws {Error} onError should not have been defined yet
|
|
2296
2297
|
*/
|
|
2297
2298
|
|
|
2298
2299
|
}, {
|
|
@@ -2463,7 +2464,7 @@ var CozyClient = /*#__PURE__*/function () {
|
|
|
2463
2464
|
CozyClient.hooks = CozyClient.hooks || {};
|
|
2464
2465
|
CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
|
|
2465
2466
|
|
|
2466
|
-
CozyClient.version = "27.
|
|
2467
|
+
CozyClient.version = "27.14.3";
|
|
2467
2468
|
|
|
2468
2469
|
_microee.default.mixin(CozyClient);
|
|
2469
2470
|
|
package/dist/CozyClient.spec.js
CHANGED
|
@@ -1140,7 +1140,7 @@ describe('CozyClient', () => {
|
|
|
1140
1140
|
})
|
|
1141
1141
|
|
|
1142
1142
|
it('should first dispatch a INIT_QUERY action', async () => {
|
|
1143
|
-
requestHandler.
|
|
1143
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1144
1144
|
await client.query(query, { as: 'allTodos' })
|
|
1145
1145
|
expect(client.store.dispatch.mock.calls[0][0]).toEqual(
|
|
1146
1146
|
initQuery('allTodos', { doctype: 'io.cozy.todos' }, { as: 'allTodos' })
|
|
@@ -1148,7 +1148,7 @@ describe('CozyClient', () => {
|
|
|
1148
1148
|
})
|
|
1149
1149
|
|
|
1150
1150
|
it('should then dispatch a RECEIVE_QUERY_RESULT action', async () => {
|
|
1151
|
-
requestHandler.
|
|
1151
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1152
1152
|
await client.query(query, { as: 'allTodos' })
|
|
1153
1153
|
const dispatchCalls = client.store.dispatch.mock.calls
|
|
1154
1154
|
const lastDispatchCall = dispatchCalls[dispatchCalls.length - 1]
|
|
@@ -1159,7 +1159,7 @@ describe('CozyClient', () => {
|
|
|
1159
1159
|
|
|
1160
1160
|
it('should dispatch a RECEIVE_QUERY_ERROR action if an error occurs', async () => {
|
|
1161
1161
|
const error = new Error('Fake error')
|
|
1162
|
-
requestHandler.
|
|
1162
|
+
requestHandler.mockRejectedValueOnce(error)
|
|
1163
1163
|
try {
|
|
1164
1164
|
await client.query(query, { as: 'allTodos' })
|
|
1165
1165
|
} catch (e) {} // eslint-disable-line no-empty
|
|
@@ -1169,13 +1169,13 @@ describe('CozyClient', () => {
|
|
|
1169
1169
|
})
|
|
1170
1170
|
|
|
1171
1171
|
it('should resolve to the query response', async () => {
|
|
1172
|
-
requestHandler.
|
|
1172
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1173
1173
|
const resp = await client.query(query)
|
|
1174
1174
|
expect(resp).toEqual(fakeResponse)
|
|
1175
1175
|
})
|
|
1176
1176
|
|
|
1177
1177
|
it('should call the link with the query', async () => {
|
|
1178
|
-
requestHandler.
|
|
1178
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1179
1179
|
await client.query(query)
|
|
1180
1180
|
expect(requestHandler).toHaveBeenCalledTimes(1)
|
|
1181
1181
|
expect(requestHandler.mock.calls[0][0]).toBe(query)
|
|
@@ -1200,8 +1200,8 @@ describe('CozyClient', () => {
|
|
|
1200
1200
|
]
|
|
1201
1201
|
})
|
|
1202
1202
|
)
|
|
1203
|
-
.
|
|
1204
|
-
.
|
|
1203
|
+
.mockResolvedValueOnce({ data: [], included: [] })
|
|
1204
|
+
.mockResolvedValueOnce({ data: [], included: [] })
|
|
1205
1205
|
|
|
1206
1206
|
const resp = await client.query(
|
|
1207
1207
|
Q('io.cozy.todos').include(['attachments'])
|
|
@@ -1246,7 +1246,7 @@ describe('CozyClient', () => {
|
|
|
1246
1246
|
})
|
|
1247
1247
|
|
|
1248
1248
|
it('should set the correct name to the query', async () => {
|
|
1249
|
-
requestHandler.
|
|
1249
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1250
1250
|
const getById = Q('io.cozy.files').getById('1')
|
|
1251
1251
|
await client.query(getById)
|
|
1252
1252
|
expect(client.store.dispatch.mock.calls[0][0]).toEqual(
|
|
@@ -1256,7 +1256,7 @@ describe('CozyClient', () => {
|
|
|
1256
1256
|
)
|
|
1257
1257
|
})
|
|
1258
1258
|
it('should use the name passed as an argument', async () => {
|
|
1259
|
-
requestHandler.
|
|
1259
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1260
1260
|
const getById = Q('io.cozy.files').getById('1')
|
|
1261
1261
|
await client.query(getById, { as: 'toto' })
|
|
1262
1262
|
expect(client.store.dispatch.mock.calls[0][0]).toEqual(
|
|
@@ -1266,7 +1266,7 @@ describe('CozyClient', () => {
|
|
|
1266
1266
|
)
|
|
1267
1267
|
})
|
|
1268
1268
|
it('should name the query correctly', async () => {
|
|
1269
|
-
requestHandler.
|
|
1269
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1270
1270
|
await client.query(query, { as: 'allTodos' })
|
|
1271
1271
|
expect(client.store.dispatch.mock.calls[0][0]).toEqual(
|
|
1272
1272
|
initQuery('allTodos', { doctype: 'io.cozy.todos' }, { as: 'allTodos' })
|
|
@@ -1353,7 +1353,7 @@ describe('CozyClient', () => {
|
|
|
1353
1353
|
})
|
|
1354
1354
|
|
|
1355
1355
|
it('should dispatch a INIT_QUERY action if status is not loaded', async () => {
|
|
1356
|
-
requestHandler.
|
|
1356
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1357
1357
|
getQueryFromState.mockReturnValueOnce({
|
|
1358
1358
|
fetchStatus: 'pending'
|
|
1359
1359
|
})
|
|
@@ -1364,7 +1364,7 @@ describe('CozyClient', () => {
|
|
|
1364
1364
|
})
|
|
1365
1365
|
|
|
1366
1366
|
it('should dispatch a INIT_QUERY action if no skip and no bookmark', async () => {
|
|
1367
|
-
requestHandler.
|
|
1367
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1368
1368
|
getQueryFromState.mockReturnValueOnce({
|
|
1369
1369
|
fetchStatus: 'loaded'
|
|
1370
1370
|
})
|
|
@@ -1375,7 +1375,7 @@ describe('CozyClient', () => {
|
|
|
1375
1375
|
})
|
|
1376
1376
|
|
|
1377
1377
|
it('should dispatch a RECEIVE_QUERY_RESULT action if query has skip', async () => {
|
|
1378
|
-
requestHandler.
|
|
1378
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1379
1379
|
getQueryFromState.mockReturnValueOnce({
|
|
1380
1380
|
fetchStatus: 'loaded'
|
|
1381
1381
|
})
|
|
@@ -1389,7 +1389,7 @@ describe('CozyClient', () => {
|
|
|
1389
1389
|
})
|
|
1390
1390
|
|
|
1391
1391
|
it('should dispatch a RECEIVE_QUERY_RESULT action if query has bookmark', async () => {
|
|
1392
|
-
requestHandler.
|
|
1392
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1393
1393
|
getQueryFromState.mockReturnValueOnce({
|
|
1394
1394
|
fetchStatus: 'loaded'
|
|
1395
1395
|
})
|
|
@@ -1402,52 +1402,54 @@ describe('CozyClient', () => {
|
|
|
1402
1402
|
)
|
|
1403
1403
|
})
|
|
1404
1404
|
|
|
1405
|
-
|
|
1406
|
-
const
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1405
|
+
describe('setupOnError', () => {
|
|
1406
|
+
const setupOnError = () => {
|
|
1407
|
+
const error = new TypeError('Failed to fetch')
|
|
1408
|
+
requestHandler.mockRejectedValueOnce(error)
|
|
1409
|
+
return jest.fn().mockReturnValueOnce(() => true)
|
|
1410
|
+
}
|
|
1411
1411
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1412
|
+
it('should call onError callback when an error is thrown. Callback passed as argument', async () => {
|
|
1413
|
+
const onError = setupOnError()
|
|
1414
1414
|
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1415
|
+
await client.query(query, { as: 'allTodos', onError })
|
|
1416
|
+
expect(onError).toBeCalled()
|
|
1417
|
+
})
|
|
1418
1418
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1419
|
+
it('should call onError callback when an error is caught. It is passed during instantiation', async () => {
|
|
1420
|
+
const setupOnError = () => jest.fn().mockReturnValueOnce(() => true)
|
|
1421
|
+
const onError = setupOnError()
|
|
1422
|
+
const client = new CozyClient({ onError })
|
|
1422
1423
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1424
|
+
await client.query(query, { as: 'allTodos' })
|
|
1425
|
+
expect(onError).toBeCalled()
|
|
1426
|
+
})
|
|
1426
1427
|
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1428
|
+
it('should call onError callback when an error is catched. It is passed with setOnError', async () => {
|
|
1429
|
+
const onError = setupOnError()
|
|
1430
|
+
client.setOnError(onError)
|
|
1430
1431
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1432
|
+
await client.query(query, { as: 'allTodos' })
|
|
1433
|
+
expect(onError).toBeCalled()
|
|
1434
|
+
})
|
|
1434
1435
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1436
|
+
it('should throw an error when we call setOnError twice (or several times)', async () => {
|
|
1437
|
+
const client = new CozyClient({})
|
|
1438
|
+
const onError = () => true
|
|
1438
1439
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1440
|
+
const funcShouldThrow = () => client.setOnError(onError)
|
|
1441
|
+
expect(funcShouldThrow).not.toThrow()
|
|
1442
|
+
expect(funcShouldThrow).toThrow('On Error is already defined')
|
|
1443
|
+
})
|
|
1443
1444
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1445
|
+
it('should throw an error when there is no onError callback', async () => {
|
|
1446
|
+
const error = new TypeError('Failed to fetch')
|
|
1447
|
+
requestHandler.mockRejectedValueOnce(error)
|
|
1447
1448
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1449
|
+
await expect(client.query(query, { as: 'allTodos' })).rejects.toThrow(
|
|
1450
|
+
'Failed to fetch'
|
|
1451
|
+
)
|
|
1452
|
+
})
|
|
1451
1453
|
})
|
|
1452
1454
|
})
|
|
1453
1455
|
|
|
@@ -1546,7 +1548,7 @@ describe('CozyClient', () => {
|
|
|
1546
1548
|
})
|
|
1547
1549
|
|
|
1548
1550
|
it('should then dispatch a RECEIVE_MUTATION_RESULT action', async () => {
|
|
1549
|
-
requestHandler.
|
|
1551
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1550
1552
|
await client.mutate(mutation, { as: 'updateTodo' })
|
|
1551
1553
|
expect(client.store.dispatch.mock.calls[1][0]).toEqual(
|
|
1552
1554
|
receiveMutationResult('updateTodo', fakeResponse, {}, mutation)
|
|
@@ -1554,14 +1556,14 @@ describe('CozyClient', () => {
|
|
|
1554
1556
|
})
|
|
1555
1557
|
|
|
1556
1558
|
it('should resolve to the mutation response', async () => {
|
|
1557
|
-
requestHandler.
|
|
1559
|
+
requestHandler.mockResolvedValueOnce(fakeResponse)
|
|
1558
1560
|
const resp = await client.mutate(mutation)
|
|
1559
1561
|
expect(resp).toEqual(fakeResponse)
|
|
1560
1562
|
})
|
|
1561
1563
|
|
|
1562
1564
|
it('should dispatch a RECEIVE_MUTATION_ERROR action if an error occurs', async () => {
|
|
1563
1565
|
const error = new Error('Fake error')
|
|
1564
|
-
requestHandler.
|
|
1566
|
+
requestHandler.mockRejectedValueOnce(error)
|
|
1565
1567
|
try {
|
|
1566
1568
|
await client.mutate(mutation, { as: 'updateTodo' })
|
|
1567
1569
|
} catch (e) {} // eslint-disable-line no-empty
|
|
@@ -1573,7 +1575,7 @@ describe('CozyClient', () => {
|
|
|
1573
1575
|
it('should handle an array of mutations (including mutation creators)', async () => {
|
|
1574
1576
|
const FAKE_MUTATION_1 = { mutationType: 'FAKE_1' }
|
|
1575
1577
|
const FAKE_MUTATION_2 = resp => ({ mutationType: 'FAKE_2', resp })
|
|
1576
|
-
requestHandler.
|
|
1578
|
+
requestHandler.mockResolvedValue(fakeResponse)
|
|
1577
1579
|
await client.mutate([mutation, FAKE_MUTATION_1, FAKE_MUTATION_2])
|
|
1578
1580
|
expect(requestHandler).toHaveBeenCalledTimes(3)
|
|
1579
1581
|
expect(requestHandler.mock.calls[0][0]).toBe(mutation)
|
|
@@ -119,7 +119,7 @@ describe('Associations', () => {
|
|
|
119
119
|
],
|
|
120
120
|
next: false
|
|
121
121
|
}
|
|
122
|
-
requestHandler.
|
|
122
|
+
requestHandler.mockResolvedValueOnce(FAKE_RESPONSE)
|
|
123
123
|
|
|
124
124
|
const queryBefore = getQueryFromStore(client.store, 'allTodos')
|
|
125
125
|
await getTodo(TODO_1._id).attachments.fetchMore()
|
package/dist/helpers.js
CHANGED
|
@@ -5,12 +5,34 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.generateWebLink = exports.dehydrate = void 0;
|
|
8
|
+
exports.rootCozyUrl = exports.InvalidCozyUrlError = exports.InvalidProtocolError = exports.generateWebLink = exports.dehydrate = void 0;
|
|
9
|
+
|
|
10
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
|
+
|
|
12
|
+
var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
|
|
13
|
+
|
|
14
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
15
|
+
|
|
16
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
17
|
+
|
|
18
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
19
|
+
|
|
20
|
+
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
21
|
+
|
|
22
|
+
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
23
|
+
|
|
24
|
+
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
25
|
+
|
|
26
|
+
var _wrapNativeSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapNativeSuper"));
|
|
9
27
|
|
|
10
28
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
29
|
|
|
12
30
|
var _associations = require("./associations");
|
|
13
31
|
|
|
32
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
|
|
33
|
+
|
|
34
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
|
35
|
+
|
|
14
36
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
15
37
|
|
|
16
38
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
@@ -103,4 +125,275 @@ var generateWebLink = function generateWebLink(_ref3) {
|
|
|
103
125
|
return url.toString();
|
|
104
126
|
};
|
|
105
127
|
|
|
106
|
-
exports.generateWebLink = generateWebLink;
|
|
128
|
+
exports.generateWebLink = generateWebLink;
|
|
129
|
+
|
|
130
|
+
var InvalidProtocolError = /*#__PURE__*/function (_Error) {
|
|
131
|
+
(0, _inherits2.default)(InvalidProtocolError, _Error);
|
|
132
|
+
|
|
133
|
+
var _super = _createSuper(InvalidProtocolError);
|
|
134
|
+
|
|
135
|
+
function InvalidProtocolError(url) {
|
|
136
|
+
var _this;
|
|
137
|
+
|
|
138
|
+
(0, _classCallCheck2.default)(this, InvalidProtocolError);
|
|
139
|
+
_this = _super.call(this, "Invalid URL protocol ".concat(url.protocol));
|
|
140
|
+
_this.url = url;
|
|
141
|
+
return _this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return InvalidProtocolError;
|
|
145
|
+
}( /*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
|
|
146
|
+
|
|
147
|
+
exports.InvalidProtocolError = InvalidProtocolError;
|
|
148
|
+
|
|
149
|
+
var InvalidCozyUrlError = /*#__PURE__*/function (_Error2) {
|
|
150
|
+
(0, _inherits2.default)(InvalidCozyUrlError, _Error2);
|
|
151
|
+
|
|
152
|
+
var _super2 = _createSuper(InvalidCozyUrlError);
|
|
153
|
+
|
|
154
|
+
function InvalidCozyUrlError(url) {
|
|
155
|
+
var _this2;
|
|
156
|
+
|
|
157
|
+
(0, _classCallCheck2.default)(this, InvalidCozyUrlError);
|
|
158
|
+
_this2 = _super2.call(this, "URL ".concat(url.toString(), " does not seem to be a valid Cozy URL"));
|
|
159
|
+
_this2.url = url;
|
|
160
|
+
return _this2;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return InvalidCozyUrlError;
|
|
164
|
+
}( /*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
|
|
165
|
+
/* uri - Returns a well formed URL origin from a protocol, a hostname and a port
|
|
166
|
+
*
|
|
167
|
+
* If the protocol and/or port are omitted from the argument, the function will
|
|
168
|
+
* default to HTTPS and omit the port in the returned origin.
|
|
169
|
+
*
|
|
170
|
+
* @param {object} url Object of URL elements
|
|
171
|
+
* @param {string} url.protocol Protocol to use in the origin (e.g. http)
|
|
172
|
+
* @param {string} url.hostname Hostname to use in the origin (e.g. claude.mycozy.cloud)
|
|
173
|
+
* @param {string} url.port Port to use in the origin (e.g. 8080)
|
|
174
|
+
*
|
|
175
|
+
* @returns {string} Generated URL origin
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
exports.InvalidCozyUrlError = InvalidCozyUrlError;
|
|
180
|
+
|
|
181
|
+
var uri = function uri(_ref4) {
|
|
182
|
+
var protocol = _ref4.protocol,
|
|
183
|
+
hostname = _ref4.hostname,
|
|
184
|
+
port = _ref4.port;
|
|
185
|
+
return (protocol !== '' ? "".concat(protocol, "//") : 'https://') + hostname + (port !== '' ? ":".concat(port) : '');
|
|
186
|
+
};
|
|
187
|
+
/* wellKnownUrl - Returns a valid URL string to a Well Known password change page
|
|
188
|
+
*
|
|
189
|
+
* The built URL will point to the origin generated from the given protocol,
|
|
190
|
+
* hostname and port.
|
|
191
|
+
*
|
|
192
|
+
* @param {object} url Object of URL elements
|
|
193
|
+
* @param {string} url.protocol Protocol to use in the origin (e.g. http)
|
|
194
|
+
* @param {string} url.hostname Hostname to use in the origin (e.g. claude.mycozy.cloud)
|
|
195
|
+
* @param {string} url.port Port to use in the origin (e.g. 8080)
|
|
196
|
+
*
|
|
197
|
+
* @returns {string} Generated Well Known password change URL string
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
var wellKnownUrl = function wellKnownUrl(url) {
|
|
202
|
+
return uri(url) + '/.well-known/change-password';
|
|
203
|
+
};
|
|
204
|
+
/* isValidOrigin - Checks whether a given URL is a valid Cozy origin
|
|
205
|
+
*
|
|
206
|
+
* This method tries to fetch the Well Known change password page of the Cozy
|
|
207
|
+
* supposedly at the given origin. This allows us to determine whether the given
|
|
208
|
+
* origin is the root URL of a Cozy or not via the status of the response:
|
|
209
|
+
* - a 200 response status means there's an actual Well Known password change
|
|
210
|
+
* page accessible from the given origin so we suppose it's a valid Cozy
|
|
211
|
+
* origin (i.e. it could be another site altogether though)
|
|
212
|
+
* - a 401 response status means the pointed page requires authentication so the
|
|
213
|
+
* origin is probably pointing to a Cozy app
|
|
214
|
+
* - another status means there aren't any Cozy behind to the given origin
|
|
215
|
+
*
|
|
216
|
+
* @param {object} url Object of URL elements
|
|
217
|
+
* @param {string} url.protocol Protocol to use in the origin (e.g. http)
|
|
218
|
+
* @param {string} url.hostname Hostname to use in the origin (e.g. claude.mycozy.cloud)
|
|
219
|
+
* @param {string} url.port Port to use in the origin (e.g. 8080)
|
|
220
|
+
*
|
|
221
|
+
* @returns {Promise<boolean>} True if we believe there's a Cozy behind the given origin
|
|
222
|
+
* @throws {InvalidCozyUrlError} Thrown when we know for sure there aren't any Cozy behind the given origin
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
var isValidOrigin = /*#__PURE__*/function () {
|
|
227
|
+
var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(url) {
|
|
228
|
+
var _yield$fetch, status;
|
|
229
|
+
|
|
230
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
231
|
+
while (1) {
|
|
232
|
+
switch (_context.prev = _context.next) {
|
|
233
|
+
case 0:
|
|
234
|
+
_context.next = 2;
|
|
235
|
+
return fetch(wellKnownUrl(url));
|
|
236
|
+
|
|
237
|
+
case 2:
|
|
238
|
+
_yield$fetch = _context.sent;
|
|
239
|
+
status = _yield$fetch.status;
|
|
240
|
+
|
|
241
|
+
if (!(status === 404)) {
|
|
242
|
+
_context.next = 6;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
throw new InvalidCozyUrlError(url);
|
|
247
|
+
|
|
248
|
+
case 6:
|
|
249
|
+
return _context.abrupt("return", status === 200);
|
|
250
|
+
|
|
251
|
+
case 7:
|
|
252
|
+
case "end":
|
|
253
|
+
return _context.stop();
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}, _callee);
|
|
257
|
+
}));
|
|
258
|
+
|
|
259
|
+
return function isValidOrigin(_x) {
|
|
260
|
+
return _ref5.apply(this, arguments);
|
|
261
|
+
};
|
|
262
|
+
}();
|
|
263
|
+
/**
|
|
264
|
+
* rootCozyUrl - Get the root URL of a Cozy from more precise ones
|
|
265
|
+
*
|
|
266
|
+
* The goal is to allow users to use any URL copied from their browser as their
|
|
267
|
+
* Cozy URL rather than trying to explain to them what we expect (e.g. when
|
|
268
|
+
* requesting the Cozy URL to connect an app).
|
|
269
|
+
* If we can't get the root URL either because there's no Cozy or the domain
|
|
270
|
+
* does not exist or anything else, we'll throw an InvalidCozyUrlError.
|
|
271
|
+
* Also, since we communicate only via HTTP or HTTPS, we'll throw an
|
|
272
|
+
* InvalidProtocolError if any other protocol is used.
|
|
273
|
+
*
|
|
274
|
+
* This function expects a fully qualified URL thus with a protocol and a valid
|
|
275
|
+
* hostname. If your application accepts Cozy intances as input (e.g. `claude`
|
|
276
|
+
* when the Cozy can be found at `https://claude.mycozy.cloud`), it is your
|
|
277
|
+
* responsibility to add the appropriate domain to the hostname before calling
|
|
278
|
+
* this function.
|
|
279
|
+
*
|
|
280
|
+
* Examples:
|
|
281
|
+
*
|
|
282
|
+
* 1. getting the root URL when your user gives you its instance name
|
|
283
|
+
*
|
|
284
|
+
* const userInput = 'claude'
|
|
285
|
+
* const rootUrl = await rootCozyUrl(new URL(`https://${userInput}.mycozy.cloud`))
|
|
286
|
+
* // → returns new URL('https://claude.mycozy.cloud')
|
|
287
|
+
*
|
|
288
|
+
* 2. getting the root URL when your user gives you a Cozy Drive URL
|
|
289
|
+
*
|
|
290
|
+
* const userInput = 'https://claude-drive.mycozy.cloud/#/folder/io.cozy.files.root-dir'
|
|
291
|
+
* const rootUrl = await rootCozyUrl(new URL(userInput))
|
|
292
|
+
* // → returns new URL('https://claude.mycozy.cloud')
|
|
293
|
+
*
|
|
294
|
+
* 3. getting the root URL when the Cozy uses nested sub-domains
|
|
295
|
+
*
|
|
296
|
+
* const userInput = 'http://photos.camille.nimbus.com:8080/#/album/1234567890'
|
|
297
|
+
* const rootCozyUrl = await rootCozyUrl(new URL(userInput))
|
|
298
|
+
* // → returns new URL('http://camille.nimbus.com:8080')
|
|
299
|
+
*
|
|
300
|
+
* @param {URL} url The URL from which we'll try to get the root Cozy URL
|
|
301
|
+
*
|
|
302
|
+
* @returns {Promise<URL>} The root Cozy URL
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
var rootCozyUrl = /*#__PURE__*/function () {
|
|
307
|
+
var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(url) {
|
|
308
|
+
var _url$hostname$split, _url$hostname$split2, subDomain, domain, _hostname, hostname;
|
|
309
|
+
|
|
310
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
311
|
+
while (1) {
|
|
312
|
+
switch (_context2.prev = _context2.next) {
|
|
313
|
+
case 0:
|
|
314
|
+
if (['http:', 'https:'].includes(url.protocol)) {
|
|
315
|
+
_context2.next = 2;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
throw new InvalidProtocolError(url);
|
|
320
|
+
|
|
321
|
+
case 2:
|
|
322
|
+
_context2.next = 4;
|
|
323
|
+
return isValidOrigin(url);
|
|
324
|
+
|
|
325
|
+
case 4:
|
|
326
|
+
if (!_context2.sent) {
|
|
327
|
+
_context2.next = 6;
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return _context2.abrupt("return", url);
|
|
332
|
+
|
|
333
|
+
case 6:
|
|
334
|
+
if (!/^[^.-][^.]+-[^.-]+\./.test(url.hostname)) {
|
|
335
|
+
_context2.next = 13;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
_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);
|
|
340
|
+
_hostname = [subDomain.replace(/-.+/, '')].concat((0, _toConsumableArray2.default)(domain)).join('.');
|
|
341
|
+
_context2.next = 11;
|
|
342
|
+
return isValidOrigin({
|
|
343
|
+
protocol: url.protocol,
|
|
344
|
+
hostname: _hostname,
|
|
345
|
+
port: url.port
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
case 11:
|
|
349
|
+
if (!_context2.sent) {
|
|
350
|
+
_context2.next = 13;
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return _context2.abrupt("return", new URL(uri({
|
|
355
|
+
protocol: url.protocol,
|
|
356
|
+
hostname: _hostname,
|
|
357
|
+
port: url.port
|
|
358
|
+
})));
|
|
359
|
+
|
|
360
|
+
case 13:
|
|
361
|
+
// Try to remove the first sub-domain in case its a nested app name
|
|
362
|
+
// eslint-disable-next-line no-unused-vars
|
|
363
|
+
hostname = url.hostname.split('.').splice(1).join('.');
|
|
364
|
+
_context2.next = 16;
|
|
365
|
+
return isValidOrigin({
|
|
366
|
+
protocol: url.protocol,
|
|
367
|
+
hostname: hostname,
|
|
368
|
+
port: url.port
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
case 16:
|
|
372
|
+
if (!_context2.sent) {
|
|
373
|
+
_context2.next = 18;
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return _context2.abrupt("return", new URL(uri({
|
|
378
|
+
protocol: url.protocol,
|
|
379
|
+
hostname: hostname,
|
|
380
|
+
port: url.port
|
|
381
|
+
})));
|
|
382
|
+
|
|
383
|
+
case 18:
|
|
384
|
+
throw new InvalidCozyUrlError(url);
|
|
385
|
+
|
|
386
|
+
case 19:
|
|
387
|
+
case "end":
|
|
388
|
+
return _context2.stop();
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}, _callee2);
|
|
392
|
+
}));
|
|
393
|
+
|
|
394
|
+
return function rootCozyUrl(_x2) {
|
|
395
|
+
return _ref6.apply(this, arguments);
|
|
396
|
+
};
|
|
397
|
+
}();
|
|
398
|
+
|
|
399
|
+
exports.rootCozyUrl = rootCozyUrl;
|
package/dist/helpers.spec.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { enableFetchMocks, disableFetchMocks } from 'jest-fetch-mock'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
dehydrate,
|
|
5
|
+
generateWebLink,
|
|
6
|
+
rootCozyUrl,
|
|
7
|
+
InvalidCozyUrlError,
|
|
8
|
+
InvalidProtocolError
|
|
9
|
+
} from './helpers'
|
|
2
10
|
|
|
3
11
|
import {
|
|
4
12
|
HasManyInPlace,
|
|
@@ -141,3 +149,234 @@ describe('generateWebLink', () => {
|
|
|
141
149
|
).toEqual(`https://drive.alice.cozy.tools/public/#/files/432432`)
|
|
142
150
|
})
|
|
143
151
|
})
|
|
152
|
+
|
|
153
|
+
describe('rootCozyUrl', () => {
|
|
154
|
+
beforeAll(() => {
|
|
155
|
+
enableFetchMocks()
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
afterAll(() => {
|
|
159
|
+
disableFetchMocks()
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('should handle cozy-hosted https', async () => {
|
|
163
|
+
fetch.mockOnceIf(
|
|
164
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
165
|
+
{},
|
|
166
|
+
{ status: 200 }
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
await expect(
|
|
170
|
+
rootCozyUrl(new URL('https://camillenimbus.mycozy.cloud'))
|
|
171
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('should handle cozy-hosted https trailing slash', async () => {
|
|
175
|
+
fetch.mockOnceIf(
|
|
176
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
177
|
+
{},
|
|
178
|
+
{ status: 200 }
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
await expect(
|
|
182
|
+
rootCozyUrl(new URL('https://camillenimbus.mycozy.cloud/'))
|
|
183
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('should handle cozy-hosted https trailing path', async () => {
|
|
187
|
+
fetch.mockOnceIf(
|
|
188
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
189
|
+
{},
|
|
190
|
+
{ status: 200 }
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
await expect(
|
|
194
|
+
rootCozyUrl(new URL('https://camillenimbus.mycozy.cloud/some-path'))
|
|
195
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('should handle cozy-hosted drive web app url', async () => {
|
|
199
|
+
fetch.mockOnceIf(
|
|
200
|
+
'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password',
|
|
201
|
+
{},
|
|
202
|
+
{ status: 401 }
|
|
203
|
+
)
|
|
204
|
+
fetch.mockOnceIf(
|
|
205
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
206
|
+
{},
|
|
207
|
+
{ status: 200 }
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
await expect(
|
|
211
|
+
rootCozyUrl(new URL('https://camillenimbus-drive.mycozy.cloud/#/folder'))
|
|
212
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('should handle cozy-hosted photos album url', async () => {
|
|
216
|
+
fetch.mockOnceIf(
|
|
217
|
+
'https://camillenimbus-photos.mycozy.cloud/.well-known/change-password',
|
|
218
|
+
{},
|
|
219
|
+
{ status: 401 }
|
|
220
|
+
)
|
|
221
|
+
fetch.mockOnceIf(
|
|
222
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
223
|
+
{},
|
|
224
|
+
{ status: 200 }
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
await expect(
|
|
228
|
+
rootCozyUrl(
|
|
229
|
+
new URL(
|
|
230
|
+
'https://camillenimbus-photos.mycozy.cloud/#/albums/68b5cda502ae29f5fa73fd89f1be4f92'
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('should handle cozy-hosted app name', async () => {
|
|
237
|
+
fetch.mockOnceIf(
|
|
238
|
+
'https://camillenimbus-drive.mycozy.cloud/.well-known/change-password',
|
|
239
|
+
{},
|
|
240
|
+
{ status: 401 }
|
|
241
|
+
)
|
|
242
|
+
fetch.mockOnceIf(
|
|
243
|
+
'https://camillenimbus.mycozy.cloud/.well-known/change-password',
|
|
244
|
+
{},
|
|
245
|
+
{ status: 200 }
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
await expect(
|
|
249
|
+
rootCozyUrl(new URL('https://camillenimbus-drive.mycozy.cloud'))
|
|
250
|
+
).resolves.toEqual(new URL('https://camillenimbus.mycozy.cloud'))
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('should handle self-hosted https', async () => {
|
|
254
|
+
fetch.mockOnceIf(
|
|
255
|
+
'https://camillenimbus.com/.well-known/change-password',
|
|
256
|
+
{},
|
|
257
|
+
{ status: 200 }
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
await expect(
|
|
261
|
+
rootCozyUrl(new URL('https://camillenimbus.com'))
|
|
262
|
+
).resolves.toEqual(new URL('https://camillenimbus.com'))
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('should handle self-hosted with dash', async () => {
|
|
266
|
+
fetch.mockOnceIf(
|
|
267
|
+
'https://camille-nimbus.com/.well-known/change-password',
|
|
268
|
+
{},
|
|
269
|
+
{
|
|
270
|
+
status: 200
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
await expect(
|
|
275
|
+
rootCozyUrl(new URL('https://camille-nimbus.com'))
|
|
276
|
+
).resolves.toEqual(new URL('https://camille-nimbus.com'))
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
it('should handle self-hosted http', async () => {
|
|
280
|
+
fetch.mockOnceIf(
|
|
281
|
+
'http://camille-nimbus.com/.well-known/change-password',
|
|
282
|
+
{},
|
|
283
|
+
{
|
|
284
|
+
status: 200
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
await expect(
|
|
289
|
+
rootCozyUrl(new URL('http://camille-nimbus.com'))
|
|
290
|
+
).resolves.toEqual(new URL('http://camille-nimbus.com'))
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
it('should handle self-hosted https with port', async () => {
|
|
294
|
+
fetch.mockOnceIf(
|
|
295
|
+
'https://camillenimbus.com:666/.well-known/change-password',
|
|
296
|
+
{},
|
|
297
|
+
{
|
|
298
|
+
status: 200
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
await expect(
|
|
303
|
+
rootCozyUrl(new URL('https://camillenimbus.com:666'))
|
|
304
|
+
).resolves.toEqual(new URL('https://camillenimbus.com:666'))
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it('should handle self-hosted nested drive web app url', async () => {
|
|
308
|
+
fetch.mockOnceIf(
|
|
309
|
+
'https://drive.camillenimbus.com/.well-known/change-password',
|
|
310
|
+
{},
|
|
311
|
+
{
|
|
312
|
+
status: 401
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
fetch.mockOnceIf(
|
|
316
|
+
'https://camillenimbus.com/.well-known/change-password',
|
|
317
|
+
{},
|
|
318
|
+
{
|
|
319
|
+
status: 200
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
await expect(
|
|
324
|
+
rootCozyUrl(new URL('https://drive.camillenimbus.com/#/folder'))
|
|
325
|
+
).resolves.toEqual(new URL('https://camillenimbus.com'))
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
it('should handle self-hosted flat drive web app url', async () => {
|
|
329
|
+
fetch.mockOnceIf(
|
|
330
|
+
'https://camille-drive.nimbus.com/.well-known/change-password',
|
|
331
|
+
{},
|
|
332
|
+
{
|
|
333
|
+
status: 401
|
|
334
|
+
}
|
|
335
|
+
)
|
|
336
|
+
fetch.mockOnceIf(
|
|
337
|
+
'https://camille.nimbus.com/.well-known/change-password',
|
|
338
|
+
{},
|
|
339
|
+
{
|
|
340
|
+
status: 200
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
await expect(
|
|
345
|
+
rootCozyUrl(new URL('https://camille-drive.nimbus.com/#/folder'))
|
|
346
|
+
).resolves.toEqual(new URL('https://camille.nimbus.com'))
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('should handle cozy.localhost', async () => {
|
|
350
|
+
await expect(
|
|
351
|
+
rootCozyUrl(new URL('http://cozy.localhost:8080'))
|
|
352
|
+
).resolves.toEqual(new URL('http://cozy.localhost:8080'))
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('expects an http or https protocol', async () => {
|
|
356
|
+
fetch.mockOnceIf(
|
|
357
|
+
'ftp://camillenimbus.com',
|
|
358
|
+
{},
|
|
359
|
+
{
|
|
360
|
+
status: 200
|
|
361
|
+
}
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
await expect(
|
|
365
|
+
rootCozyUrl(new URL('ftp://camillenimbus.com'))
|
|
366
|
+
).rejects.toBeInstanceOf(InvalidProtocolError)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('rejects if URL points to a valid cozy-stack but no valid Cozy instance', async () => {
|
|
370
|
+
fetch.mockOnceIf(
|
|
371
|
+
'https://missing.mycozy.cloud',
|
|
372
|
+
{},
|
|
373
|
+
{
|
|
374
|
+
status: 404
|
|
375
|
+
}
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
await expect(
|
|
379
|
+
rootCozyUrl(new URL('https://missing.mycozy.cloud'))
|
|
380
|
+
).rejects.toBeInstanceOf(InvalidCozyUrlError)
|
|
381
|
+
})
|
|
382
|
+
})
|
|
@@ -214,7 +214,7 @@ describe('use query', () => {
|
|
|
214
214
|
links: [new CozyLink(requestHandler)]
|
|
215
215
|
})
|
|
216
216
|
const error = new TypeError('Failed to fetch')
|
|
217
|
-
requestHandler.
|
|
217
|
+
requestHandler.mockRejectedValue(error)
|
|
218
218
|
const onError = jest.fn().mockReturnValue(() => true)
|
|
219
219
|
setupQuery({
|
|
220
220
|
customClient: client,
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,9 @@ var _exportNames = {
|
|
|
28
28
|
getReferencedById: true,
|
|
29
29
|
dehydrate: true,
|
|
30
30
|
generateWebLink: true,
|
|
31
|
+
rootCozyUrl: true,
|
|
32
|
+
InvalidCozyUrlError: true,
|
|
33
|
+
InvalidProtocolError: true,
|
|
31
34
|
cancelable: true,
|
|
32
35
|
isQueryLoading: true,
|
|
33
36
|
hasQueryBeenLoaded: true,
|
|
@@ -172,6 +175,24 @@ Object.defineProperty(exports, "generateWebLink", {
|
|
|
172
175
|
return _helpers2.generateWebLink;
|
|
173
176
|
}
|
|
174
177
|
});
|
|
178
|
+
Object.defineProperty(exports, "rootCozyUrl", {
|
|
179
|
+
enumerable: true,
|
|
180
|
+
get: function get() {
|
|
181
|
+
return _helpers2.rootCozyUrl;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
Object.defineProperty(exports, "InvalidCozyUrlError", {
|
|
185
|
+
enumerable: true,
|
|
186
|
+
get: function get() {
|
|
187
|
+
return _helpers2.InvalidCozyUrlError;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
Object.defineProperty(exports, "InvalidProtocolError", {
|
|
191
|
+
enumerable: true,
|
|
192
|
+
get: function get() {
|
|
193
|
+
return _helpers2.InvalidProtocolError;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
175
196
|
Object.defineProperty(exports, "cancelable", {
|
|
176
197
|
enumerable: true,
|
|
177
198
|
get: function get() {
|
package/dist/index.node.js
CHANGED
|
@@ -24,6 +24,9 @@ var _exportNames = {
|
|
|
24
24
|
HasManyTriggers: true,
|
|
25
25
|
dehydrate: true,
|
|
26
26
|
generateWebLink: true,
|
|
27
|
+
rootCozyUrl: true,
|
|
28
|
+
InvalidCozyUrlError: true,
|
|
29
|
+
InvalidProtocolError: true,
|
|
27
30
|
cancelable: true,
|
|
28
31
|
getQueryFromState: true,
|
|
29
32
|
Registry: true,
|
|
@@ -133,6 +136,24 @@ Object.defineProperty(exports, "generateWebLink", {
|
|
|
133
136
|
return _helpers.generateWebLink;
|
|
134
137
|
}
|
|
135
138
|
});
|
|
139
|
+
Object.defineProperty(exports, "rootCozyUrl", {
|
|
140
|
+
enumerable: true,
|
|
141
|
+
get: function get() {
|
|
142
|
+
return _helpers.rootCozyUrl;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
Object.defineProperty(exports, "InvalidCozyUrlError", {
|
|
146
|
+
enumerable: true,
|
|
147
|
+
get: function get() {
|
|
148
|
+
return _helpers.InvalidCozyUrlError;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
Object.defineProperty(exports, "InvalidProtocolError", {
|
|
152
|
+
enumerable: true,
|
|
153
|
+
get: function get() {
|
|
154
|
+
return _helpers.InvalidProtocolError;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
136
157
|
Object.defineProperty(exports, "cancelable", {
|
|
137
158
|
enumerable: true,
|
|
138
159
|
get: function get() {
|
package/dist/utils.spec.js
CHANGED
|
@@ -22,6 +22,7 @@ describe('cancelable', () => {
|
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
it('should reject with the rejection of the promise', done => {
|
|
25
|
+
jest.spyOn(console, 'log').mockImplementation()
|
|
25
26
|
const error = 'normal-rejection-from-cancelable-test'
|
|
26
27
|
const { reject, wrapped } = setup()
|
|
27
28
|
expect.assertions(1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-client",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.14.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.node.js",
|
|
6
6
|
"browser": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"cozy-device-helper": "^1.12.0",
|
|
22
22
|
"cozy-flags": "2.7.1",
|
|
23
23
|
"cozy-logger": "^1.6.0",
|
|
24
|
-
"cozy-stack-client": "^27.
|
|
24
|
+
"cozy-stack-client": "^27.14.1",
|
|
25
25
|
"json-stable-stringify": "^1.0.1",
|
|
26
26
|
"lodash": "^4.17.13",
|
|
27
27
|
"microee": "^0.0.6",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
|
|
72
72
|
},
|
|
73
73
|
"sideEffects": false,
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "786f6d73d3d1cc0f423776e2af642f8bdd3fba2c"
|
|
75
75
|
}
|
package/types/CozyClient.d.ts
CHANGED
|
@@ -652,6 +652,7 @@ declare class CozyClient {
|
|
|
652
652
|
* At any time put an error function
|
|
653
653
|
*
|
|
654
654
|
* @param {Function} [onError] - Set a callback for queries which are errored
|
|
655
|
+
* @throws {Error} onError should not have been defined yet
|
|
655
656
|
*/
|
|
656
657
|
setOnError(onError?: Function): void;
|
|
657
658
|
toJSON(): SnapshotClient;
|
package/types/helpers.d.ts
CHANGED
|
@@ -7,3 +7,12 @@ export function generateWebLink({ cozyUrl, searchParams: searchParamsOption, pat
|
|
|
7
7
|
slug: string;
|
|
8
8
|
subDomainType: string;
|
|
9
9
|
}): string;
|
|
10
|
+
export class InvalidProtocolError extends Error {
|
|
11
|
+
constructor(url: any);
|
|
12
|
+
url: any;
|
|
13
|
+
}
|
|
14
|
+
export class InvalidCozyUrlError extends Error {
|
|
15
|
+
constructor(url: any);
|
|
16
|
+
url: any;
|
|
17
|
+
}
|
|
18
|
+
export function rootCozyUrl(url: URL): Promise<URL>;
|
package/types/index.d.ts
CHANGED
|
@@ -19,6 +19,6 @@ export { manifest, models };
|
|
|
19
19
|
export { QueryDefinition, Q, Mutations, MutationTypes, getDoctypeFromOperation } from "./queries/dsl";
|
|
20
20
|
export { Association, HasMany, HasOne, HasOneInPlace, HasManyInPlace, HasManyTriggers } from "./associations";
|
|
21
21
|
export { isReferencedBy, isReferencedById, getReferencedBy, getReferencedById } from "./associations/helpers";
|
|
22
|
-
export { dehydrate, generateWebLink } from "./helpers";
|
|
22
|
+
export { dehydrate, generateWebLink, rootCozyUrl, InvalidCozyUrlError, InvalidProtocolError } from "./helpers";
|
|
23
23
|
export { cancelable, isQueryLoading, hasQueryBeenLoaded } from "./utils";
|
|
24
24
|
export { queryConnect, queryConnectFlat, withClient } from "./hoc";
|
package/types/index.node.d.ts
CHANGED
|
@@ -13,4 +13,4 @@ import * as models from "./models";
|
|
|
13
13
|
export { manifest, models };
|
|
14
14
|
export { QueryDefinition, Mutations, MutationTypes, getDoctypeFromOperation, Q } from "./queries/dsl";
|
|
15
15
|
export { Association, HasMany, HasOne, HasOneInPlace, HasManyInPlace, HasManyTriggers } from "./associations";
|
|
16
|
-
export { dehydrate, generateWebLink } from "./helpers";
|
|
16
|
+
export { dehydrate, generateWebLink, rootCozyUrl, InvalidCozyUrlError, InvalidProtocolError } from "./helpers";
|