cozy-client 29.1.3 → 31.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2550,7 +2550,7 @@ var CozyClient = /*#__PURE__*/function () {
2550
2550
  CozyClient.hooks = CozyClient.hooks || {};
2551
2551
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
2552
2552
 
2553
- CozyClient.version = "29.1.3";
2553
+ CozyClient.version = "31.0.0";
2554
2554
 
2555
2555
  _microee.default.mixin(CozyClient);
2556
2556
 
@@ -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.sendMeasureToDACC = exports.checkMeasureParams = void 0;
8
+ exports.fetchAggregatesFromDACC = exports.buildAggregateParams = exports.sendMeasureToDACC = exports.checkMeasureParams = exports.isCorrectDateFormat = void 0;
9
9
 
10
10
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
11
 
@@ -15,11 +15,31 @@ var _cozyLogger = _interopRequireDefault(require("cozy-logger"));
15
15
 
16
16
  var _types = require("../types");
17
17
 
18
+ var _CozyClient = _interopRequireDefault(require("../CozyClient"));
19
+
20
+ /**
21
+ * Check whether or not the given date is in YYYY-MM-DD format
22
+ *
23
+ * @param {string} date - The date to check
24
+ * @returns {boolean}
25
+ */
26
+ var isCorrectDateFormat = function isCorrectDateFormat(date) {
27
+ try {
28
+ var parsedDate = new Date(Date.parse(date));
29
+ return !!parsedDate.toISOString().startsWith(date);
30
+ } catch (err) {
31
+ return false;
32
+ }
33
+ };
18
34
  /**
19
35
  * Throw an errror if a DACC parameter is incorrect.
20
36
  *
21
37
  * @param { DACCMeasure} measure - The DACC measure
22
38
  */
39
+
40
+
41
+ exports.isCorrectDateFormat = isCorrectDateFormat;
42
+
23
43
  var checkMeasureParams = function checkMeasureParams(measure) {
24
44
  var createdBy = measure.createdBy,
25
45
  measureName = measure.measureName,
@@ -41,9 +61,7 @@ var checkMeasureParams = function checkMeasureParams(measure) {
41
61
  throw new Error('Missing parameter: startDate');
42
62
  }
43
63
 
44
- var parsedDate = new Date(Date.parse(startDate));
45
-
46
- if (!parsedDate.toISOString().startsWith(startDate)) {
64
+ if (!isCorrectDateFormat(startDate)) {
47
65
  throw new Error('Date should be in YYYY-MM-DD format');
48
66
  }
49
67
 
@@ -62,7 +80,7 @@ var checkMeasureParams = function checkMeasureParams(measure) {
62
80
  /**
63
81
  * Send measures to a DACC through a remote doctype
64
82
  *
65
- * @param {object} client - The CozyClient instance
83
+ * @param {CozyClient} client - The CozyClient instance
66
84
  * @param {string} remoteDoctype - The remote doctype to use
67
85
  * @param {DACCMeasure} measure - The DACC measure
68
86
  */
@@ -80,7 +98,8 @@ var sendMeasureToDACC = /*#__PURE__*/function () {
80
98
  checkMeasureParams(measure);
81
99
  _context.next = 4;
82
100
  return client.getStackClient().fetchJSON('POST', "/remote/".concat(remoteDoctype), {
83
- data: JSON.stringify(measure)
101
+ data: JSON.stringify(measure),
102
+ path: 'measure'
84
103
  });
85
104
 
86
105
  case 4:
@@ -105,5 +124,90 @@ var sendMeasureToDACC = /*#__PURE__*/function () {
105
124
  return _ref.apply(this, arguments);
106
125
  };
107
126
  }();
127
+ /**
128
+ * Build parameters to request DACC aggregate
129
+ *
130
+ *
131
+ * @typedef Params - The unformatted DACC aggregate params
132
+ * @property {string} [measureName] - The measure name
133
+ * @property {string} [startDate] - The measure start date
134
+ * @property {string} [endDate] - The measure end date
135
+ *
136
+ * @param {Params} params - The unformatted DACC aggregate params
137
+ * @returns {DACCAggregatesParams}
138
+ */
139
+
140
+
141
+ exports.sendMeasureToDACC = sendMeasureToDACC;
142
+
143
+ var buildAggregateParams = function buildAggregateParams(params) {
144
+ var measureName = params.measureName;
145
+
146
+ if (!measureName || typeof measureName !== 'string') {
147
+ throw new Error('Missing or wrong type parameter: measureName');
148
+ }
149
+
150
+ var startDate = params.startDate || new Date(0).toISOString();
151
+ var endDate = params.endDate || new Date(Date.now()).toISOString();
152
+
153
+ if (!isCorrectDateFormat(startDate) || !isCorrectDateFormat(endDate)) {
154
+ (0, _cozyLogger.default)('error', "Date should be in YYYY-MM-DD format but received: startDate: ".concat(startDate, " | endDate: ").concat(endDate));
155
+ throw new Error('Date should be in YYYY-MM-DD format');
156
+ }
157
+
158
+ return {
159
+ measureName: measureName,
160
+ startDate: startDate,
161
+ endDate: endDate
162
+ };
163
+ };
164
+ /**
165
+ * Send measures to a DACC through a remote doctype
166
+ *
167
+ * @param {CozyClient} client - The CozyClient instance
168
+ * @param {string} remoteDoctype - The remote doctype to use
169
+ * @param {DACCAggregatesParams} params - The request params
170
+ */
171
+
172
+
173
+ exports.buildAggregateParams = buildAggregateParams;
174
+
175
+ var fetchAggregatesFromDACC = /*#__PURE__*/function () {
176
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(client, remoteDoctype, params) {
177
+ var aggregateParams;
178
+ return _regenerator.default.wrap(function _callee2$(_context2) {
179
+ while (1) {
180
+ switch (_context2.prev = _context2.next) {
181
+ case 0:
182
+ _context2.prev = 0;
183
+ aggregateParams = buildAggregateParams(params);
184
+ _context2.next = 4;
185
+ return client.getStackClient().fetchJSON('POST', "/remote/".concat(remoteDoctype), {
186
+ data: JSON.stringify(aggregateParams),
187
+ path: 'aggregate'
188
+ });
189
+
190
+ case 4:
191
+ _context2.next = 10;
192
+ break;
193
+
194
+ case 6:
195
+ _context2.prev = 6;
196
+ _context2.t0 = _context2["catch"](0);
197
+ (0, _cozyLogger.default)('error', "Error while fetching aggregates to remote doctype: ".concat(_context2.t0.message));
198
+ throw _context2.t0;
199
+
200
+ case 10:
201
+ case "end":
202
+ return _context2.stop();
203
+ }
204
+ }
205
+ }, _callee2, null, [[0, 6]]);
206
+ }));
207
+
208
+ return function fetchAggregatesFromDACC(_x4, _x5, _x6) {
209
+ return _ref2.apply(this, arguments);
210
+ };
211
+ }();
108
212
 
109
- exports.sendMeasureToDACC = sendMeasureToDACC;
213
+ exports.fetchAggregatesFromDACC = fetchAggregatesFromDACC;
@@ -1,6 +1,6 @@
1
- import { checkMeasureParams } from './dacc'
1
+ import { checkMeasureParams, buildAggregateParams } from './dacc'
2
2
 
3
- describe('dacc', () => {
3
+ describe('checkMeasureParams', () => {
4
4
  const measure = {
5
5
  value: 42,
6
6
  measureName: 'theanswer',
@@ -104,3 +104,55 @@ describe('dacc', () => {
104
104
  ).toThrow()
105
105
  })
106
106
  })
107
+
108
+ describe('buildAggregateParams', () => {
109
+ beforeAll(() => {
110
+ jest
111
+ .spyOn(global.Date, 'now')
112
+ .mockImplementation(() => new Date(2022, 5, 1).valueOf())
113
+ })
114
+ it('should throw if measure name is not correct', () => {
115
+ expect(() => buildAggregateParams({})).toThrow()
116
+ expect(() => buildAggregateParams({ measurName: 42 })).toThrow()
117
+ })
118
+
119
+ it('should throw if dates are not correct', () => {
120
+ expect(() =>
121
+ buildAggregateParams({
122
+ measureName: 'test',
123
+ startDate: 'Lundi 10 août 2021'
124
+ })
125
+ ).toThrow()
126
+ expect(() =>
127
+ buildAggregateParams({
128
+ measureName: 'test',
129
+ endDate: 'Lundi 10 août 2021'
130
+ })
131
+ ).toThrow()
132
+ })
133
+ it('should build dates if none provided', () => {
134
+ expect(buildAggregateParams({ measureName: 'test' })).toEqual({
135
+ measureName: 'test',
136
+ startDate: '1970-01-01T00:00:00.000Z',
137
+ endDate: new Date(2022, 5, 1).toISOString()
138
+ })
139
+ })
140
+ it('should build dates if startDate provided', () => {
141
+ expect(
142
+ buildAggregateParams({ measureName: 'test', startDate: '2021-08-10' })
143
+ ).toEqual({
144
+ measureName: 'test',
145
+ startDate: '2021-08-10',
146
+ endDate: new Date(2022, 5, 1).toISOString()
147
+ })
148
+ })
149
+ it('should build dates if endDate provided', () => {
150
+ expect(
151
+ buildAggregateParams({ measureName: 'test', endDate: '2022-05-02' })
152
+ ).toEqual({
153
+ measureName: 'test',
154
+ startDate: '1970-01-01T00:00:00.000Z',
155
+ endDate: '2022-05-02'
156
+ })
157
+ })
158
+ })
@@ -29,6 +29,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
29
29
  * @property {Array} [indexedFields]
30
30
  * @property {Array} [sort]
31
31
  * @property {object} [selector]
32
+ * @property {object} [partialFilter]
33
+ * @property {Array} [fields]
32
34
  */
33
35
 
34
36
  /**
@@ -155,6 +157,42 @@ var QueryDefinition = /*#__PURE__*/function () {
155
157
  console.info("The use of the $ne operator is more efficient with a partial index.\n\n Selector: ".concat(selector));
156
158
  }
157
159
  }
160
+ /**
161
+ * Check if the selected fields are all included in the selectors
162
+ *
163
+ * @param {PartialQueryDefinition} obj - A partial QueryDefinition to check
164
+ */
165
+
166
+ }, {
167
+ key: "checkSelectFields",
168
+ value: function checkSelectFields(_ref2) {
169
+ var fields = _ref2.fields,
170
+ selector = _ref2.selector,
171
+ partialFilter = _ref2.partialFilter;
172
+
173
+ var _fields = this.fields || fields;
174
+
175
+ var _selector = this.selector || selector;
176
+
177
+ var _partialFilter = this.partialFilter || partialFilter;
178
+
179
+ if (!_fields || !_selector && !_partialFilter) {
180
+ return;
181
+ }
182
+
183
+ var mergedSelector = _objectSpread(_objectSpread({}, _selector), _partialFilter);
184
+
185
+ var selectorAttributes = Object.keys(mergedSelector);
186
+ var hasEveryFieldsInSelector = selectorAttributes.every(function (attribute) {
187
+ return _fields.includes(attribute);
188
+ });
189
+
190
+ if (!hasEveryFieldsInSelector) {
191
+ throw new Error("The .select should includes all the fields used in where or partialIndex.\n Please fix this query: fields: ".concat(JSON.stringify(this.toDefinition())));
192
+ }
193
+
194
+ return;
195
+ }
158
196
  /**
159
197
  * Query a single document on its id.
160
198
  *
@@ -202,6 +240,9 @@ var QueryDefinition = /*#__PURE__*/function () {
202
240
  selector: selector
203
241
  });
204
242
  this.checkSelector(selector);
243
+ this.checkSelectFields({
244
+ selector: selector
245
+ });
205
246
  return new QueryDefinition(_objectSpread(_objectSpread({}, this.toDefinition()), {}, {
206
247
  selector: selector
207
248
  }));
@@ -216,6 +257,9 @@ var QueryDefinition = /*#__PURE__*/function () {
216
257
  }, {
217
258
  key: "select",
218
259
  value: function select(fields) {
260
+ this.checkSelectFields({
261
+ fields: fields
262
+ });
219
263
  return new QueryDefinition(_objectSpread(_objectSpread({}, this.toDefinition()), {}, {
220
264
  fields: fields
221
265
  }));
@@ -250,6 +294,9 @@ var QueryDefinition = /*#__PURE__*/function () {
250
294
  }, {
251
295
  key: "partialIndex",
252
296
  value: function partialIndex(partialFilter) {
297
+ this.checkSelectFields({
298
+ partialFilter: partialFilter
299
+ });
253
300
  return new QueryDefinition(_objectSpread(_objectSpread({}, this.toDefinition()), {}, {
254
301
  partialFilter: partialFilter
255
302
  }));
@@ -107,4 +107,43 @@ describe('QueryDefinition', () => {
107
107
  Q('io.cozy.files').where({ _id: { $ne: 'io.cozy.root-id' } })
108
108
  expect(console.info).toHaveBeenCalledTimes(1)
109
109
  })
110
+
111
+ it('should throw an error when there is a select without all the fields in selector', () => {
112
+ const query = () =>
113
+ Q('io.cozy.files')
114
+ .where({ name: 'saymyname' })
115
+ .select(['size'])
116
+ expect(() => query()).toThrow()
117
+ })
118
+ it('should throw an error when there is a select without all the fields in partial index', () => {
119
+ const query = () =>
120
+ Q('io.cozy.files')
121
+ .where({ size: 42 })
122
+ .partialIndex({ name: { $exists: true } })
123
+ .select(['size'])
124
+ expect(() => query()).toThrow()
125
+ })
126
+ it('should throw an error when there is a select without all the fields in nor selector nor partial index', () => {
127
+ const query = () =>
128
+ Q('io.cozy.files')
129
+ .where({ size: 42 })
130
+ .partialIndex({ name: { $exists: true } })
131
+ .select(['date'])
132
+ expect(() => query()).toThrow()
133
+ })
134
+ it('should not throw when there is a select with all the fields in selector and partial index', () => {
135
+ const query = () =>
136
+ Q('io.cozy.files')
137
+ .where(
138
+ {
139
+ size: 42
140
+ },
141
+ {
142
+ date: '2021-01-01'
143
+ }
144
+ )
145
+ .partialIndex({ name: { $exists: true } })
146
+ .select(['date', 'size', 'name', 'trashed'])
147
+ expect(() => query()).not.toThrow()
148
+ })
110
149
  })
package/dist/types.js CHANGED
@@ -329,6 +329,15 @@ var _dsl = require("./queries/dsl");
329
329
  * @property {object} group3 - Should be a {key: value} where the key is set in the measure definition.
330
330
  */
331
331
 
332
+ /**
333
+ * @typedef {object} DACCAggregatesParams
334
+ * See https://github.com/cozy/DACC
335
+ *
336
+ * @property {string} measureName - It must match an existing measure name on the DACC server
337
+ * @property {string} startDate - Start of the aggregation period. Should be in YYYY-MM-DD format
338
+ * @property {string} endDate - End of the aggregation period. Should be in YYYY-MM-DD format
339
+ */
340
+
332
341
  /**
333
342
  * Receives the URL to present to the user as a parameter, and should return a promise that resolves with the URL the user was redirected to after accepting the permissions.
334
343
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "29.1.3",
3
+ "version": "31.0.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.node.js",
6
6
  "browser": "dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "@types/jest": "^26.0.20",
19
19
  "@types/lodash": "^4.14.170",
20
20
  "btoa": "^1.2.1",
21
- "cozy-stack-client": "^29.1.0",
21
+ "cozy-stack-client": "^31.0.0",
22
22
  "json-stable-stringify": "^1.0.1",
23
23
  "lodash": "^4.17.13",
24
24
  "microee": "^0.0.6",
@@ -73,5 +73,5 @@
73
73
  "react-native-ios11-devicecheck": "https://github.com/cozy/react-native-devicecheck#app-attest-v0.1"
74
74
  },
75
75
  "sideEffects": false,
76
- "gitHead": "5471636693d11500031cd1cdb3d7217f5ae9871c"
76
+ "gitHead": "3d72a338ddcd4cfbedc9203634dff5125c5e3fd1"
77
77
  }
@@ -1,3 +1,25 @@
1
+ export function isCorrectDateFormat(date: string): boolean;
1
2
  export function checkMeasureParams(measure: DACCMeasure): void;
2
- export function sendMeasureToDACC(client: object, remoteDoctype: string, measure: DACCMeasure): Promise<void>;
3
+ export function sendMeasureToDACC(client: CozyClient, remoteDoctype: string, measure: DACCMeasure): Promise<void>;
4
+ export function buildAggregateParams(params: Params): DACCAggregatesParams;
5
+ export function fetchAggregatesFromDACC(client: CozyClient, remoteDoctype: string, params: DACCAggregatesParams): Promise<void>;
6
+ /**
7
+ * - The unformatted DACC aggregate params
8
+ */
9
+ export type Params = {
10
+ /**
11
+ * - The measure name
12
+ */
13
+ measureName?: string;
14
+ /**
15
+ * - The measure start date
16
+ */
17
+ startDate?: string;
18
+ /**
19
+ * - The measure end date
20
+ */
21
+ endDate?: string;
22
+ };
3
23
  import { DACCMeasure } from "../types";
24
+ import CozyClient from "../CozyClient";
25
+ import { DACCAggregatesParams } from "../types";
@@ -68,6 +68,8 @@ export type PartialQueryDefinition = {
68
68
  indexedFields?: any[];
69
69
  sort?: any[];
70
70
  selector?: object;
71
+ partialFilter?: object;
72
+ fields?: any[];
71
73
  };
72
74
  export type MangoSelector = any;
73
75
  export type MangoPartialFilter = any;
@@ -78,6 +80,8 @@ import { Doctype } from "../types";
78
80
  * @property {Array} [indexedFields]
79
81
  * @property {Array} [sort]
80
82
  * @property {object} [selector]
83
+ * @property {object} [partialFilter]
84
+ * @property {Array} [fields]
81
85
  */
82
86
  /**
83
87
  * @typedef {object} MangoSelector
@@ -162,6 +166,12 @@ export class QueryDefinition {
162
166
  * @returns {void}
163
167
  */
164
168
  checkSelector(selector: MangoSelector): void;
169
+ /**
170
+ * Check if the selected fields are all included in the selectors
171
+ *
172
+ * @param {PartialQueryDefinition} obj - A partial QueryDefinition to check
173
+ */
174
+ checkSelectFields({ fields, selector, partialFilter }: PartialQueryDefinition): void;
165
175
  /**
166
176
  * Query a single document on its id.
167
177
  *
package/types/types.d.ts CHANGED
@@ -390,6 +390,23 @@ export type DACCMeasure = {
390
390
  */
391
391
  group3: object;
392
392
  };
393
+ /**
394
+ * See https://github.com/cozy/DACC
395
+ */
396
+ export type DACCAggregatesParams = {
397
+ /**
398
+ * - It must match an existing measure name on the DACC server
399
+ */
400
+ measureName: string;
401
+ /**
402
+ * - Start of the aggregation period. Should be in YYYY-MM-DD format
403
+ */
404
+ startDate: string;
405
+ /**
406
+ * - End of the aggregation period. Should be in YYYY-MM-DD format
407
+ */
408
+ endDate: string;
409
+ };
393
410
  /**
394
411
  * Receives the URL to present to the user as a parameter, and should return a promise that resolves with the URL the user was redirected to after accepting the permissions.
395
412
  */