@warp-drive-mirror/ember 5.6.0-alpha.14 → 5.6.0-alpha.17

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/index.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import { service } from '@ember/service';
2
2
  import Component from '@glimmer/component';
3
- import { tracked, cached } from '@glimmer/tracking';
4
3
  import { macroCondition, moduleExists, importSync, getGlobalConfig } from '@embroider/macros';
5
- import { getPromiseState, getRequestState } from '@warp-drive-mirror/core/store/-private';
4
+ import { getPromiseState, DISPOSE, createRequestSubscription } from '@warp-drive-mirror/core/store/-private';
6
5
  export { getPromiseState, getRequestState } from '@warp-drive-mirror/core/store/-private';
7
- import { EnableHydration } from '@warp-drive-mirror/core/types/request';
8
6
  import { precompileTemplate } from '@ember/template-compilation';
9
7
  import { setComponentTemplate } from '@ember/component';
10
8
 
@@ -131,20 +129,6 @@ function decorateFieldV2(prototype, prop, decorators, initializer) {
131
129
  deferDecorator(prototype, prop, desc);
132
130
  }
133
131
  }
134
- function decorateMethodV2(prototype, prop, decorators) {
135
- const origDesc = Object.getOwnPropertyDescriptor(prototype, prop);
136
- let desc = {
137
- ...origDesc
138
- };
139
- for (let decorator of decorators) {
140
- desc = decorator(prototype, prop, desc) || desc;
141
- }
142
- if (desc.initializer !== void 0) {
143
- desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
144
- desc.initializer = void 0;
145
- }
146
- Object.defineProperty(prototype, prop, desc);
147
- }
148
132
  function initializeDeferredDecorator(target, prop) {
149
133
  let desc = findDeferredDecorator(target.constructor, prop);
150
134
  if (desc) {
@@ -166,8 +150,6 @@ function notNull(x) {
166
150
  return x;
167
151
  }
168
152
  const not = x => !x;
169
- // default to 30 seconds unavailable before we refresh
170
- const DEFAULT_DEADLINE = 30_000;
171
153
  const IdleBlockMissingError = new Error('No idle block provided for <Request> component, and no query or request was provided.');
172
154
  let consume = service;
173
155
  if (macroCondition(moduleExists('ember-provide-consume-context'))) {
@@ -176,9 +158,6 @@ if (macroCondition(moduleExists('ember-provide-consume-context'))) {
176
158
  } = importSync('ember-provide-consume-context');
177
159
  consume = contextConsume;
178
160
  }
179
- function isNeverString(val) {
180
- return val;
181
- }
182
161
  /**
183
162
  * The `<Request />` component is a powerful tool for managing data fetching and
184
163
  * state in your Ember application. It provides a declarative approach to reactive
@@ -407,516 +386,6 @@ class Request extends Component {
407
386
  *
408
387
  * @internal
409
388
  */
410
- static {
411
- decorateFieldV2(this.prototype, "isOnline", [tracked], function () {
412
- return true;
413
- });
414
- }
415
- #isOnline = (initializeDeferredDecorator(this, "isOnline"), void 0);
416
- /**
417
- * Whether the browser reports that the network is online.
418
- *
419
- * @internal
420
- */
421
- static {
422
- decorateFieldV2(this.prototype, "isHidden", [tracked], function () {
423
- return true;
424
- });
425
- }
426
- #isHidden = (initializeDeferredDecorator(this, "isHidden"), void 0);
427
- /**
428
- * Whether the browser reports that the tab is hidden.
429
- *
430
- * @internal
431
- */
432
- static {
433
- decorateFieldV2(this.prototype, "isRefreshing", [tracked], function () {
434
- return false;
435
- });
436
- }
437
- #isRefreshing = (initializeDeferredDecorator(this, "isRefreshing"), void 0);
438
- /**
439
- * Whether the component is currently refreshing the request.
440
- *
441
- * @internal
442
- */
443
- static {
444
- decorateFieldV2(this.prototype, "_localRequest", [tracked]);
445
- }
446
- #_localRequest = (initializeDeferredDecorator(this, "_localRequest"), void 0);
447
- /**
448
- * The most recent blocking request that was made, typically
449
- * the result of a reload.
450
- *
451
- * This will never be the original request passed as an arg to
452
- * the component.
453
- *
454
- * @internal
455
- */
456
- static {
457
- decorateFieldV2(this.prototype, "_latestRequest", [tracked]);
458
- }
459
- #_latestRequest = (initializeDeferredDecorator(this, "_latestRequest"), void 0);
460
- /**
461
- * The most recent request that was made, typically due to either a
462
- * reload or a refresh.
463
- *
464
- * This will never be the original request passed as an arg to
465
- * the component.
466
- *
467
- * @internal
468
- */
469
- /**
470
- * The time at which the network was reported as offline.
471
- *
472
- * @internal
473
- */
474
-
475
- /**
476
- * The event listener for network status changes,
477
- * cached to use the reference for removal.
478
- *
479
- * @internal
480
- */
481
- /**
482
- * The event listener for visibility status changes,
483
- * cached to use the reference for removal.
484
- *
485
- * @internal
486
- */
487
- /**
488
- * The last request passed as an arg to the component,
489
- * cached for comparison.
490
- *
491
- * @internal
492
- */
493
- /**
494
- * The last query passed as an arg to the component,
495
- * cached for comparison.
496
- *
497
- * @internal
498
- */
499
-
500
- constructor(owner, args) {
501
- super(owner, args);
502
- this._subscribedTo = null;
503
- this._subscription = null;
504
- this.intervalStart = null;
505
- this.invalidated = false;
506
- this.nextInterval = null;
507
- this.installListeners();
508
- void this.beginPolling();
509
- }
510
- async beginPolling() {
511
- // await the initial request
512
- try {
513
- await this.request;
514
- } catch {
515
- // ignore errors here, we just want to wait for the request to finish
516
- } finally {
517
- if (!this.isDestroyed) {
518
- void this.scheduleInterval();
519
- }
520
- }
521
- }
522
- get isIdle() {
523
- const {
524
- request,
525
- query
526
- } = this.args;
527
- return Boolean(!request && !query);
528
- }
529
- static {
530
- decorateMethodV2(this.prototype, "isIdle", [cached]);
531
- }
532
- get autorefreshTypes() {
533
- const {
534
- autorefresh
535
- } = this.args;
536
- let types;
537
- if (autorefresh === true) {
538
- types = ['online', 'invalid'];
539
- } else if (typeof autorefresh === 'string') {
540
- types = autorefresh.split(',');
541
- } else {
542
- types = [];
543
- }
544
- return new Set(types);
545
- }
546
- // we only run this function on component creation
547
- // and when an update is triggered, so it does not
548
- // react to changes in the autorefreshThreshold
549
- // or autorefresh args.
550
- //
551
- // if we need to react to those changes, we can
552
- // use a modifier or internal component or some
553
- // such to trigger a re-run of this function.
554
- static {
555
- decorateMethodV2(this.prototype, "autorefreshTypes", [cached]);
556
- }
557
- async scheduleInterval() {
558
- const {
559
- autorefreshThreshold
560
- } = this.args;
561
- const hasValidThreshold = typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0;
562
- if (typeof window === 'undefined' ||
563
- // dont schedule without a threshold
564
- !hasValidThreshold ||
565
- // dont schedule if we weren't told to
566
- !this.autorefreshTypes.has('interval') ||
567
- // dont schedule if we're already scheduled
568
- this.intervalStart !== null) {
569
- return;
570
- }
571
- // if we have a current request, wait for it to finish
572
- // before scheduling the next one
573
- if (this._latestRequest) {
574
- try {
575
- await this._latestRequest;
576
- } catch {
577
- // ignore errors here, we just want to wait for the request to finish
578
- }
579
- if (this.isDestroyed) {
580
- return;
581
- }
582
- }
583
- // setup the next interval
584
- this.intervalStart = Date.now();
585
- this.nextInterval = setTimeout(() => {
586
- this.maybeUpdate();
587
- }, autorefreshThreshold);
588
- }
589
- clearInterval() {
590
- if (this.nextInterval) {
591
- clearTimeout(this.nextInterval);
592
- this.intervalStart = null;
593
- }
594
- }
595
- updateSubscriptions() {
596
- if (this.isIdle) {
597
- return;
598
- }
599
- const requestId = this._request.lid;
600
- // if we're already subscribed to this request, we don't need to do anything
601
- if (this._subscribedTo === requestId) {
602
- return;
603
- }
604
- // if we're subscribed to a different request, we need to unsubscribe
605
- this.removeSubscriptions();
606
- // if we have a request, we need to subscribe to it
607
- if (requestId) {
608
- this._subscribedTo = requestId;
609
- this._subscription = this.store.notifications.subscribe(requestId, (_id, op) => {
610
- // ignore subscription events that occur while our own component's request
611
- // is ocurring
612
- if (this.isUpdating) {
613
- return;
614
- }
615
- switch (op) {
616
- case 'invalidated':
617
- {
618
- // if we're subscribed to invalidations, we need to update
619
- if (this.autorefreshTypes.has('invalid')) {
620
- this.invalidated = true;
621
- this.maybeUpdate();
622
- }
623
- break;
624
- }
625
- case 'state':
626
- {
627
- const latest = this.store.requestManager._deduped.get(requestId);
628
- const priority = latest?.priority;
629
- const state = this.reqState;
630
- if (!priority) {
631
- // if there is no priority, we have completed whatever request
632
- // was occurring and so we are no longer refreshing (if we were)
633
- this.isRefreshing = false;
634
- } else if (priority.blocking && !state.isLoading) {
635
- // if we are blocking, there is an active request for this identity
636
- // that MUST be fulfilled from network (not cache).
637
- // Thus this is not "refreshing" because we should clear out and
638
- // block on this request.
639
- //
640
- // we receive state notifications when either a request initiates
641
- // or completes.
642
- //
643
- // In the completes case: we may receive the state notification
644
- // slightly before the request is finalized because the NotificationManager
645
- // may sync flush it (and thus deliver it before the microtask completes)
646
- //
647
- // In the initiates case: we aren't supposed to receive one unless there
648
- // is no other request in flight for this identity.
649
- //
650
- // However, there is a race condition here where the completed
651
- // notification can trigger an update that generates a new request
652
- // thus giving us an initiated notification before the older request
653
- // finalizes.
654
- //
655
- // When this occurs, if the triggered update happens to have caused
656
- // a new request to be made for the same identity AND that request
657
- // is the one passed into this component as the @request arg, then
658
- // getRequestState will return the state of the new request.
659
- // We can detect this by checking if the request state is "loading"
660
- // as outside of this case we would have a completed request.
661
- //
662
- // That is the reason for the `&& !state.isLoading` check above.
663
- // TODO should we just treat this as refreshing?
664
- this.isRefreshing = false;
665
- this.maybeUpdate('policy', true);
666
- } else {
667
- this.isRefreshing = true;
668
- }
669
- }
670
- }
671
- });
672
- }
673
- }
674
- removeSubscriptions() {
675
- if (this._subscription) {
676
- this.store.notifications.unsubscribe(this._subscription);
677
- this._subscribedTo = null;
678
- this._subscription = null;
679
- }
680
- }
681
- /**
682
- * Install the event listeners for network and visibility changes.
683
- * This is only done in browser environments with a global `window`.
684
- *
685
- * @internal
686
- */
687
- installListeners() {
688
- if (typeof window === 'undefined') {
689
- return;
690
- }
691
- this.isOnline = window.navigator.onLine;
692
- this.unavailableStart = this.isOnline ? null : Date.now();
693
- this.isHidden = document.visibilityState === 'hidden';
694
- this.onlineChanged = event => {
695
- this.isOnline = event.type === 'online';
696
- if (event.type === 'offline' && this.unavailableStart === null) {
697
- this.unavailableStart = Date.now();
698
- }
699
- this.maybeUpdate();
700
- };
701
- this.backgroundChanged = () => {
702
- const isHidden = document.visibilityState === 'hidden';
703
- this.isHidden = isHidden;
704
- if (isHidden && this.unavailableStart === null) {
705
- this.unavailableStart = Date.now();
706
- }
707
- this.maybeUpdate();
708
- };
709
- window.addEventListener('online', this.onlineChanged, {
710
- passive: true,
711
- capture: true
712
- });
713
- window.addEventListener('offline', this.onlineChanged, {
714
- passive: true,
715
- capture: true
716
- });
717
- document.addEventListener('visibilitychange', this.backgroundChanged, {
718
- passive: true,
719
- capture: true
720
- });
721
- }
722
- /**
723
- * If the network is online and the tab is visible, either reload or refresh the request
724
- * based on the component's configuration and the requested update mode.
725
- *
726
- * Valid modes are:
727
- *
728
- * - `'reload'`: Force a reload of the request.
729
- * - `'refresh'`: Refresh the request in the background.
730
- * - `'policy'`: Make the request, letting the store's configured CachePolicy decide whether to reload, refresh, or do nothing.
731
- * - `undefined`: Make the request using the component's autorefreshBehavior setting if the autorefreshThreshold has passed.
732
- *
733
- * @internal
734
- */
735
- maybeUpdate(mode, silent) {
736
- if (this.isIdle) {
737
- return;
738
- }
739
- const canAttempt = Boolean(this.isOnline && !this.isHidden && (mode || this.autorefreshTypes.size));
740
- if (!canAttempt) {
741
- if (!silent && mode && mode !== 'invalidated') {
742
- throw new Error(`Reload not available: the network is not online or the tab is hidden`);
743
- }
744
- return;
745
- }
746
- const {
747
- autorefreshTypes
748
- } = this;
749
- let shouldAttempt = this.invalidated || Boolean(mode);
750
- if (!shouldAttempt && autorefreshTypes.has('online')) {
751
- const {
752
- unavailableStart
753
- } = this;
754
- const {
755
- autorefreshThreshold
756
- } = this.args;
757
- const deadline = typeof autorefreshThreshold === 'number' ? autorefreshThreshold : DEFAULT_DEADLINE;
758
- shouldAttempt = Boolean(unavailableStart && Date.now() - unavailableStart > deadline);
759
- }
760
- if (!shouldAttempt && autorefreshTypes.has('interval')) {
761
- const {
762
- intervalStart
763
- } = this;
764
- const {
765
- autorefreshThreshold
766
- } = this.args;
767
- if (intervalStart && typeof autorefreshThreshold === 'number' && autorefreshThreshold > 0) {
768
- shouldAttempt = Boolean(Date.now() - intervalStart >= autorefreshThreshold);
769
- }
770
- }
771
- this.unavailableStart = null;
772
- this.invalidated = false;
773
- if (shouldAttempt) {
774
- this.clearInterval();
775
- const request = Object.assign({}, this.reqState.request);
776
- const realMode = mode === 'invalidated' ? null : mode;
777
- const val = realMode ?? this.args.autorefreshBehavior ?? 'policy';
778
- switch (val) {
779
- case 'reload':
780
- request.cacheOptions = Object.assign({}, request.cacheOptions, {
781
- reload: true
782
- });
783
- break;
784
- case 'refresh':
785
- request.cacheOptions = Object.assign({}, request.cacheOptions, {
786
- backgroundReload: true
787
- });
788
- break;
789
- case 'policy':
790
- break;
791
- default:
792
- throw new Error(`Invalid ${mode ? 'update mode' : '@autorefreshBehavior'} for <Request />: ${isNeverString(val)}`);
793
- }
794
- const wasStoreRequest = request[EnableHydration] === true;
795
- macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
796
- if (!test) {
797
- throw new Error(`Cannot supply a different store via context than was used to create the request`);
798
- }
799
- })(!request.store || request.store === this.store) : {};
800
- this.isUpdating = true;
801
- this._latestRequest = wasStoreRequest ? this.store.request(request) : this.store.requestManager.request(request);
802
- if (val !== 'refresh') {
803
- this._localRequest = this._latestRequest;
804
- }
805
- void this.scheduleInterval();
806
- void this._latestRequest.finally(() => {
807
- this.isUpdating = false;
808
- });
809
- }
810
- }
811
- /**
812
- * Retry the request, reloading it from the server.
813
- *
814
- * @internal
815
- */
816
- retry = async () => {
817
- this.maybeUpdate('reload');
818
- await this._localRequest;
819
- };
820
- /**
821
- * Refresh the request, updating it in the background.
822
- *
823
- * @internal
824
- */
825
- refresh = async () => {
826
- this.maybeUpdate('refresh');
827
- await this._latestRequest;
828
- };
829
- get errorFeatures() {
830
- return {
831
- isHidden: this.isHidden,
832
- isOnline: this.isOnline,
833
- retry: this.retry
834
- };
835
- }
836
- static {
837
- decorateMethodV2(this.prototype, "errorFeatures", [cached]);
838
- }
839
- get contentFeatures() {
840
- const feat = {
841
- isHidden: this.isHidden,
842
- isOnline: this.isOnline,
843
- reload: this.retry,
844
- refresh: this.refresh,
845
- isRefreshing: this.isRefreshing,
846
- latestRequest: this._latestRequest
847
- };
848
- if (feat.isRefreshing) {
849
- feat.abort = () => {
850
- this._latestRequest?.abort();
851
- };
852
- }
853
- return feat;
854
- }
855
- static {
856
- decorateMethodV2(this.prototype, "contentFeatures", [cached]);
857
- }
858
- willDestroy() {
859
- this.removeSubscriptions();
860
- if (typeof window === 'undefined') {
861
- return;
862
- }
863
- this.clearInterval();
864
- window.removeEventListener('online', this.onlineChanged, {
865
- passive: true,
866
- capture: true
867
- });
868
- window.removeEventListener('offline', this.onlineChanged, {
869
- passive: true,
870
- capture: true
871
- });
872
- document.removeEventListener('visibilitychange', this.backgroundChanged, {
873
- passive: true,
874
- capture: true
875
- });
876
- }
877
- get _request() {
878
- const {
879
- request,
880
- query
881
- } = this.args;
882
- macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
883
- if (!test) {
884
- throw new Error(`Cannot use both @request and @query args with the <Request> component`);
885
- }
886
- })(!request || !query) : {};
887
- const {
888
- _localRequest,
889
- _originalRequest,
890
- _originalQuery
891
- } = this;
892
- const isOriginalRequest = request === _originalRequest && query === _originalQuery;
893
- if (_localRequest && isOriginalRequest) {
894
- return _localRequest;
895
- }
896
- // update state checks for the next time
897
- this._originalQuery = query;
898
- this._originalRequest = request;
899
- if (request) {
900
- return request;
901
- }
902
- macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
903
- if (!test) {
904
- throw new Error(`You must provide either @request or an @query arg with the <Request> component`);
905
- }
906
- })(query) : {};
907
- return this.store.request(query);
908
- }
909
- static {
910
- decorateMethodV2(this.prototype, "_request", [cached]);
911
- }
912
- get request() {
913
- const request = this._request;
914
- this.updateSubscriptions();
915
- return request;
916
- }
917
- static {
918
- decorateMethodV2(this.prototype, "request", [cached]);
919
- }
920
389
  get store() {
921
390
  const store = this.args.store || this._store;
922
391
  macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
@@ -926,14 +395,29 @@ class Request extends Component {
926
395
  })(store) : {};
927
396
  return store;
928
397
  }
929
- get reqState() {
930
- return getRequestState(this.request);
398
+ _state = null;
399
+ get state() {
400
+ let {
401
+ _state
402
+ } = this;
403
+ const {
404
+ store
405
+ } = this;
406
+ if (_state && _state.store !== store) {
407
+ _state[DISPOSE]();
408
+ _state = null;
409
+ }
410
+ if (!_state) {
411
+ this._state = _state = createRequestSubscription(store, this.args);
412
+ }
413
+ return _state;
931
414
  }
932
- get result() {
933
- return this.reqState.result;
415
+ willDestroy() {
416
+ this._state[DISPOSE]();
417
+ this._state = null;
934
418
  }
935
419
  static {
936
- setComponentTemplate(precompileTemplate("\n {{#if (and this.isIdle (has-block \"idle\"))}}\n {{yield to=\"idle\"}}\n {{else if this.isIdle}}\n <Throw @error={{IdleBlockMissingError}} />\n {{else if this.reqState.isLoading}}\n {{yield this.reqState.loadingState to=\"loading\"}}\n {{else if (and this.reqState.isCancelled (has-block \"cancelled\"))}}\n {{yield (notNull this.reqState.error) this.errorFeatures to=\"cancelled\"}}\n {{else if (and this.reqState.isError (has-block \"error\"))}}\n {{yield (notNull this.reqState.error) this.errorFeatures to=\"error\"}}\n {{else if this.reqState.isSuccess}}\n {{yield this.result this.contentFeatures to=\"content\"}}\n {{else if (not this.reqState.isCancelled)}}\n <Throw @error={{(notNull this.reqState.error)}} />\n {{/if}}\n {{yield this.reqState to=\"always\"}}\n ", {
420
+ setComponentTemplate(precompileTemplate("\n {{#if (and this.state.isIdle (has-block \"idle\"))}}\n {{yield to=\"idle\"}}\n\n {{else if this.state.isIdle}}\n <Throw @error={{IdleBlockMissingError}} />\n\n {{else if this.state.reqState.isLoading}}\n {{yield this.state.reqState.loadingState to=\"loading\"}}\n\n {{else if (and this.state.reqState.isCancelled (has-block \"cancelled\"))}}\n {{yield (notNull this.state.reqState.reason) this.state.errorFeatures to=\"cancelled\"}}\n\n {{else if (and this.state.reqState.isError (has-block \"error\"))}}\n {{yield (notNull this.state.reqState.reason) this.state.errorFeatures to=\"error\"}}\n\n {{else if this.state.reqState.isSuccess}}\n {{yield this.state.result this.state.contentFeatures to=\"content\"}}\n\n {{else if (not this.state.reqState.isCancelled)}}\n <Throw @error={{(notNull this.state.reqState.reason)}} />\n {{/if}}\n\n {{yield this.state.reqState to=\"always\"}}\n ", {
937
421
  strictMode: true,
938
422
  scope: () => ({
939
423
  and,
@@ -947,4 +431,3 @@ class Request extends Component {
947
431
  }
948
432
 
949
433
  export { Await, Request, Throw };
950
- //# sourceMappingURL=index.js.map
package/dist/install.js CHANGED
@@ -75,4 +75,3 @@ function buildSignalConfig(options) {
75
75
  setupSignals(buildSignalConfig);
76
76
 
77
77
  export { buildSignalConfig };
78
- //# sourceMappingURL=install.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@warp-drive-mirror/ember",
3
3
  "description": "Data bindings and utilities for Ember applications using WarpDrive",
4
- "version": "5.6.0-alpha.14",
4
+ "version": "5.6.0-alpha.17",
5
5
  "license": "MIT",
6
6
  "author": "Chris Thoburn <runspired@users.noreply.github.com>",
7
7
  "repository": {
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@embroider/macros": "^1.16.12",
41
- "@warp-drive-mirror/core": "5.6.0-alpha.14"
41
+ "@warp-drive-mirror/core": "5.6.0-alpha.17"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "ember-provide-consume-context": {
@@ -60,14 +60,14 @@
60
60
  "@embroider/addon-dev": "^7.1.3",
61
61
  "@ember/test-helpers": "5.2.0",
62
62
  "@ember/test-waiters": "^4.1.0",
63
- "@warp-drive/internal-config": "5.6.0-alpha.14",
64
- "@warp-drive-mirror/core": "5.6.0-alpha.14",
63
+ "@warp-drive/internal-config": "5.6.0-alpha.17",
64
+ "@warp-drive-mirror/core": "5.6.0-alpha.17",
65
65
  "babel-plugin-ember-template-compilation": "^2.4.1",
66
66
  "ember-template-imports": "^4.3.0",
67
67
  "ember-source": "~6.3.0",
68
68
  "rollup": "^4.40.0",
69
69
  "typescript": "^5.8.3",
70
- "vite": "^5.4.15",
70
+ "vite": "^7.0.0",
71
71
  "ember-provide-consume-context": "^0.7.0"
72
72
  },
73
73
  "volta": {