@atlaskit/collab-provider 9.15.2 → 9.15.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 9.15.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#41977](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/41977) [`5b2f6d283ef`](https://bitbucket.org/atlassian/atlassian-frontend/commits/5b2f6d283ef) - clean up catchup retry feature flag
8
+
3
9
  ## 9.15.2
4
10
 
5
11
  ### Patch Changes
@@ -42,13 +42,11 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
42
42
  * @param getUserId - Callback to fetch the current user's ID
43
43
  * @param onErrorHandled - Callback to handle
44
44
  * @param metadataService
45
- * @param failedStepsBeforeCatchupOnPublish - Control MAX_STEP_REJECTED_ERROR during page publishes.
46
45
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
47
46
  */
48
47
  function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
49
48
  var _this = this;
50
- var failedStepsBeforeCatchupOnPublish = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : _provider.MAX_STEP_REJECTED_ERROR;
51
- var enableErrorOnFailedDocumentApply = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
49
+ var enableErrorOnFailedDocumentApply = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
52
50
  (0, _classCallCheck2.default)(this, DocumentService);
53
51
  // Fires analytics to editor when collab editor cannot sync up
54
52
  (0, _defineProperty2.default)(this, "stepRejectCounter", 0);
@@ -507,7 +505,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
507
505
  (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendActionEvent(_const.EVENT_ACTION.SEND_STEPS_RETRY, _const.EVENT_STATUS.INFO, {
508
506
  count: _this.stepRejectCounter
509
507
  });
510
- var maxRetries = _this.aggressiveCatchup ? _this.failedStepsBeforeCatchupOnPublish : _provider.MAX_STEP_REJECTED_ERROR;
508
+ var maxRetries = _this.aggressiveCatchup ? _provider.MAX_STEP_REJECTED_ERROR_AGGRESSIVE : _provider.MAX_STEP_REJECTED_ERROR;
511
509
  if (_this.stepRejectCounter >= maxRetries) {
512
510
  var _this$analyticsHelper24;
513
511
  logger("The steps were rejected too many times (tries=".concat(_this.stepRejectCounter, ", limit=").concat(_provider.MAX_STEP_REJECTED_ERROR, "). Trying to catch-up."));
@@ -532,7 +530,6 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
532
530
  this.getUserId = getUserId;
533
531
  this.onErrorHandled = onErrorHandled;
534
532
  this.metadataService = metadataService;
535
- this.failedStepsBeforeCatchupOnPublish = failedStepsBeforeCatchupOnPublish;
536
533
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
537
534
  this.stepQueue = new _stepQueueState.StepQueueState();
538
535
  }
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.Provider = exports.MAX_STEP_REJECTED_ERROR = void 0;
7
+ exports.Provider = exports.MAX_STEP_REJECTED_ERROR_AGGRESSIVE = exports.MAX_STEP_REJECTED_ERROR = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
9
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
10
10
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
@@ -34,6 +34,7 @@ var OUT_OF_SYNC_PERIOD = 3 * 1000; // 3 seconds
34
34
  var PRELOAD_DRAFT_SYNC_PERIOD = 15 * 1000; // 15 seconds
35
35
 
36
36
  var MAX_STEP_REJECTED_ERROR = exports.MAX_STEP_REJECTED_ERROR = 15;
37
+ var MAX_STEP_REJECTED_ERROR_AGGRESSIVE = exports.MAX_STEP_REJECTED_ERROR_AGGRESSIVE = 2;
37
38
  var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
38
39
  (0, _inherits2.default)(Provider, _Emitter);
39
40
  var _super = _createSuper(Provider);
@@ -267,7 +268,7 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
267
268
  _this.metadataService = new _metadataService.MetadataService(_this.emitCallback, _this.channel.sendMetadata);
268
269
  _this.documentService = new _documentService.DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
269
270
  return _this.userId;
270
- }, _this.onErrorHandled, _this.metadataService, _this.config.failedStepLimitBeforeCatchupOnPublish, _this.config.enableErrorOnFailedDocumentApply);
271
+ }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply);
271
272
  _this.namespaceService = new _namespaceService.NamespaceService();
272
273
  return _this;
273
274
  }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/collab-provider";
8
- var version = exports.version = "9.15.2";
8
+ var version = exports.version = "9.15.3";
9
9
  var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
10
10
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
11
11
  };
@@ -6,7 +6,7 @@ import throttle from 'lodash/throttle';
6
6
  import { throttledCommitStep } from '../provider/commit-step';
7
7
  import { MEASURE_NAME, startMeasure, stopMeasure } from '../analytics/performance';
8
8
  import { JSONTransformer } from '@atlaskit/editor-json-transformer';
9
- import { MAX_STEP_REJECTED_ERROR } from '../provider';
9
+ import { MAX_STEP_REJECTED_ERROR, MAX_STEP_REJECTED_ERROR_AGGRESSIVE } from '../provider';
10
10
  import { catchup } from './catchup';
11
11
  import { StepQueueState } from './step-queue-state';
12
12
  import { CantSyncUpError, INTERNAL_ERROR_CODE, UpdateDocumentError } from '../errors/error-types';
@@ -29,10 +29,9 @@ export class DocumentService {
29
29
  * @param getUserId - Callback to fetch the current user's ID
30
30
  * @param onErrorHandled - Callback to handle
31
31
  * @param metadataService
32
- * @param failedStepsBeforeCatchupOnPublish - Control MAX_STEP_REJECTED_ERROR during page publishes.
33
32
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
34
33
  */
35
- constructor(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, failedStepsBeforeCatchupOnPublish = MAX_STEP_REJECTED_ERROR, enableErrorOnFailedDocumentApply = false) {
34
+ constructor(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, enableErrorOnFailedDocumentApply = false) {
36
35
  // Fires analytics to editor when collab editor cannot sync up
37
36
  _defineProperty(this, "stepRejectCounter", 0);
38
37
  _defineProperty(this, "aggressiveCatchup", false);
@@ -419,7 +418,7 @@ export class DocumentService {
419
418
  (_this$analyticsHelper23 = this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 ? void 0 : _this$analyticsHelper23.sendActionEvent(EVENT_ACTION.SEND_STEPS_RETRY, EVENT_STATUS.INFO, {
420
419
  count: this.stepRejectCounter
421
420
  });
422
- let maxRetries = this.aggressiveCatchup ? this.failedStepsBeforeCatchupOnPublish : MAX_STEP_REJECTED_ERROR;
421
+ let maxRetries = this.aggressiveCatchup ? MAX_STEP_REJECTED_ERROR_AGGRESSIVE : MAX_STEP_REJECTED_ERROR;
423
422
  if (this.stepRejectCounter >= maxRetries) {
424
423
  var _this$analyticsHelper24;
425
424
  logger(`The steps were rejected too many times (tries=${this.stepRejectCounter}, limit=${MAX_STEP_REJECTED_ERROR}). Trying to catch-up.`);
@@ -442,7 +441,6 @@ export class DocumentService {
442
441
  this.getUserId = getUserId;
443
442
  this.onErrorHandled = onErrorHandled;
444
443
  this.metadataService = metadataService;
445
- this.failedStepsBeforeCatchupOnPublish = failedStepsBeforeCatchupOnPublish;
446
444
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
447
445
  this.stepQueue = new StepQueueState();
448
446
  }
@@ -16,6 +16,7 @@ const OUT_OF_SYNC_PERIOD = 3 * 1000; // 3 seconds
16
16
  const PRELOAD_DRAFT_SYNC_PERIOD = 15 * 1000; // 15 seconds
17
17
 
18
18
  export const MAX_STEP_REJECTED_ERROR = 15;
19
+ export const MAX_STEP_REJECTED_ERROR_AGGRESSIVE = 2;
19
20
  export class Provider extends Emitter {
20
21
  constructor(config) {
21
22
  super();
@@ -220,7 +221,7 @@ export class Provider extends Emitter {
220
221
  this.isProviderInitialized = false;
221
222
  this.participantsService = new ParticipantsService(this.analyticsHelper, undefined, this.emitCallback, this.config.getUser, this.channel.broadcast, this.channel.sendPresenceJoined, this.getPresenceData, this.setUserId);
222
223
  this.metadataService = new MetadataService(this.emitCallback, this.channel.sendMetadata);
223
- this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.config.failedStepLimitBeforeCatchupOnPublish, this.config.enableErrorOnFailedDocumentApply);
224
+ this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.config.enableErrorOnFailedDocumentApply);
224
225
  this.namespaceService = new NamespaceService();
225
226
  }
226
227
  /**
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "9.15.2";
2
+ export const version = "9.15.3";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -12,7 +12,7 @@ import throttle from 'lodash/throttle';
12
12
  import { throttledCommitStep } from '../provider/commit-step';
13
13
  import { MEASURE_NAME, startMeasure, stopMeasure } from '../analytics/performance';
14
14
  import { JSONTransformer } from '@atlaskit/editor-json-transformer';
15
- import { MAX_STEP_REJECTED_ERROR } from '../provider';
15
+ import { MAX_STEP_REJECTED_ERROR, MAX_STEP_REJECTED_ERROR_AGGRESSIVE } from '../provider';
16
16
  import { catchup } from './catchup';
17
17
  import { StepQueueState } from './step-queue-state';
18
18
  import { CantSyncUpError, INTERNAL_ERROR_CODE, UpdateDocumentError } from '../errors/error-types';
@@ -35,13 +35,11 @@ export var DocumentService = /*#__PURE__*/function () {
35
35
  * @param getUserId - Callback to fetch the current user's ID
36
36
  * @param onErrorHandled - Callback to handle
37
37
  * @param metadataService
38
- * @param failedStepsBeforeCatchupOnPublish - Control MAX_STEP_REJECTED_ERROR during page publishes.
39
38
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
40
39
  */
41
40
  function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
42
41
  var _this = this;
43
- var failedStepsBeforeCatchupOnPublish = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : MAX_STEP_REJECTED_ERROR;
44
- var enableErrorOnFailedDocumentApply = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
42
+ var enableErrorOnFailedDocumentApply = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
45
43
  _classCallCheck(this, DocumentService);
46
44
  // Fires analytics to editor when collab editor cannot sync up
47
45
  _defineProperty(this, "stepRejectCounter", 0);
@@ -500,7 +498,7 @@ export var DocumentService = /*#__PURE__*/function () {
500
498
  (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendActionEvent(EVENT_ACTION.SEND_STEPS_RETRY, EVENT_STATUS.INFO, {
501
499
  count: _this.stepRejectCounter
502
500
  });
503
- var maxRetries = _this.aggressiveCatchup ? _this.failedStepsBeforeCatchupOnPublish : MAX_STEP_REJECTED_ERROR;
501
+ var maxRetries = _this.aggressiveCatchup ? MAX_STEP_REJECTED_ERROR_AGGRESSIVE : MAX_STEP_REJECTED_ERROR;
504
502
  if (_this.stepRejectCounter >= maxRetries) {
505
503
  var _this$analyticsHelper24;
506
504
  logger("The steps were rejected too many times (tries=".concat(_this.stepRejectCounter, ", limit=").concat(MAX_STEP_REJECTED_ERROR, "). Trying to catch-up."));
@@ -525,7 +523,6 @@ export var DocumentService = /*#__PURE__*/function () {
525
523
  this.getUserId = getUserId;
526
524
  this.onErrorHandled = onErrorHandled;
527
525
  this.metadataService = metadataService;
528
- this.failedStepsBeforeCatchupOnPublish = failedStepsBeforeCatchupOnPublish;
529
526
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
530
527
  this.stepQueue = new StepQueueState();
531
528
  }
@@ -27,6 +27,7 @@ var OUT_OF_SYNC_PERIOD = 3 * 1000; // 3 seconds
27
27
  var PRELOAD_DRAFT_SYNC_PERIOD = 15 * 1000; // 15 seconds
28
28
 
29
29
  export var MAX_STEP_REJECTED_ERROR = 15;
30
+ export var MAX_STEP_REJECTED_ERROR_AGGRESSIVE = 2;
30
31
  export var Provider = /*#__PURE__*/function (_Emitter) {
31
32
  _inherits(Provider, _Emitter);
32
33
  var _super = _createSuper(Provider);
@@ -260,7 +261,7 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
260
261
  _this.metadataService = new MetadataService(_this.emitCallback, _this.channel.sendMetadata);
261
262
  _this.documentService = new DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
262
263
  return _this.userId;
263
- }, _this.onErrorHandled, _this.metadataService, _this.config.failedStepLimitBeforeCatchupOnPublish, _this.config.enableErrorOnFailedDocumentApply);
264
+ }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply);
264
265
  _this.namespaceService = new NamespaceService();
265
266
  return _this;
266
267
  }
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "9.15.2";
2
+ export var version = "9.15.3";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -18,7 +18,6 @@ export declare class DocumentService {
18
18
  private getUserId;
19
19
  private onErrorHandled;
20
20
  private metadataService;
21
- private failedStepsBeforeCatchupOnPublish;
22
21
  private enableErrorOnFailedDocumentApply;
23
22
  private getState;
24
23
  private onSyncUpError?;
@@ -38,10 +37,9 @@ export declare class DocumentService {
38
37
  * @param getUserId - Callback to fetch the current user's ID
39
38
  * @param onErrorHandled - Callback to handle
40
39
  * @param metadataService
41
- * @param failedStepsBeforeCatchupOnPublish - Control MAX_STEP_REJECTED_ERROR during page publishes.
42
40
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
43
41
  */
44
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, failedStepsBeforeCatchupOnPublish?: number, enableErrorOnFailedDocumentApply?: boolean);
42
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean);
45
43
  /**
46
44
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
47
45
  */
@@ -4,6 +4,7 @@ import { Emitter } from '../emitter';
4
4
  import type { Config } from '../types';
5
5
  import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction } from '@atlaskit/editor-common/collab';
6
6
  export declare const MAX_STEP_REJECTED_ERROR = 15;
7
+ export declare const MAX_STEP_REJECTED_ERROR_AGGRESSIVE = 2;
7
8
  type BaseEvents = Pick<CollabEditProvider<CollabEvents>, 'setup' | 'send' | 'sendMessage'>;
8
9
  export declare class Provider extends Emitter<CollabEvents> implements BaseEvents {
9
10
  private channel;
@@ -18,7 +18,6 @@ export declare class DocumentService {
18
18
  private getUserId;
19
19
  private onErrorHandled;
20
20
  private metadataService;
21
- private failedStepsBeforeCatchupOnPublish;
22
21
  private enableErrorOnFailedDocumentApply;
23
22
  private getState;
24
23
  private onSyncUpError?;
@@ -38,10 +37,9 @@ export declare class DocumentService {
38
37
  * @param getUserId - Callback to fetch the current user's ID
39
38
  * @param onErrorHandled - Callback to handle
40
39
  * @param metadataService
41
- * @param failedStepsBeforeCatchupOnPublish - Control MAX_STEP_REJECTED_ERROR during page publishes.
42
40
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
43
41
  */
44
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, failedStepsBeforeCatchupOnPublish?: number, enableErrorOnFailedDocumentApply?: boolean);
42
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean);
45
43
  /**
46
44
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
47
45
  */
@@ -4,6 +4,7 @@ import { Emitter } from '../emitter';
4
4
  import type { Config } from '../types';
5
5
  import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction } from '@atlaskit/editor-common/collab';
6
6
  export declare const MAX_STEP_REJECTED_ERROR = 15;
7
+ export declare const MAX_STEP_REJECTED_ERROR_AGGRESSIVE = 2;
7
8
  type BaseEvents = Pick<CollabEditProvider<CollabEvents>, 'setup' | 'send' | 'sendMessage'>;
8
9
  export declare class Provider extends Emitter<CollabEvents> implements BaseEvents {
9
10
  private channel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "9.15.2",
3
+ "version": "9.15.3",
4
4
  "description": "A provider for collaborative editing.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@atlaskit/analytics-gas-types": "^5.1.0",
38
38
  "@atlaskit/analytics-listeners": "^8.7.0",
39
- "@atlaskit/editor-common": "^76.11.0",
39
+ "@atlaskit/editor-common": "^76.15.0",
40
40
  "@atlaskit/editor-json-transformer": "^8.10.0",
41
41
  "@atlaskit/editor-prosemirror": "1.1.0",
42
42
  "@atlaskit/prosemirror-collab": "^0.2.0",