cozy-client 57.2.0 → 57.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CozyClient.js +1 -1
- package/dist/store/documents.js +59 -27
- package/dist/store/documents.spec.js +66 -52
- package/package.json +4 -2
- package/types/store/documents.d.ts +1 -1
package/dist/CozyClient.js
CHANGED
|
@@ -3097,7 +3097,7 @@ var CozyClient = /*#__PURE__*/function () {
|
|
|
3097
3097
|
CozyClient.hooks = CozyClient.hooks || {};
|
|
3098
3098
|
CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
|
|
3099
3099
|
|
|
3100
|
-
CozyClient.version = "57.
|
|
3100
|
+
CozyClient.version = "57.3.0";
|
|
3101
3101
|
|
|
3102
3102
|
_microee.default.mixin(CozyClient);
|
|
3103
3103
|
|
package/dist/store/documents.js
CHANGED
|
@@ -9,15 +9,13 @@ exports.extractAndMergeDocument = exports.getCollectionFromSlice = exports.getDo
|
|
|
9
9
|
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
11
|
|
|
12
|
-
var _keyBy = _interopRequireDefault(require("lodash/keyBy"));
|
|
13
|
-
|
|
14
12
|
var _get = _interopRequireDefault(require("lodash/get"));
|
|
15
13
|
|
|
16
|
-
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
17
|
-
|
|
18
14
|
var _omit = _interopRequireDefault(require("lodash/omit"));
|
|
19
15
|
|
|
20
|
-
var
|
|
16
|
+
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
|
|
17
|
+
|
|
18
|
+
var _deepmerge = _interopRequireDefault(require("@fastify/deepmerge"));
|
|
21
19
|
|
|
22
20
|
var _logger = _interopRequireDefault(require("../logger"));
|
|
23
21
|
|
|
@@ -33,6 +31,8 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
33
31
|
|
|
34
32
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
35
33
|
|
|
34
|
+
var deepmergeFn = (0, _deepmerge.default)();
|
|
35
|
+
|
|
36
36
|
var storeDocument = function storeDocument(state, document) {
|
|
37
37
|
var type = document._type;
|
|
38
38
|
|
|
@@ -54,7 +54,7 @@ var storeDocument = function storeDocument(state, document) {
|
|
|
54
54
|
|
|
55
55
|
var existingDoc = (0, _get.default)(state, [type, (0, _helpers.properId)(document)]);
|
|
56
56
|
|
|
57
|
-
if ((0,
|
|
57
|
+
if ((0, _fastDeepEqual.default)(existingDoc, document)) {
|
|
58
58
|
return state;
|
|
59
59
|
} else {
|
|
60
60
|
return _objectSpread(_objectSpread({}, state), {}, (0, _defineProperty2.default)({}, type, _objectSpread(_objectSpread({}, state[type]), {}, (0, _defineProperty2.default)({}, (0, _helpers.properId)(document), mergeDocumentsWithRelationships(existingDoc, document)))));
|
|
@@ -203,44 +203,76 @@ var getCollectionFromSlice = function getCollectionFromSlice() {
|
|
|
203
203
|
|
|
204
204
|
return Object.values(state[doctype]);
|
|
205
205
|
};
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
/**
|
|
207
|
+
*
|
|
208
|
+
* This method has been created in order to get a returned object
|
|
209
|
+
in `data` with the full set on information coming potentially from
|
|
209
210
|
`included`
|
|
210
|
-
|
|
211
|
+
|
|
211
212
|
This method should be somewhere else. The `document` shall not be
|
|
212
213
|
dealt with included / data and so on.
|
|
213
|
-
|
|
214
|
+
|
|
214
215
|
This method takes `data` and `included` and merge both sources
|
|
215
216
|
together. It should be always up-to-date. The returned object
|
|
216
217
|
will be as full of information as it can be.
|
|
217
|
-
|
|
218
|
+
|
|
219
|
+
* @param {Array<import('../types').CozyClientDocument>} newData - Queries documents
|
|
220
|
+
* @param {import("../types").DocumentsStateSlice} updatedStateWithIncluded documents' state
|
|
221
|
+
* @returns {import("../types").DocumentsStateSlice} the merged documents state
|
|
222
|
+
*/
|
|
218
223
|
|
|
219
224
|
|
|
220
225
|
exports.getCollectionFromSlice = getCollectionFromSlice;
|
|
221
226
|
|
|
222
|
-
var extractAndMergeDocument = function extractAndMergeDocument(
|
|
223
|
-
var doctype =
|
|
227
|
+
var extractAndMergeDocument = function extractAndMergeDocument(newData, updatedStateWithIncluded) {
|
|
228
|
+
var doctype = newData[0]._type;
|
|
224
229
|
|
|
225
230
|
if (!doctype) {
|
|
226
|
-
_logger.default.info('Document without _type',
|
|
231
|
+
_logger.default.info('Document without _type', newData[0]);
|
|
227
232
|
|
|
228
233
|
throw new Error('Document without _type');
|
|
229
|
-
}
|
|
234
|
+
} // Index docs by id, for faster retrieval
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
var newDocsMap = new Map(newData.map(function (doc) {
|
|
238
|
+
return [(0, _helpers.properId)(doc), doc];
|
|
239
|
+
}));
|
|
240
|
+
var mergedState = Object.assign({}, updatedStateWithIncluded); // FIXME: this was introduced for a bug in banks, but it does not look useful
|
|
241
|
+
|
|
242
|
+
mergedState[doctype] = Object.assign({}, updatedStateWithIncluded[doctype]);
|
|
230
243
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
Object.values(sortedData).map(function (data) {
|
|
235
|
-
var id = (0, _helpers.properId)(data);
|
|
244
|
+
if (!mergedState[doctype]) {
|
|
245
|
+
mergedState[doctype] = {};
|
|
246
|
+
}
|
|
236
247
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
248
|
+
var haveDocumentsChanged = false;
|
|
249
|
+
newDocsMap.forEach(function (newDoc, key) {
|
|
250
|
+
var id = key;
|
|
251
|
+
var currentDoc = mergedState[doctype][id];
|
|
252
|
+
|
|
253
|
+
if (!currentDoc) {
|
|
254
|
+
mergedState[doctype][id] = newDoc;
|
|
255
|
+
haveDocumentsChanged = true;
|
|
256
|
+
} else if (!(0, _fastDeepEqual.default)(currentDoc, newDoc)) {
|
|
257
|
+
// XXX Here we check if the doc has changed. Note this would be way faster
|
|
258
|
+
// by just relying on revision change, but:
|
|
259
|
+
// - it does not work if the new doc is partial (i.e. retrieved with a .select query)
|
|
260
|
+
// - some documents might change without a rev change: typically the thumbnails links
|
|
261
|
+
// in io.cozy.files, and the io.cozy.settings.instance doc, with additional
|
|
262
|
+
// fields added by the stack
|
|
263
|
+
// - some documents don't have any revision
|
|
264
|
+
mergedState[doctype][id] = deepmergeFn(mergedState[doctype][id], newDoc);
|
|
265
|
+
haveDocumentsChanged = true;
|
|
241
266
|
}
|
|
242
|
-
});
|
|
243
|
-
|
|
267
|
+
}); // XXX If there is any state change, the updated state should have a new reference,
|
|
268
|
+
// as we heavily rely on referential equality.
|
|
269
|
+
// Conversely, if there is no change, the same reference should be kept
|
|
270
|
+
|
|
271
|
+
if (haveDocumentsChanged) {
|
|
272
|
+
return mergedState;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return updatedStateWithIncluded;
|
|
244
276
|
};
|
|
245
277
|
|
|
246
278
|
exports.extractAndMergeDocument = extractAndMergeDocument;
|
|
@@ -4,11 +4,9 @@ import {
|
|
|
4
4
|
} from './documents'
|
|
5
5
|
|
|
6
6
|
describe('extractAndMerge', () => {
|
|
7
|
-
const data =
|
|
8
|
-
|
|
9
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
7
|
+
const data = [
|
|
8
|
+
{
|
|
10
9
|
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
11
|
-
type: 'io.cozy.files',
|
|
12
10
|
_type: 'io.cozy.files',
|
|
13
11
|
blabla: 'new field',
|
|
14
12
|
cozyMetadata: {
|
|
@@ -18,24 +16,20 @@ describe('extractAndMerge', () => {
|
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
18
|
},
|
|
21
|
-
|
|
22
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
23
|
-
type: 'io.cozy.files',
|
|
24
|
-
_type: 'io.cozy.files',
|
|
19
|
+
{
|
|
25
20
|
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
21
|
+
_type: 'io.cozy.files',
|
|
26
22
|
blibli: 'another new field'
|
|
27
23
|
}
|
|
28
|
-
|
|
24
|
+
]
|
|
29
25
|
const updatedStateWithIncluded = {
|
|
30
26
|
'io.cozy.files': {
|
|
31
27
|
b6ff135b34e041ffb2d4a4865f3e0a53: {
|
|
32
|
-
attributes: {
|
|
33
|
-
type: 'file',
|
|
34
|
-
name: 'IMG_0016.PNG',
|
|
35
|
-
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6'
|
|
36
|
-
},
|
|
37
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
38
28
|
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
29
|
+
_type: 'io.cozy.files',
|
|
30
|
+
name: 'IMG_0016.PNG',
|
|
31
|
+
type: 'file',
|
|
32
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
39
33
|
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e0a53' },
|
|
40
34
|
meta: { rev: '5-87840eceaab358e38aa8b6bb0d4577b1' },
|
|
41
35
|
relationships: {
|
|
@@ -43,8 +37,6 @@ describe('extractAndMerge', () => {
|
|
|
43
37
|
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
44
38
|
}
|
|
45
39
|
},
|
|
46
|
-
type: 'io.cozy.files',
|
|
47
|
-
_type: 'io.cozy.files',
|
|
48
40
|
cozyMetadata: {
|
|
49
41
|
updated_at: '987654',
|
|
50
42
|
updatedByApps: {
|
|
@@ -53,22 +45,18 @@ describe('extractAndMerge', () => {
|
|
|
53
45
|
}
|
|
54
46
|
},
|
|
55
47
|
b6ff135b34e041ffb2d4a4865f3e235f: {
|
|
56
|
-
attributes: {
|
|
57
|
-
type: 'file',
|
|
58
|
-
name: 'IMG_0054.PNG',
|
|
59
|
-
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6'
|
|
60
|
-
},
|
|
61
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
62
48
|
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
49
|
+
_type: 'io.cozy.files',
|
|
50
|
+
type: 'file',
|
|
51
|
+
name: 'IMG_0054.PNG',
|
|
52
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
63
53
|
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e235f' },
|
|
64
54
|
meta: { rev: '5-ca91c0dc02dafb38eb56070c1d80d62c' },
|
|
65
55
|
relationships: {
|
|
66
56
|
parent: {
|
|
67
57
|
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
68
58
|
}
|
|
69
|
-
}
|
|
70
|
-
type: 'io.cozy.files',
|
|
71
|
-
_type: 'io.cozy.files'
|
|
59
|
+
}
|
|
72
60
|
}
|
|
73
61
|
}
|
|
74
62
|
}
|
|
@@ -84,11 +72,9 @@ describe('extractAndMerge', () => {
|
|
|
84
72
|
b6ff135b34e041ffb2d4a4865f3e0a53: {
|
|
85
73
|
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
86
74
|
_type: 'io.cozy.files',
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
type: 'file'
|
|
91
|
-
},
|
|
75
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
76
|
+
name: 'IMG_0016.PNG',
|
|
77
|
+
type: 'file',
|
|
92
78
|
blabla: 'new field',
|
|
93
79
|
cozyMetadata: {
|
|
94
80
|
created_at: '123456',
|
|
@@ -98,34 +84,28 @@ describe('extractAndMerge', () => {
|
|
|
98
84
|
date: '2019-06-11T01:02:03Z'
|
|
99
85
|
}
|
|
100
86
|
},
|
|
101
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
102
87
|
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e0a53' },
|
|
103
88
|
meta: { rev: '5-87840eceaab358e38aa8b6bb0d4577b1' },
|
|
104
89
|
relationships: {
|
|
105
90
|
parent: {
|
|
106
91
|
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
107
92
|
}
|
|
108
|
-
}
|
|
109
|
-
type: 'io.cozy.files'
|
|
93
|
+
}
|
|
110
94
|
},
|
|
111
95
|
b6ff135b34e041ffb2d4a4865f3e235f: {
|
|
112
96
|
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
113
97
|
_type: 'io.cozy.files',
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
type: 'file'
|
|
118
|
-
},
|
|
98
|
+
dir_id: '7d2f9c24cd345ce3171bf71f401e80c6',
|
|
99
|
+
name: 'IMG_0054.PNG',
|
|
100
|
+
type: 'file',
|
|
119
101
|
blibli: 'another new field',
|
|
120
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
121
102
|
links: { self: '/files/b6ff135b34e041ffb2d4a4865f3e235f' },
|
|
122
103
|
meta: { rev: '5-ca91c0dc02dafb38eb56070c1d80d62c' },
|
|
123
104
|
relationships: {
|
|
124
105
|
parent: {
|
|
125
106
|
links: { related: '/files/7d2f9c24cd345ce3171bf71f401e80c6' }
|
|
126
107
|
}
|
|
127
|
-
}
|
|
128
|
-
type: 'io.cozy.files'
|
|
108
|
+
}
|
|
129
109
|
}
|
|
130
110
|
}
|
|
131
111
|
}
|
|
@@ -171,20 +151,16 @@ describe('extractAndMerge', () => {
|
|
|
171
151
|
'even if the mergedData is the same, because reselect createSelector update ' +
|
|
172
152
|
'according to object reference, not only value',
|
|
173
153
|
() => {
|
|
174
|
-
const dataAlreadyIncludedInUpdatedStateWithIncluded =
|
|
175
|
-
|
|
176
|
-
id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
154
|
+
const dataAlreadyIncludedInUpdatedStateWithIncluded = [
|
|
155
|
+
{
|
|
177
156
|
_id: 'b6ff135b34e041ffb2d4a4865f3e0a53',
|
|
178
|
-
type: 'io.cozy.files',
|
|
179
157
|
_type: 'io.cozy.files'
|
|
180
158
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
_type: 'io.cozy.files',
|
|
185
|
-
_id: 'b6ff135b34e041ffb2d4a4865f3e235f'
|
|
159
|
+
{
|
|
160
|
+
_id: 'b6ff135b34e041ffb2d4a4865f3e235f',
|
|
161
|
+
_type: 'io.cozy.files'
|
|
186
162
|
}
|
|
187
|
-
|
|
163
|
+
]
|
|
188
164
|
|
|
189
165
|
const returnedDatas = extractAndMergeDocument(
|
|
190
166
|
dataAlreadyIncludedInUpdatedStateWithIncluded,
|
|
@@ -202,6 +178,44 @@ describe('extractAndMerge', () => {
|
|
|
202
178
|
)
|
|
203
179
|
}
|
|
204
180
|
)
|
|
181
|
+
it('should keep state reference in case no document has changed', () => {
|
|
182
|
+
const newDoc = { ...data[0] }
|
|
183
|
+
|
|
184
|
+
const mergedState = extractAndMergeDocument(
|
|
185
|
+
[newDoc],
|
|
186
|
+
updatedStateWithIncluded
|
|
187
|
+
)
|
|
188
|
+
expect(mergedState === updatedStateWithIncluded)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('should have different state reference if a new document is added', () => {
|
|
192
|
+
const newDoc = {
|
|
193
|
+
_id: '1234',
|
|
194
|
+
_type: 'io.cozy.files',
|
|
195
|
+
name: 'New doc'
|
|
196
|
+
}
|
|
197
|
+
const mergedState = extractAndMergeDocument(
|
|
198
|
+
[newDoc],
|
|
199
|
+
updatedStateWithIncluded
|
|
200
|
+
)
|
|
201
|
+
expect(mergedState !== updatedStateWithIncluded)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('should have different state reference if an existing document have changed', () => {
|
|
205
|
+
const newDoc = {
|
|
206
|
+
...data[0],
|
|
207
|
+
cozyMetadata: {
|
|
208
|
+
...data[0].cozyMetadata,
|
|
209
|
+
updatedByApps: '2025-01-01'
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const mergedState = extractAndMergeDocument(
|
|
214
|
+
[newDoc],
|
|
215
|
+
updatedStateWithIncluded
|
|
216
|
+
)
|
|
217
|
+
expect(mergedState !== updatedStateWithIncluded)
|
|
218
|
+
})
|
|
205
219
|
})
|
|
206
220
|
|
|
207
221
|
describe('mergeDocumentsWithRelationships', () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-client",
|
|
3
|
-
"version": "57.
|
|
3
|
+
"version": "57.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.node.js",
|
|
6
6
|
"browser": "dist/index.js",
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@cozy/minilog": "1.0.0",
|
|
18
|
+
"@fastify/deepmerge": "^2.0.2",
|
|
18
19
|
"@types/jest": "^26.0.20",
|
|
19
20
|
"@types/lodash": "^4.14.170",
|
|
20
21
|
"btoa": "^1.2.1",
|
|
21
22
|
"cozy-stack-client": "^57.2.0",
|
|
22
23
|
"date-fns": "2.29.3",
|
|
24
|
+
"fast-deep-equal": "^3.1.3",
|
|
23
25
|
"json-stable-stringify": "^1.0.1",
|
|
24
26
|
"lodash": "^4.17.13",
|
|
25
27
|
"microee": "^0.0.6",
|
|
@@ -72,5 +74,5 @@
|
|
|
72
74
|
"react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
|
|
73
75
|
},
|
|
74
76
|
"sideEffects": false,
|
|
75
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "aa4094d6cb80bbd4173cc82fb1a2a06406718b5e"
|
|
76
78
|
}
|
|
@@ -3,5 +3,5 @@ export default documents;
|
|
|
3
3
|
export function getDocumentFromSlice(state: import('../types').DocumentsStateSlice, doctype: string, id: string): import('../types').CozyClientDocument;
|
|
4
4
|
export function getDocumentsFromSlice(state: import('../types').DocumentsStateSlice, doctype: string, ids: Array<string>): Array<import('../types').CozyClientDocument>;
|
|
5
5
|
export function getCollectionFromSlice(state: {}, doctype: any): any[];
|
|
6
|
-
export function extractAndMergeDocument(
|
|
6
|
+
export function extractAndMergeDocument(newData: Array<import('../types').CozyClientDocument>, updatedStateWithIncluded: import("../types").DocumentsStateSlice): import("../types").DocumentsStateSlice;
|
|
7
7
|
declare function documents(state: {}, action: any): any;
|