UNPKG

27.8 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
8
9var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
10
11var _promise = require('babel-runtime/core-js/promise');
12
13var _promise2 = _interopRequireDefault(_promise);
14
15var _typeof2 = require('babel-runtime/helpers/typeof');
16
17var _typeof3 = _interopRequireDefault(_typeof2);
18
19var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
20
21var _defineProperty3 = _interopRequireDefault(_defineProperty2);
22
23var _extends3 = require('babel-runtime/helpers/extends');
24
25var _extends4 = _interopRequireDefault(_extends3);
26
27var _regenerator = require('babel-runtime/regenerator');
28
29var _regenerator2 = _interopRequireDefault(_regenerator);
30
31var _getIterator2 = require('babel-runtime/core-js/get-iterator');
32
33var _getIterator3 = _interopRequireDefault(_getIterator2);
34
35var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
36
37var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
38
39var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
40
41var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
42
43var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
44
45var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
46
47var _createClass2 = require('babel-runtime/helpers/createClass');
48
49var _createClass3 = _interopRequireDefault(_createClass2);
50
51var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
52
53var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
54
55var _get2 = require('babel-runtime/helpers/get');
56
57var _get3 = _interopRequireDefault(_get2);
58
59var _inherits2 = require('babel-runtime/helpers/inherits');
60
61var _inherits3 = _interopRequireDefault(_inherits2);
62
63exports.default = subscribe;
64
65var _isArray = require('lodash/isArray');
66
67var _isArray2 = _interopRequireDefault(_isArray);
68
69var _uniq = require('lodash/uniq');
70
71var _uniq2 = _interopRequireDefault(_uniq);
72
73var _union = require('lodash/union');
74
75var _union2 = _interopRequireDefault(_union);
76
77var _keys2 = require('lodash/keys');
78
79var _keys3 = _interopRequireDefault(_keys2);
80
81var _isEqual = require('lodash/isEqual');
82
83var _isEqual2 = _interopRequireDefault(_isEqual);
84
85var _react = require('react');
86
87var _react2 = _interopRequireDefault(_react);
88
89var _hoistNonReactStatics = require('hoist-non-react-statics');
90
91var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics);
92
93var _model2 = require('@startupjs/model');
94
95var _model3 = _interopRequireDefault(_model2);
96
97var _Doc = require('./types/Doc');
98
99var _Doc2 = _interopRequireDefault(_Doc);
100
101var _Query = require('./types/Query');
102
103var _Query2 = _interopRequireDefault(_Query);
104
105var _QueryExtra = require('./types/QueryExtra');
106
107var _QueryExtra2 = _interopRequireDefault(_QueryExtra);
108
109var _Local = require('./types/Local');
110
111var _Local2 = _interopRequireDefault(_Local);
112
113var _Value = require('./types/Value');
114
115var _Value2 = _interopRequireDefault(_Value);
116
117var _Api = require('./types/Api');
118
119var _Api2 = _interopRequireDefault(_Api);
120
121var _batching = require('../batching');
122
123var _batching2 = _interopRequireDefault(_batching);
124
125var _semaphore = require('./semaphore');
126
127var _semaphore2 = _interopRequireDefault(_semaphore);
128
129var _isExtraQuery = require('./isExtraQuery');
130
131var _observerUtil = require('@nx-js/observer-util');
132
133function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
134
135var STORE = 'store';
136// import debounce from 'lodash/debounce'
137
138var STORE_DEPRECATED = 'scope';
139var $STORE = '$' + STORE;
140var $STORE_DEPRECATED = '$' + STORE_DEPRECATED;
141var DEFAULT_COLLECTION = '$components';
142var SUBSCRIBE_COMPUTATION_NAME = '__subscribeComputation';
143var HELPER_METHODS_TO_BIND = ['get', 'at'];
144var DUMMY_STATE = {};
145
146function subscribe(fn) {
147 return function decorateTarget(Component) {
148 var isStateless = !(Component.prototype && Component.prototype.isReactComponent);
149 var AutorunComponent = Component.__isSubscription ? Component : getAutorunComponent(Component, isStateless);
150 var SubscriptionsContainer = getSubscriptionsContainer(AutorunComponent, fn ? [fn] : []);
151 return (0, _hoistNonReactStatics2.default)(SubscriptionsContainer, AutorunComponent);
152 };
153}
154
155var getAutorunComponent = function getAutorunComponent(Component, isStateless) {
156 var AutorunHOC = function (_ref) {
157 (0, _inherits3.default)(AutorunHOC, _ref);
158
159 function AutorunHOC(props) {
160 var _ref2;
161
162 (0, _classCallCheck3.default)(this, AutorunHOC);
163
164 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
165 args[_key - 1] = arguments[_key];
166 }
167
168 // Mark subscription as used.
169 // This is needed to track in later @subscribe's whether
170 // to create a new $STORE or use the one received from props
171 // (in case when the outer component is @subscribe)
172 var _this = (0, _possibleConstructorReturn3.default)(this, (_ref2 = AutorunHOC.__proto__ || (0, _getPrototypeOf2.default)(AutorunHOC)).call.apply(_ref2, [this, props].concat(args)));
173
174 props[$STORE].__used = true;
175
176 // let fn = debounce(() => {
177 // if (this.unmounted) return
178 // this.setState(DUMMY_STATE)
179 // })
180
181 var updateFn = function updateFn() {
182 if (_this.unmounted) return;
183 _this.setState(DUMMY_STATE);
184 };
185 _this.update = function () {
186 return _batching2.default.add(updateFn);
187 };
188
189 // let fn = () => batchedUpdate(() => {
190 // if (this.unmounted) return
191 // this.setState(DUMMY_STATE)
192 // })
193
194 // create a reactive render for the component
195 // run a dummy setState to schedule a new reactive render, avoid forceUpdate
196 _this.render = (0, _observerUtil.observe)(_this.render, {
197 scheduler: _this.update,
198 lazy: true
199 });
200 return _this;
201 }
202
203 (0, _createClass3.default)(AutorunHOC, [{
204 key: 'render',
205 value: function render() {
206 return isStateless ? Component(this.props, this.context) : (0, _get3.default)(AutorunHOC.prototype.__proto__ || (0, _getPrototypeOf2.default)(AutorunHOC.prototype), 'render', this).call(this);
207 }
208 }, {
209 key: 'componentWillUnmount',
210 value: function componentWillUnmount() {
211 this.unmounted = true;
212 // stop autorun
213 (0, _observerUtil.unobserve)(this.render);
214 // call user defined componentWillUnmount
215 if ((0, _get3.default)(AutorunHOC.prototype.__proto__ || (0, _getPrototypeOf2.default)(AutorunHOC.prototype), 'componentWillUnmount', this)) (0, _get3.default)(AutorunHOC.prototype.__proto__ || (0, _getPrototypeOf2.default)(AutorunHOC.prototype), 'componentWillUnmount', this).call(this);
216 }
217 }]);
218 return AutorunHOC;
219 }(isStateless ? _react2.default.Component : Component);
220
221 AutorunHOC.displayName = 'AutorunHOC(' + (Component.displayName || Component.name || 'Component') + ')';
222 return AutorunHOC;
223};
224
225var getSubscriptionsContainer = function getSubscriptionsContainer(DecoratedComponent, fns) {
226 var _class, _temp;
227
228 return _temp = _class = function (_React$Component) {
229 (0, _inherits3.default)(SubscriptionsContainer, _React$Component);
230
231 function SubscriptionsContainer() {
232 (0, _classCallCheck3.default)(this, SubscriptionsContainer);
233 return (0, _possibleConstructorReturn3.default)(this, (SubscriptionsContainer.__proto__ || (0, _getPrototypeOf2.default)(SubscriptionsContainer)).apply(this, arguments));
234 }
235
236 (0, _createClass3.default)(SubscriptionsContainer, [{
237 key: 'UNSAFE_componentWillMount',
238
239
240 // eslint-disable-next-line camelcase
241 value: function UNSAFE_componentWillMount() {
242 this.model = this.getOrCreateModel();
243 this.models = {};
244 // pipe the local model into props as $STORE
245 this.models[$STORE] = this.model;
246 this.models[$STORE_DEPRECATED] = this.model; // TODO: DEPRECATED
247 this[STORE] = this.model.get();
248 this.autorunSubscriptions();
249 }
250
251 // TODO: Implement queueing
252 // eslint-disable-next-line camelcase
253
254 // eslint-disable-next-line
255
256 }, {
257 key: 'UNSAFE_componentWillReceiveProps',
258 value: function () {
259 var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
260 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
261 args[_key2] = arguments[_key2];
262 }
263
264 var nextProps, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, dataFn;
265
266 return _regenerator2.default.wrap(function _callee$(_context) {
267 while (1) {
268 switch (_context.prev = _context.next) {
269 case 0:
270 nextProps = args[0];
271 _iteratorNormalCompletion = true;
272 _didIteratorError = false;
273 _iteratorError = undefined;
274 _context.prev = 4;
275 _iterator = (0, _getIterator3.default)(this.dataFns);
276
277 case 6:
278 if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
279 _context.next = 16;
280 break;
281 }
282
283 dataFn = _step.value;
284 _context.next = 10;
285 return dataFn(nextProps);
286
287 case 10:
288 if (!this.unmounted) {
289 _context.next = 12;
290 break;
291 }
292
293 return _context.abrupt('return');
294
295 case 12:
296 if (this.doForceUpdate) {
297 this.doForceUpdate = false;
298 this.setState(DUMMY_STATE);
299 }
300
301 case 13:
302 _iteratorNormalCompletion = true;
303 _context.next = 6;
304 break;
305
306 case 16:
307 _context.next = 22;
308 break;
309
310 case 18:
311 _context.prev = 18;
312 _context.t0 = _context['catch'](4);
313 _didIteratorError = true;
314 _iteratorError = _context.t0;
315
316 case 22:
317 _context.prev = 22;
318 _context.prev = 23;
319
320 if (!_iteratorNormalCompletion && _iterator.return) {
321 _iterator.return();
322 }
323
324 case 25:
325 _context.prev = 25;
326
327 if (!_didIteratorError) {
328 _context.next = 28;
329 break;
330 }
331
332 throw _iteratorError;
333
334 case 28:
335 return _context.finish(25);
336
337 case 29:
338 return _context.finish(22);
339
340 case 30:
341 case 'end':
342 return _context.stop();
343 }
344 }
345 }, _callee, this, [[4, 18, 22, 30], [23,, 25, 29]]);
346 }));
347
348 function UNSAFE_componentWillReceiveProps() {
349 return _ref3.apply(this, arguments);
350 }
351
352 return UNSAFE_componentWillReceiveProps;
353 }()
354
355 // TODO: Maybe throw an error when passing used $STORE to new @subscribe
356
357 }, {
358 key: 'getOrCreateModel',
359 value: function getOrCreateModel() {
360 if (this.props[$STORE] && !this.props[$STORE].__used) {
361 return this.props[$STORE];
362 } else {
363 var _model = generateScopedModel();
364 _semaphore2.default.allowComponentSetter = true;
365 _model.set('', (0, _observerUtil.observable)({})); // Initially set empty object for observable
366 _semaphore2.default.allowComponentSetter = false;
367 bindMethods(_model, HELPER_METHODS_TO_BIND);
368 return _model;
369 }
370 }
371 }, {
372 key: 'componentWillUnmount',
373 value: function componentWillUnmount() {
374 this.unmounted = true;
375
376 // Stop all subscription params computations
377 for (var index = 0; index < this.dataFns.length; index++) {
378 var computationName = getComputationName(index);
379 this.comps[computationName] && (0, _observerUtil.unobserve)(this.comps[computationName]);
380 delete this.comps[computationName];
381 }
382 delete this.dataFns;
383
384 // Destroy whole model before destroying items one by one.
385 // This prevents model.on() and model.start() from firing
386 // extra times
387 _semaphore2.default.allowComponentSetter = true;
388 this.model.destroy();
389 _semaphore2.default.allowComponentSetter = false;
390
391 // Destroy all subscription items
392 for (var key in this.items) {
393 this.destroyItem(key, true, true);
394 }
395
396 for (var _key3 in this.models) {
397 delete this.models[_key3];
398 }
399 delete this.models;
400 delete this[STORE];
401 delete this.model; // delete the actual model
402 }
403 }, {
404 key: 'render',
405 value: function render() {
406 var _this3 = this;
407
408 this.rendered = true;
409 if (this.loaded) {
410 var _extends2;
411
412 return _react2.default.createElement(DecoratedComponent, (0, _extends4.default)({}, this.props, (_extends2 = {}, (0, _defineProperty3.default)(_extends2, STORE, this[STORE]), (0, _defineProperty3.default)(_extends2, STORE_DEPRECATED, this[STORE]), _extends2), this.models, {
413 ref: function ref() {
414 if (!DecoratedComponent.__isSubscription) {
415 var _props;
416
417 if (_this3.props.innerRef) (_props = _this3.props).innerRef.apply(_props, arguments);
418 }
419 }
420 }));
421 } else {
422 // When in React Native env, don't use any loading spinner
423 if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
424 return null;
425 } else {
426 return _react2.default.createElement('div', { className: 'Loading' });
427 }
428 }
429 }
430
431 // TODO: When we change subscription params quickly, we are going to
432 // receive a race condition when earlier subscription result might
433 // take longer to process compared to the same newer subscription.
434 // Implement Queue.
435
436 }, {
437 key: 'autorunSubscriptions',
438 value: function () {
439 var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3() {
440 var _this4 = this;
441
442 var _loop, index, _ret;
443
444 return _regenerator2.default.wrap(function _callee3$(_context4) {
445 while (1) {
446 switch (_context4.prev = _context4.next) {
447 case 0:
448 this.items = {};
449 this.comps = {};
450 this.dataFns = [];
451 _loop = /*#__PURE__*/_regenerator2.default.mark(function _loop(index) {
452 var fn, subscriptions, dataFn;
453 return _regenerator2.default.wrap(function _loop$(_context3) {
454 while (1) {
455 switch (_context3.prev = _context3.next) {
456 case 0:
457 fn = fns[index];
458 subscriptions = {};
459
460 dataFn = function () {
461 var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(props) {
462 var prevSubscriptions, computationName, subscribeFn, keys, promises;
463 return _regenerator2.default.wrap(function _callee2$(_context2) {
464 while (1) {
465 switch (_context2.prev = _context2.next) {
466 case 0:
467 if (_this4.model.get()) {
468 _context2.next = 2;
469 break;
470 }
471
472 return _context2.abrupt('return');
473
474 case 2:
475 prevSubscriptions = subscriptions || {};
476 computationName = getComputationName(index);
477
478 subscribeFn = function subscribeFn() {
479 subscriptions = fn.call(_this4, typeof props === 'function' ? _this4.props : props);
480 };
481
482 _this4.comps[computationName] && (0, _observerUtil.unobserve)(_this4.comps[computationName]);
483 _this4.comps[computationName] = (0, _observerUtil.observe)(subscribeFn, {
484 scheduler: dataFn
485 });
486
487 keys = (0, _union2.default)((0, _keys3.default)(prevSubscriptions), (0, _keys3.default)(subscriptions));
488
489 keys = (0, _uniq2.default)(keys);
490 promises = [];
491
492 _batching2.default.batch(function () {
493 var _iteratorNormalCompletion2 = true;
494 var _didIteratorError2 = false;
495 var _iteratorError2 = undefined;
496
497 try {
498 for (var _iterator2 = (0, _getIterator3.default)(keys), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
499 var key = _step2.value;
500
501 if (!(0, _isEqual2.default)(subscriptions[key], prevSubscriptions[key])) {
502 if (subscriptions[key]) {
503 promises.push(_this4.initItem(key, subscriptions[key]));
504 } else {
505 _this4.destroyItem(key, true);
506 }
507 }
508 }
509 } catch (err) {
510 _didIteratorError2 = true;
511 _iteratorError2 = err;
512 } finally {
513 try {
514 if (!_iteratorNormalCompletion2 && _iterator2.return) {
515 _iterator2.return();
516 }
517 } finally {
518 if (_didIteratorError2) {
519 throw _iteratorError2;
520 }
521 }
522 }
523 });
524 _context2.next = 13;
525 return _promise2.default.all(promises);
526
527 case 13:
528 case 'end':
529 return _context2.stop();
530 }
531 }
532 }, _callee2, _this4);
533 }));
534
535 return function dataFn(_x) {
536 return _ref5.apply(this, arguments);
537 };
538 }();
539
540 _this4.dataFns.push(dataFn);
541 _context3.next = 6;
542 return dataFn(_this4.props);
543
544 case 6:
545 if (!_this4.unmounted) {
546 _context3.next = 8;
547 break;
548 }
549
550 return _context3.abrupt('return', {
551 v: void 0
552 });
553
554 case 8:
555 case 'end':
556 return _context3.stop();
557 }
558 }
559 }, _loop, _this4);
560 });
561 index = 0;
562
563 case 5:
564 if (!(index < fns.length)) {
565 _context4.next = 13;
566 break;
567 }
568
569 return _context4.delegateYield(_loop(index), 't0', 7);
570
571 case 7:
572 _ret = _context4.t0;
573
574 if (!((typeof _ret === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret)) === "object")) {
575 _context4.next = 10;
576 break;
577 }
578
579 return _context4.abrupt('return', _ret.v);
580
581 case 10:
582 index++;
583 _context4.next = 5;
584 break;
585
586 case 13:
587 // Reset force update since we are doing the initial rendering anyways
588 this.doForceUpdate = false;
589 this.loaded = true;
590 // Sometimes all the subscriptions might go through synchronously
591 // (for example if we are only subscribing to local data).
592 // In this case we don't need to manually trigger update
593 // since render will execute on its own later in the lifecycle.
594 if (this.rendered) this.setState(DUMMY_STATE);
595
596 case 16:
597 case 'end':
598 return _context4.stop();
599 }
600 }
601 }, _callee3, this);
602 }));
603
604 function autorunSubscriptions() {
605 return _ref4.apply(this, arguments);
606 }
607
608 return autorunSubscriptions;
609 }()
610
611 // TODO: Maybe implement queueing. Research if race condition is present.
612
613 }, {
614 key: 'initItem',
615 value: function initItem(key, params) {
616 var _this5 = this;
617
618 var constructor = void 0,
619 subscriptionParams = void 0;
620 var explicitType = params && params.__subscriptionType;
621 if (explicitType) {
622 subscriptionParams = params.params;
623 constructor = getItemConstructor(explicitType);
624 } else {
625 subscriptionParams = params;
626 constructor = getItemConstructorFromParams(params);
627 }
628 var item = new constructor(this.model, key, subscriptionParams);
629 // We have to use promises directly here rather than async/await,
630 // because we have to prevent async execution of init() if it is not present.
631 // But defining the function as `async` will make it run in the next event loop.
632 var finishInit = function finishInit() {
633 if (_this5.unmounted) return item.destroy();
634 _batching2.default.batch(function () {
635 if (_this5.items[key]) _this5.destroyItem(key);
636 item.refModel();
637 _this5.items[key] = item;
638 // Expose scoped model under the same name with prepended $
639 var keyModelName = getScopedModelName(key);
640 if (!_this5.models[keyModelName]) {
641 _this5.models[keyModelName] = _this5.model.at(key);
642 _this5.doForceUpdate = true;
643 }
644 });
645 };
646 if (item.init) {
647 var initRes = item.init();
648
649 if (!initRes) {
650 finishInit();
651 return _promise2.default.resolve();
652 }
653 return initRes.then(finishInit).catch(function (err) {
654 console.warn("[react-sharedb] Warning. Item couldn't initialize. " + 'This might be normal if several resubscriptions happened ' + 'quickly one after another. Error:', err);
655 // Ignore the .init() error
656 return _promise2.default.resolve();
657 });
658 } else {
659 finishInit();
660 return _promise2.default.resolve();
661 }
662 }
663
664 // TODO: Refactor to use 3 different facade methods
665
666 }, {
667 key: 'destroyItem',
668 value: function destroyItem(key, terminate, modelDestroyed) {
669 var _this6 = this;
670
671 if (!this.items[key]) return console.error('Trying to destroy', key);
672 _batching2.default.batch(function () {
673 if (!modelDestroyed) _this6.items[key].unrefModel();
674 var keyModelName = getScopedModelName(key);
675 if (terminate) {
676 delete _this6[keyModelName];
677 _this6.doForceUpdate = true;
678 }
679 _this6.items[key].destroy();
680 });
681 delete this.items[key];
682 }
683 }]);
684 return SubscriptionsContainer;
685 }(_react2.default.Component), _class.__isSubscription = true, _temp;
686};
687
688function generateScopedModel() {
689 var path = DEFAULT_COLLECTION + '.' + _model3.default.id();
690 return _model3.default.scope(path);
691}
692
693function getItemConstructor(type) {
694 switch (type) {
695 case 'Local':
696 return _Local2.default;
697 case 'Doc':
698 return _Doc2.default;
699 case 'Query':
700 return _Query2.default;
701 case 'QueryExtra':
702 return _QueryExtra2.default;
703 case 'Value':
704 return _Value2.default;
705 case 'Api':
706 return _Api2.default;
707 default:
708 throw new Error('Unsupported subscription type: ' + type);
709 }
710}
711
712// TODO: DEPRECATED
713function getItemConstructorFromParams(params) {
714 console.warn('\n [react-sharedb] Implicit auto-guessing of subscription type is DEPRECATED and will be removed in a future version.\n Please use explicit `sub*()` functions:\n - subDoc(collection, docId)\n - subQuery(collection, query)\n - subLocal(localPath)\n - subValue(value)\n ');
715 if (typeof params === 'string') return _Local2.default;
716 if ((0, _isArray2.default)(params)) {
717 var _params = (0, _slicedToArray3.default)(params, 2),
718 queryOrId = _params[1];
719
720 return typeof queryOrId === 'string' || !queryOrId ? _Doc2.default : (0, _isExtraQuery.isExtraQuery)(queryOrId) ? _QueryExtra2.default : _Query2.default;
721 }
722 throw new Error("Can't automatically determine subscription type from params: " + params);
723}
724
725function getComputationName(index) {
726 return '' + SUBSCRIBE_COMPUTATION_NAME + index;
727}
728
729function bindMethods(object, methodsToBind) {
730 var _iteratorNormalCompletion3 = true;
731 var _didIteratorError3 = false;
732 var _iteratorError3 = undefined;
733
734 try {
735 for (var _iterator3 = (0, _getIterator3.default)(methodsToBind), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
736 var method = _step3.value;
737
738 object[method] = object[method].bind(object);
739 }
740 } catch (err) {
741 _didIteratorError3 = true;
742 _iteratorError3 = err;
743 } finally {
744 try {
745 if (!_iteratorNormalCompletion3 && _iterator3.return) {
746 _iterator3.return();
747 }
748 } finally {
749 if (_didIteratorError3) {
750 throw _iteratorError3;
751 }
752 }
753 }
754}
755
756function getScopedModelName(key) {
757 return '$' + key;
758}
759module.exports = exports['default'];
\No newline at end of file