cozy-client 60.28.2 → 60.29.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.
@@ -3126,7 +3126,7 @@ var CozyClient = /*#__PURE__*/function () {
3126
3126
  CozyClient.hooks = CozyClient.hooks || {};
3127
3127
  CozyClient.fetchPolicies = _policies.default; //COZY_CLIENT_VERSION_PACKAGE in replaced by babel. See babel config
3128
3128
 
3129
- CozyClient.version = "60.28.2";
3129
+ CozyClient.version = "60.29.0";
3130
3130
 
3131
3131
  _microee.default.mixin(CozyClient);
3132
3132
 
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ var _exportNames = {
12
12
  StackLink: true,
13
13
  WebFlagshipLink: true,
14
14
  DataProxyLink: true,
15
+ resolveForceLink: true,
15
16
  compose: true,
16
17
  QueryDefinition: true,
17
18
  Q: true,
@@ -94,6 +95,12 @@ Object.defineProperty(exports, "DataProxyLink", {
94
95
  return _DataProxyLink.default;
95
96
  }
96
97
  });
98
+ Object.defineProperty(exports, "resolveForceLink", {
99
+ enumerable: true,
100
+ get: function get() {
101
+ return _forceLink.resolveForceLink;
102
+ }
103
+ });
97
104
  Object.defineProperty(exports, "compose", {
98
105
  enumerable: true,
99
106
  get: function get() {
@@ -400,6 +407,8 @@ var _WebFlagshipLink = _interopRequireDefault(require("./links/WebFlagshipLink")
400
407
 
401
408
  var _DataProxyLink = _interopRequireDefault(require("./links/DataProxyLink"));
402
409
 
410
+ var _forceLink = require("./links/forceLink");
411
+
403
412
  var _flow = _interopRequireDefault(require("lodash/flow"));
404
413
 
405
414
  var _dsl = require("./queries/dsl");
@@ -40,7 +40,8 @@ var _exportNames = {
40
40
  models: true,
41
41
  fetchPolicies: true,
42
42
  webPerformanceApi: true,
43
- defaultPerformanceApi: true
43
+ defaultPerformanceApi: true,
44
+ resolveForceLink: true
44
45
  };
45
46
  Object.defineProperty(exports, "default", {
46
47
  enumerable: true,
@@ -234,6 +235,12 @@ Object.defineProperty(exports, "defaultPerformanceApi", {
234
235
  return _defaultPerformanceApi.defaultPerformanceApi;
235
236
  }
236
237
  });
238
+ Object.defineProperty(exports, "resolveForceLink", {
239
+ enumerable: true,
240
+ get: function get() {
241
+ return _forceLink.resolveForceLink;
242
+ }
243
+ });
237
244
  exports.models = exports.manifest = void 0;
238
245
 
239
246
  var _CozyClient = _interopRequireDefault(require("./CozyClient"));
@@ -300,4 +307,6 @@ var _policies = _interopRequireDefault(require("./policies"));
300
307
 
301
308
  var _webPerformanceApi = require("./performances/webPerformanceApi");
302
309
 
303
- var _defaultPerformanceApi = require("./performances/defaultPerformanceApi");
310
+ var _defaultPerformanceApi = require("./performances/defaultPerformanceApi");
311
+
312
+ var _forceLink = require("./links/forceLink");
@@ -126,6 +126,17 @@ var CozyLink = /*#__PURE__*/function () {
126
126
 
127
127
  return reset;
128
128
  }()
129
+ /**
130
+ * Stable name used to target this link via the `forceLink` query option.
131
+ *
132
+ * @returns {string|undefined}
133
+ */
134
+
135
+ }, {
136
+ key: "name",
137
+ get: function get() {
138
+ return undefined;
139
+ }
129
140
  }]);
130
141
  return CozyLink;
131
142
  }();
@@ -16,6 +16,11 @@ describe('CozyLink', () => {
16
16
  expect(link.request('dummyOperation')).toBe('foobarbaz')
17
17
  })
18
18
 
19
+ it('has name === undefined by default', () => {
20
+ const link = new CozyLink()
21
+ expect(link.name).toBe(undefined)
22
+ })
23
+
19
24
  describe('default last link', () => {
20
25
  it('should throw an error when called without result', () => {
21
26
  const link = chain([
@@ -29,6 +29,8 @@ var _CozyLink2 = _interopRequireDefault(require("./CozyLink"));
29
29
 
30
30
  var _cozyLogger = _interopRequireDefault(require("cozy-logger"));
31
31
 
32
+ var _forceLink = require("./forceLink");
33
+
32
34
  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
35
 
34
36
  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; } }
@@ -124,18 +126,29 @@ var DataProxyLink = /*#__PURE__*/function (_CozyLink) {
124
126
  var _this$dataproxy,
125
127
  _this2 = this;
126
128
 
129
+ var forceLink;
127
130
  return _regenerator.default.wrap(function _callee2$(_context2) {
128
131
  while (1) {
129
132
  switch (_context2.prev = _context2.next) {
130
133
  case 0:
134
+ forceLink = (0, _forceLink.resolveForceLink)(options);
135
+
136
+ if (!(forceLink && forceLink !== this.name)) {
137
+ _context2.next = 3;
138
+ break;
139
+ }
140
+
141
+ return _context2.abrupt("return", forward(operation, options));
142
+
143
+ case 3:
131
144
  if (!((_this$dataproxy = this.dataproxy) !== null && _this$dataproxy !== void 0 && _this$dataproxy.requestLink)) {
132
- _context2.next = 2;
145
+ _context2.next = 5;
133
146
  break;
134
147
  }
135
148
 
136
149
  return _context2.abrupt("return", this.doRequest(operation, options));
137
150
 
138
- case 2:
151
+ case 5:
139
152
  return _context2.abrupt("return", new Promise(function (resolve, reject) {
140
153
  _this2._queue.push({
141
154
  operation: operation,
@@ -145,7 +158,7 @@ var DataProxyLink = /*#__PURE__*/function (_CozyLink) {
145
158
  });
146
159
  }));
147
160
 
148
- case 3:
161
+ case 6:
149
162
  case "end":
150
163
  return _context2.stop();
151
164
  }
@@ -295,6 +308,11 @@ var DataProxyLink = /*#__PURE__*/function (_CozyLink) {
295
308
 
296
309
  return _flushQueue;
297
310
  }()
311
+ }, {
312
+ key: "name",
313
+ get: function get() {
314
+ return 'dataproxy';
315
+ }
298
316
  }]);
299
317
  return DataProxyLink;
300
318
  }(_CozyLink2.default);
@@ -1,6 +1,54 @@
1
1
  /** @jest-environment jsdom */
2
2
  import DataProxyLink from './DataProxyLink'
3
3
 
4
+ describe('DataProxyLink name', () => {
5
+ it('should expose a stable name', () => {
6
+ expect(new DataProxyLink().name).toBe('dataproxy')
7
+ })
8
+ })
9
+
10
+ describe('DataProxyLink forceLink', () => {
11
+ it('forwards a forceStack:true query (routes away from dataproxy)', async () => {
12
+ const link = new DataProxyLink()
13
+ const forwardFn = jest.fn().mockResolvedValue(null)
14
+ await link.request(
15
+ { doctype: 'io.cozy.files' },
16
+ { forceStack: true },
17
+ null,
18
+ forwardFn
19
+ )
20
+ expect(forwardFn).toHaveBeenCalled()
21
+ })
22
+
23
+ it('handles when forceLink targets it', async () => {
24
+ const link = new DataProxyLink()
25
+ link.registerDataProxy({
26
+ requestLink: jest.fn().mockResolvedValue({ data: [{ _id: '1' }] })
27
+ })
28
+ const forward = jest.fn()
29
+ const res = await link.request(
30
+ { doctype: 'io.cozy.files' },
31
+ { forceLink: 'dataproxy' },
32
+ undefined,
33
+ forward
34
+ )
35
+ expect(forward).not.toHaveBeenCalled()
36
+ expect(res).toEqual({ data: [{ _id: '1' }] })
37
+ })
38
+ it('forwards when forceLink targets another link', async () => {
39
+ const link = new DataProxyLink()
40
+ const forward = jest.fn().mockResolvedValue('forwarded')
41
+ expect(
42
+ await link.request(
43
+ { doctype: 'io.cozy.files' },
44
+ { forceLink: 'stack' },
45
+ undefined,
46
+ forward
47
+ )
48
+ ).toBe('forwarded')
49
+ })
50
+ })
51
+
4
52
  describe('DataProxyLink queueing', () => {
5
53
  it('should directly call dataproxy requestLink if available', async () => {
6
54
  const requestLink = jest.fn().mockResolvedValue('OK')
@@ -41,6 +41,8 @@ var _utils = require("../utils");
41
41
 
42
42
  var _defaultPerformanceApi = require("../performances/defaultPerformanceApi");
43
43
 
44
+ var _forceLink = require("./forceLink");
45
+
44
46
  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); }; }
45
47
 
46
48
  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; } }
@@ -176,72 +178,83 @@ var StackLink = /*#__PURE__*/function (_CozyLink) {
176
178
  key: "request",
177
179
  value: function () {
178
180
  var _request = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(operation, options, result, forward) {
181
+ var forceLink;
179
182
  return _regenerator.default.wrap(function _callee2$(_context2) {
180
183
  while (1) {
181
184
  switch (_context2.prev = _context2.next) {
182
185
  case 0:
183
- _context2.t0 = !(options !== null && options !== void 0 && options.forceStack) && this.isOnline;
186
+ forceLink = (0, _forceLink.resolveForceLink)(options);
187
+
188
+ if (!(forceLink && forceLink !== this.name)) {
189
+ _context2.next = 3;
190
+ break;
191
+ }
192
+
193
+ return _context2.abrupt("return", forward(operation, options));
194
+
195
+ case 3:
196
+ _context2.t0 = forceLink !== 'stack' && this.isOnline;
184
197
 
185
198
  if (!_context2.t0) {
186
- _context2.next = 5;
199
+ _context2.next = 8;
187
200
  break;
188
201
  }
189
202
 
190
- _context2.next = 4;
203
+ _context2.next = 7;
191
204
  return this.isOnline();
192
205
 
193
- case 4:
206
+ case 7:
194
207
  _context2.t0 = !_context2.sent;
195
208
 
196
- case 5:
209
+ case 8:
197
210
  if (!_context2.t0) {
198
- _context2.next = 7;
211
+ _context2.next = 10;
199
212
  break;
200
213
  }
201
214
 
202
215
  return _context2.abrupt("return", forward(operation, options));
203
216
 
204
- case 7:
205
- _context2.prev = 7;
217
+ case 10:
218
+ _context2.prev = 10;
206
219
 
207
220
  if (!operation.mutationType) {
208
- _context2.next = 12;
221
+ _context2.next = 15;
209
222
  break;
210
223
  }
211
224
 
212
- _context2.next = 11;
225
+ _context2.next = 14;
213
226
  return this.executeMutation(operation, options, result, forward);
214
227
 
215
- case 11:
228
+ case 14:
216
229
  return _context2.abrupt("return", _context2.sent);
217
230
 
218
- case 12:
219
- _context2.next = 14;
231
+ case 15:
232
+ _context2.next = 17;
220
233
  return this.executeQuery(operation);
221
234
 
222
- case 14:
235
+ case 17:
223
236
  return _context2.abrupt("return", _context2.sent);
224
237
 
225
- case 17:
226
- _context2.prev = 17;
227
- _context2.t1 = _context2["catch"](7);
238
+ case 20:
239
+ _context2.prev = 20;
240
+ _context2.t1 = _context2["catch"](10);
228
241
 
229
- if (!(!(options !== null && options !== void 0 && options.forceStack) && (0, _utils.isReactNativeOfflineError)(_context2.t1))) {
230
- _context2.next = 21;
242
+ if (!(forceLink !== 'stack' && (0, _utils.isReactNativeOfflineError)(_context2.t1))) {
243
+ _context2.next = 24;
231
244
  break;
232
245
  }
233
246
 
234
247
  return _context2.abrupt("return", forward(operation, options));
235
248
 
236
- case 21:
249
+ case 24:
237
250
  throw _context2.t1;
238
251
 
239
- case 22:
252
+ case 25:
240
253
  case "end":
241
254
  return _context2.stop();
242
255
  }
243
256
  }
244
- }, _callee2, this, [[7, 17]]);
257
+ }, _callee2, this, [[10, 20]]);
245
258
  }));
246
259
 
247
260
  function request(_x, _x2, _x3, _x4) {
@@ -409,6 +422,11 @@ var StackLink = /*#__PURE__*/function (_CozyLink) {
409
422
 
410
423
  return executeMutation;
411
424
  }()
425
+ }, {
426
+ key: "name",
427
+ get: function get() {
428
+ return 'stack';
429
+ }
412
430
  }]);
413
431
  return StackLink;
414
432
  }(_CozyLink2.default);
@@ -2,8 +2,17 @@ import { Q } from '../queries/dsl'
2
2
  import CozyClient from '../CozyClient'
3
3
  import StackLink, { transformBulkDocsResponse } from './StackLink'
4
4
  import { SCHEMA } from '../__tests__/fixtures'
5
+ import logger from '../logger'
6
+ // eslint-disable-next-line no-underscore-dangle
7
+ import { _resetForceStackWarning } from './forceLink'
5
8
 
6
9
  describe('StackLink', () => {
10
+ describe('name', () => {
11
+ it('should expose a stable name', () => {
12
+ expect(new StackLink().name).toBe('stack')
13
+ })
14
+ })
15
+
7
16
  let stackClient, link, client
8
17
 
9
18
  beforeEach(() => {
@@ -12,6 +21,54 @@ describe('StackLink', () => {
12
21
  stackClient = client.getStackClient()
13
22
  })
14
23
 
24
+ describe('forceLink', () => {
25
+ let warnSpy
26
+
27
+ beforeEach(() => {
28
+ _resetForceStackWarning()
29
+ warnSpy = jest.spyOn(logger, 'warn').mockImplementation(() => {})
30
+ })
31
+
32
+ afterEach(() => {
33
+ warnSpy.mockRestore()
34
+ })
35
+
36
+ it('forwards when forceLink targets another link', async () => {
37
+ const link = new StackLink()
38
+ const forward = jest.fn().mockResolvedValue('forwarded')
39
+ expect(
40
+ await link.request(
41
+ { doctype: 'io.cozy.files' },
42
+ { forceLink: 'dataproxy' },
43
+ undefined,
44
+ forward
45
+ )
46
+ ).toBe('forwarded')
47
+ })
48
+
49
+ it('handles a forceStack:true query (legacy: does not forward, emits deprecation warning)', async () => {
50
+ const link = new StackLink()
51
+ link.executeQuery = jest.fn().mockResolvedValue({ data: [] })
52
+ link.isOnline = jest.fn().mockResolvedValue(false) // offline — should NOT bail because forceStack
53
+ const forwardFn = jest.fn()
54
+ const op = { doctype: 'io.cozy.files' }
55
+ await link.request(op, { forceStack: true }, null, forwardFn)
56
+ expect(forwardFn).not.toHaveBeenCalled()
57
+ expect(warnSpy).toHaveBeenCalledWith(
58
+ expect.stringContaining('forceStack is deprecated')
59
+ )
60
+ })
61
+
62
+ it('forwards a plain query when offline', async () => {
63
+ const link = new StackLink()
64
+ link.isOnline = jest.fn().mockResolvedValue(false)
65
+ const forwardFn = jest.fn().mockResolvedValue(null)
66
+ const op = { doctype: 'io.cozy.files' }
67
+ await link.request(op, {}, null, forwardFn)
68
+ expect(forwardFn).toHaveBeenCalled()
69
+ })
70
+ })
71
+
15
72
  describe('query execution', () => {
16
73
  it('should execute queries without a selector', async () => {
17
74
  const query = Q('io.cozy.todos')
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.resolveForceLink = exports._resetForceStackWarning = void 0;
9
+
10
+ var _logger = _interopRequireDefault(require("../logger"));
11
+
12
+ var hasWarnedForceStack = false; // eslint-disable-next-line no-underscore-dangle
13
+
14
+ var _resetForceStackWarning = function _resetForceStackWarning() {
15
+ hasWarnedForceStack = false;
16
+ };
17
+ /* eslint-disable jsdoc/check-tag-names */
18
+
19
+ /**
20
+ * Resolves the effective forceLink target, mapping the deprecated forceStack option onto forceLink:'stack'.
21
+ *
22
+ * @internal
23
+ * @param {{ forceLink?: string, forceStack?: boolean }} [options] - Query options
24
+ * @returns {string|undefined}
25
+ */
26
+
27
+
28
+ exports._resetForceStackWarning = _resetForceStackWarning;
29
+
30
+ var resolveForceLink = function resolveForceLink(options) {
31
+ if (options !== null && options !== void 0 && options.forceLink) return options.forceLink;
32
+
33
+ if (options !== null && options !== void 0 && options.forceStack) {
34
+ if (!hasWarnedForceStack) {
35
+ _logger.default.warn("options.forceStack is deprecated, use forceLink: 'stack' instead");
36
+
37
+ hasWarnedForceStack = true;
38
+ }
39
+
40
+ return 'stack';
41
+ }
42
+
43
+ return undefined;
44
+ };
45
+ /* eslint-enable jsdoc/check-tag-names */
46
+
47
+
48
+ exports.resolveForceLink = resolveForceLink;
package/dist/types.js CHANGED
@@ -315,7 +315,8 @@ var _dsl = require("./queries/dsl");
315
315
  * a single doc instead of an array for single doc queries. Defaults to false for backward
316
316
  * compatibility but will be set to true in the future.
317
317
  * @property {boolean} [executeFromStore=false] - If set to true, the query will be run directly on the current store's state
318
- * @property {boolean} [forceStack] - If set to true, the query will be executed through StackLink only even if there are other links available
318
+ * @property {boolean} [forceStack] - Deprecated: use forceLink:'stack'. Executes the query through StackLink only.
319
+ * @property {string} [forceLink] - Route this query exclusively to the link whose name matches (e.g. 'dataproxy').
319
320
  */
320
321
 
321
322
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-client",
3
- "version": "60.28.2",
3
+ "version": "60.29.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": "272fde3c9e8dc4a4472744513ace8b71a8b2c417"
77
+ "gitHead": "0e624ae6b3ba93c2618ba9d26f4d4f48945bf5c8"
78
78
  }
package/types/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { default as CozyLink } from "./links/CozyLink";
3
3
  export { default as StackLink } from "./links/StackLink";
4
4
  export { default as WebFlagshipLink } from "./links/WebFlagshipLink";
5
5
  export { default as DataProxyLink } from "./links/DataProxyLink";
6
+ export { resolveForceLink } from "./links/forceLink";
6
7
  export { default as compose } from "lodash/flow";
7
8
  export { default as Registry } from "./registry";
8
9
  export { default as RealTimeQueries } from "./RealTimeQueries";
@@ -12,6 +12,7 @@ export { BulkEditError } from "./errors";
12
12
  export { default as fetchPolicies } from "./policies";
13
13
  export { webPerformanceApi } from "./performances/webPerformanceApi";
14
14
  export { defaultPerformanceApi } from "./performances/defaultPerformanceApi";
15
+ export { resolveForceLink } from "./links/forceLink";
15
16
  import * as manifest from "./models/manifest";
16
17
  import * as models from "./models";
17
18
  export { manifest, models };
@@ -24,5 +24,11 @@ export default class CozyLink {
24
24
  * @returns {Promise<any>}
25
25
  */
26
26
  reset(): Promise<any>;
27
+ /**
28
+ * Stable name used to target this link via the `forceLink` query option.
29
+ *
30
+ * @returns {string|undefined}
31
+ */
32
+ get name(): string;
27
33
  }
28
34
  export function chain(links: any): any;
@@ -0,0 +1,5 @@
1
+ export function _resetForceStackWarning(): void;
2
+ export function resolveForceLink(options?: {
3
+ forceLink?: string;
4
+ forceStack?: boolean;
5
+ }): string | undefined;
package/types/types.d.ts CHANGED
@@ -567,9 +567,13 @@ export type QueryOptions = {
567
567
  */
568
568
  executeFromStore?: boolean;
569
569
  /**
570
- * - If set to true, the query will be executed through StackLink only even if there are other links available
570
+ * - Deprecated: use forceLink:'stack'. Executes the query through StackLink only.
571
571
  */
572
572
  forceStack?: boolean;
573
+ /**
574
+ * - Route this query exclusively to the link whose name matches (e.g. 'dataproxy').
575
+ */
576
+ forceLink?: string;
573
577
  };
574
578
  export type Query = {
575
579
  definition: QueryDefinition;