Prechádzať zdrojové kódy

chore: initial import

minhducdz99 1 mesiac pred
commit
dce325141e
100 zmenil súbory, kde vykonal 6773 pridanie a 0 odobranie
  1. 57 0
      README.md
  2. 1 0
      api/csp-report.html
  3. BIN
      assets/favicon/favicon-32.png
  4. 157 0
      assets/focus-visible/focus-visible.min.js
  5. 1 0
      assets/fonts/locale-switcher/ArabicUIText-Regular-subset.woff2
  6. 1 0
      assets/icons/sidebar-searchfield-close-on-dark.svg
  7. 1 0
      assets/indexB87DnNzwx-.js
  8. 0 0
      assets/indexBRTBTu87nN.js
  9. 0 0
      assets/indexC-lllyUtRG.css
  10. 0 0
      assets/indexC16D7IckKX.js
  11. 0 0
      assets/mt-client-logger-core.esm-rJfHcY8Zf.js
  12. 0 0
      assets/mt-metricskit-delegates-web.esmC4cdYnvnOP.js
  13. 0 0
      assets/mt-metricskit-processor-clickstream.esmBRd_H7lt9Y.js
  14. 0 0
      assets/mt-metricskit-utils-private.esmDkzakSThTT.js
  15. 0 0
      assets/translationsrCrRWHpZfd.js
  16. 0 0
      assets/versionBNUm1OH-k3.js
  17. 17 0
      node_modules/@amp/amd-apps/dist/index.js
  18. 13 0
      node_modules/@amp/amd-apps/dist/rankers/engagement-based-demotion.js
  19. 2 0
      node_modules/@amp/amd-apps/dist/rankers/entities/candidate.js
  20. 2 0
      node_modules/@amp/amd-apps/dist/rankers/entities/engagement-event.js
  21. 18 0
      node_modules/@amp/amd-apps/dist/rankers/entities/index.js
  22. 18 0
      node_modules/@amp/amd-apps/dist/rankers/index.js
  23. 23 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/index.js
  24. 250 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/json/validation.js
  25. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/alert-action.js
  26. 22 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/compound-action.js
  27. 21 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/empty-action.js
  28. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/external-url-action.js
  29. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/flow-action.js
  30. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/flow-back-action.js
  31. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/http-action.js
  32. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/http-template-action.js
  33. 26 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/index.js
  34. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/toast-action.js
  35. 39 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/artwork.js
  36. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/button.js
  37. 196 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/color.js
  38. 25 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/index.js
  39. 8 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/menu.js
  40. 4 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/paragraph.js
  41. 5 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/programmed-text.js
  42. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/video.js
  43. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/bag.js
  44. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/bundle.js
  45. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/cookie-provider.js
  46. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/cryptography.js
  47. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/host.js
  48. 55 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/index.js
  49. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/jscookie.js
  50. 19 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/net.js
  51. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/platform.js
  52. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/plist.js
  53. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/preprocessor.js
  54. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/random.js
  55. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/service.js
  56. 16 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/types.js
  57. 14 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/javascriptcore/console.js
  58. 18 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/javascriptcore/index.js
  59. 57 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/metrics.js
  60. 3 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/models.js
  61. 71 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/optional.js
  62. 10 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/util/metatype.js
  63. 373 0
      node_modules/@apple-media-services/media-api/node_modules/@jet/environment/util/urls.js
  64. 289 0
      node_modules/@apple-media-services/media-api/src/models/attributes.ts
  65. 476 0
      node_modules/@apple-media-services/media-api/src/models/server-data.ts
  66. 469 0
      node_modules/@apple-media-services/media-api/src/models/urls.ts
  67. 403 0
      node_modules/@apple-media-services/media-api/src/network.ts
  68. 1046 0
      node_modules/@floating-ui/core/dist/floating-ui.core.mjs
  69. 759 0
      node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs
  70. 154 0
      node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
  71. 138 0
      node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
  72. 14 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/app-event-page-intent.js
  73. 10 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/arcade-grouping-page-intent.js
  74. 16 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/bundle-page-intent.js
  75. 8 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/category-tabs-intent.js
  76. 13 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/charts-hub-page-intent.js
  77. 13 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/charts-page-intent.js
  78. 19 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/developer-page-intent.js
  79. 37 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/editorial/editorial-page-intent.js
  80. 14 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/editorial/editorial-shelf-collection-page-intent.js
  81. 19 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/eula-page-intent.js
  82. 33 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/grouping-page-intent.js
  83. 17 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/product-page-intent.js
  84. 16 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/room-page-intent.js
  85. 11 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/routable-arcade-see-all-page-intent.js
  86. 13 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/routable-article-page-intent.js
  87. 4 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/routable-intent.js
  88. 10 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/routable-today-page-intent.js
  89. 19 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/search-results-page-intent.js
  90. 14 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/search/search-landing-page-intent.js
  91. 13 0
      node_modules/@jet-app/app-store/tmp/src/api/intents/see-all-page-intent.js
  92. 37 0
      node_modules/@jet-app/app-store/tmp/src/api/models/accessibility.js
  93. 525 0
      node_modules/@jet-app/app-store/tmp/src/api/models/actions/actions.js
  94. 15 0
      node_modules/@jet-app/app-store/tmp/src/api/models/actions/base-action.js
  95. 26 0
      node_modules/@jet-app/app-store/tmp/src/api/models/actions/flow-action.js
  96. 26 0
      node_modules/@jet-app/app-store/tmp/src/api/models/ad-incidents.js
  97. 50 0
      node_modules/@jet-app/app-store/tmp/src/api/models/annotation.js
  98. 186 0
      node_modules/@jet-app/app-store/tmp/src/api/models/app-promotions.js
  99. 18 0
      node_modules/@jet-app/app-store/tmp/src/api/models/arcade-upsell.js
  100. 240 0
      node_modules/@jet-app/app-store/tmp/src/api/models/arcade.js

+ 57 - 0
README.md

@@ -0,0 +1,57 @@
+# Apple App Store frontend source code archive
+
+Extracted from [https://apps.apple.com/](https://apps.apple.com/). Saved using the Chrome extension [Save All Resources](https://chromewebstore.google.com/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb).
+
+### How is this possible?
+
+Because Apple forgot to disable sourcemaps in production on the App Store website 🙃
+
+<img width="795" height="548" alt="image" src="https://github.com/user-attachments/assets/59211dfb-5a56-456b-85b8-d292c1cfbfa2" />
+
+As an interesting discovery, I've archived them here on GitHub for educational purposes.
+
+## Directory Structure
+
+```
+.
+├── api/          # API related code
+├── assets/       # Static assets
+├── node_modules/ # Dependencies
+├── shared/       # Shared modules
+├── src/          # Source code
+│   ├── components/
+│   ├── config/
+│   ├── constants/
+│   ├── context/
+│   ├── stores/
+│   └── utils/
+└── us/           # US region specific
+```
+
+## What's Inside
+
+- Complete Svelte/TypeScript source code
+- State management logic
+- UI components
+- API integration code
+- Routing configuration
+- And more...
+
+## Disclaimer
+
+This repository is for educational and research purposes only. All code is copyrighted by Apple Inc.
+
+The source code was obtained from publicly accessible resources through browser developer tools.
+
+## License
+
+The content in this repository belongs to Apple Inc. If there are any copyright concerns, please contact for removal.
+
+---
+
+*Remember: Always disable sourcemaps in production! 😉*
+
+## Related
+
+- [Apple App Store](https://apps.apple.com/)
+- [Save All Resources Extension](https://chromewebstore.google.com/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb)

+ 1 - 0
api/csp-report.html

@@ -0,0 +1 @@
+No Content: https://apps.apple.com/api/csp-report

BIN
assets/favicon/favicon-32.png


+ 157 - 0
assets/focus-visible/focus-visible.min.js

@@ -0,0 +1,157 @@
+!(function (e, t) {
+    'object' == typeof exports && 'undefined' != typeof module
+        ? t()
+        : 'function' == typeof define && define.amd
+        ? define(t)
+        : t();
+})(0, function () {
+    'use strict';
+    function e(e) {
+        var t = !0,
+            n = !1,
+            o = null,
+            d = {
+                text: !0,
+                search: !0,
+                url: !0,
+                tel: !0,
+                email: !0,
+                password: !0,
+                number: !0,
+                date: !0,
+                month: !0,
+                week: !0,
+                time: !0,
+                datetime: !0,
+                'datetime-local': !0,
+            };
+        function i(e) {
+            return !!(
+                e &&
+                e !== document &&
+                'HTML' !== e.nodeName &&
+                'BODY' !== e.nodeName &&
+                'classList' in e &&
+                'contains' in e.classList
+            );
+        }
+        function s(e) {
+            e.classList.contains('focus-visible') ||
+                (e.classList.add('focus-visible'),
+                e.setAttribute('data-focus-visible-added', ''));
+        }
+        function u(e) {
+            t = !1;
+        }
+        function a() {
+            document.addEventListener('mousemove', c),
+                document.addEventListener('mousedown', c),
+                document.addEventListener('mouseup', c),
+                document.addEventListener('pointermove', c),
+                document.addEventListener('pointerdown', c),
+                document.addEventListener('pointerup', c),
+                document.addEventListener('touchmove', c),
+                document.addEventListener('touchstart', c),
+                document.addEventListener('touchend', c);
+        }
+        function c(e) {
+            (e.target.nodeName && 'html' === e.target.nodeName.toLowerCase()) ||
+                ((t = !1),
+                document.removeEventListener('mousemove', c),
+                document.removeEventListener('mousedown', c),
+                document.removeEventListener('mouseup', c),
+                document.removeEventListener('pointermove', c),
+                document.removeEventListener('pointerdown', c),
+                document.removeEventListener('pointerup', c),
+                document.removeEventListener('touchmove', c),
+                document.removeEventListener('touchstart', c),
+                document.removeEventListener('touchend', c));
+        }
+        document.addEventListener(
+            'keydown',
+            function (n) {
+                n.metaKey ||
+                    n.altKey ||
+                    n.ctrlKey ||
+                    (i(e.activeElement) && s(e.activeElement), (t = !0));
+            },
+            !0,
+        ),
+            document.addEventListener('mousedown', u, !0),
+            document.addEventListener('pointerdown', u, !0),
+            document.addEventListener('touchstart', u, !0),
+            document.addEventListener(
+                'visibilitychange',
+                function (e) {
+                    'hidden' === document.visibilityState &&
+                        (n && (t = !0), a());
+                },
+                !0,
+            ),
+            a(),
+            e.addEventListener(
+                'focus',
+                function (e) {
+                    var n, o, u;
+                    i(e.target) &&
+                        (t ||
+                            ((n = e.target),
+                            (o = n.type),
+                            ('INPUT' === (u = n.tagName) &&
+                                d[o] &&
+                                !n.readOnly) ||
+                                ('TEXTAREA' === u && !n.readOnly) ||
+                                n.isContentEditable)) &&
+                        s(e.target);
+                },
+                !0,
+            ),
+            e.addEventListener(
+                'blur',
+                function (e) {
+                    var t;
+                    i(e.target) &&
+                        (e.target.classList.contains('focus-visible') ||
+                            e.target.hasAttribute(
+                                'data-focus-visible-added',
+                            )) &&
+                        ((n = !0),
+                        window.clearTimeout(o),
+                        (o = window.setTimeout(function () {
+                            n = !1;
+                        }, 100)),
+                        (t = e.target).hasAttribute(
+                            'data-focus-visible-added',
+                        ) &&
+                            (t.classList.remove('focus-visible'),
+                            t.removeAttribute('data-focus-visible-added')));
+                },
+                !0,
+            ),
+            e.nodeType === Node.DOCUMENT_FRAGMENT_NODE && e.host
+                ? e.host.setAttribute('data-js-focus-visible', '')
+                : e.nodeType === Node.DOCUMENT_NODE &&
+                  (document.documentElement.classList.add('js-focus-visible'),
+                  document.documentElement.setAttribute(
+                      'data-js-focus-visible',
+                      '',
+                  ));
+    }
+    if ('undefined' != typeof window && 'undefined' != typeof document) {
+        var t;
+        window.applyFocusVisiblePolyfill = e;
+        try {
+            t = new CustomEvent('focus-visible-polyfill-ready');
+        } catch (e) {
+            (t = document.createEvent('CustomEvent')).initCustomEvent(
+                'focus-visible-polyfill-ready',
+                !1,
+                !1,
+                {},
+            );
+        }
+        window.dispatchEvent(t);
+    }
+    'undefined' != typeof document && e(document);
+});
+//# sourceMappingURL=focus-visible.min.js.map

+ 1 - 0
assets/fonts/locale-switcher/ArabicUIText-Regular-subset.woff2

@@ -0,0 +1 @@
+No Content: https://apps.apple.com/assets/fonts/locale-switcher/ArabicUIText-Regular-subset.woff2

+ 1 - 0
assets/icons/sidebar-searchfield-close-on-dark.svg

@@ -0,0 +1 @@
+<svg height="14" viewBox="0 0 14 14" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m7 0c3.8659932 0 7 3.13400675 7 7 0 3.8659932-3.1340068 7-7 7-3.86599325 0-7-3.1340068-7-7 0-3.86599325 3.13400675-7 7-7zm3.2615892 3.73841079c-.31788105-.31788105-.83326807-.31788105-1.15114912 0l-2.11044008 2.11058921-2.11044008-2.11058921c-.31788105-.31788105-.83326807-.31788105-1.15114913 0-.31788105.31788106-.31788105.83326808 0 1.15114913l2.11058921 2.11044008-2.11058921 2.11044008-.07284774.08335637c-.24282581.31905095-.21854323.77640179.07284774 1.06779275l.08335638.0728478c.31905094.2428258.77640179.2185432 1.06779275-.0728478l2.11044008-2.1105892 2.11044008 2.1105892c.31788105.3178811.83326807.3178811 1.15114912 0 .3178811-.31788105.3178811-.83326807 0-1.15114912l-2.1105892-2.11044008 2.1105892-2.11044008.0728478-.08335637c.2428258-.31905095.2185432-.77640179-.0728478-1.06779276z" fill="#fff" fill-opacity=".6" fill-rule="evenodd"/></svg>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
assets/indexB87DnNzwx-.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/indexBRTBTu87nN.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/indexC-lllyUtRG.css


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/indexC16D7IckKX.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/mt-client-logger-core.esm-rJfHcY8Zf.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/mt-metricskit-delegates-web.esmC4cdYnvnOP.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/mt-metricskit-processor-clickstream.esmBRd_H7lt9Y.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/mt-metricskit-utils-private.esmDkzakSThTT.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/translationsrCrRWHpZfd.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 0
assets/versionBNUm1OH-k3.js


+ 17 - 0
node_modules/@amp/amd-apps/dist/index.js

@@ -0,0 +1,17 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./rankers"), exports);

+ 13 - 0
node_modules/@amp/amd-apps/dist/rankers/engagement-based-demotion.js

@@ -0,0 +1,13 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.demoteByEngagements = void 0;
+/**
+ * Re-rank candidates by demoting candidates based on engagement events.
+ * @param candidates Recommendable entities
+ * @param engagementEvents Recorded engagement events
+ * @returns Reordered candidates
+ */
+function demoteByEngagements(candidates, _engagementEvents) {
+    return [...candidates];
+}
+exports.demoteByEngagements = demoteByEngagements;

+ 2 - 0
node_modules/@amp/amd-apps/dist/rankers/entities/candidate.js

@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });

+ 2 - 0
node_modules/@amp/amd-apps/dist/rankers/entities/engagement-event.js

@@ -0,0 +1,2 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });

+ 18 - 0
node_modules/@amp/amd-apps/dist/rankers/entities/index.js

@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./candidate"), exports);
+__exportStar(require("./engagement-event"), exports);

+ 18 - 0
node_modules/@amp/amd-apps/dist/rankers/index.js

@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./entities"), exports);
+__exportStar(require("./engagement-based-demotion"), exports);

+ 23 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/index.js

@@ -0,0 +1,23 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./models"), exports);
+__exportStar(require("./types/globals"), exports);
+__exportStar(require("./types/javascriptcore"), exports);
+__exportStar(require("./types/metrics"), exports);
+__exportStar(require("./types/models"), exports);
+__exportStar(require("./types/optional"), exports);
+//# sourceMappingURL=index.js.map

+ 250 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/json/validation.js

@@ -0,0 +1,250 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.unexpectedNull = exports.catchingContext = exports.context = exports.recordValidationIncidents = exports.endContext = exports.getContextNames = exports.beginContext = exports.messageForRecoveryAction = exports.isValidatable = exports.unexpectedType = exports.extendedTypeof = void 0;
+const optional_1 = require("../types/optional");
+/**
+ * Returns a string containing the type of a given value.
+ * This function augments the built in `typeof` operator
+ * to return sensible values for arrays and null values.
+ *
+ * @privateRemarks
+ * This function is exported for testing.
+ *
+ * @param value - The value to find the type of.
+ * @returns A string containing the type of `value`.
+ */
+function extendedTypeof(value) {
+    if (Array.isArray(value)) {
+        return "array";
+    }
+    else if (value === null) {
+        return "null";
+    }
+    else {
+        return typeof value;
+    }
+}
+exports.extendedTypeof = extendedTypeof;
+/**
+ * Reports a non-fatal validation failure, logging a message to the console.
+ * @param recovery -    The recovery action taken when the bad type was found.
+ * @param expected -    The expected type of the value.
+ * @param actual -      The actual value.
+ * @param pathString -  A string containing the path to the value on the object which failed type validation.
+ */
+function unexpectedType(recovery, expected, actual, pathString) {
+    const actualType = extendedTypeof(actual);
+    const prettyPath = (0, optional_1.isSome)(pathString) && pathString.length > 0 ? pathString : "<this>";
+    trackIncident({
+        type: "badType",
+        expected: expected,
+        // Our test assertions are matching the string interpolation of ${actual} value.
+        // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+        actual: `${actualType} (${actual})`,
+        objectPath: prettyPath,
+        contextNames: getContextNames(),
+        recoveryAction: recovery,
+        stack: new Error().stack,
+    });
+}
+exports.unexpectedType = unexpectedType;
+// endregion
+/**
+ * Determines if a given object conforms to the Validatable interface
+ * @param possibleValidatable - An object that might be considered validatable
+ *
+ * @returns `true` if it is an instance of Validatable, `false` if not
+ */
+function isValidatable(possibleValidatable) {
+    if ((0, optional_1.isNothing)(possibleValidatable)) {
+        return false;
+    }
+    // MAINTAINER'S NOTE: We must check for either the existence of a pre-existing incidents
+    //                    property *or* the ability to add one. Failure to do so will cause
+    //                    problems for clients that either a) use interfaces to define their
+    //                    view models; or b) return collections from their service routes.
+    return (Object.prototype.hasOwnProperty.call(possibleValidatable, "$incidents") ||
+        Object.isExtensible(possibleValidatable));
+}
+exports.isValidatable = isValidatable;
+/**
+ * Returns a developer-readable diagnostic message for a given recovery action.
+ * @param action - The recovery action to get the message for.
+ * @returns The message for `action`.
+ */
+function messageForRecoveryAction(action) {
+    switch (action) {
+        case "coercedValue":
+            return "Coerced format";
+        case "defaultValue":
+            return "Default value used";
+        case "ignoredValue":
+            return "Ignored value";
+        default:
+            return "Unknown";
+    }
+}
+exports.messageForRecoveryAction = messageForRecoveryAction;
+// region Contexts
+/**
+ * Shared validation context "stack".
+ *
+ * Because validation incidents propagate up the context stack,
+ * the representation used here is optimized for memory usage.
+ * A more literal representation of this would be a singly linked
+ * list describing a basic stack, but that will produce a large
+ * amount of unnecessary garbage and require copying `incidents`
+ * arrays backwards.
+ */
+const contextState = {
+    /// The names of each validation context on the stack.
+    nameStack: Array(),
+    /// All incidents reported so far. Cleared when the
+    /// context stack is emptied.
+    incidents: Array(),
+    // TODO: Removal of this is being tracked here:
+    //     <rdar://problem/35015460> Intro Pricing: Un-suppress missing parent 'offers' error when server address missing key
+    /// The paths for incidents we wish to forgo tracking.
+    suppressedIncidentPaths: Array(),
+};
+/**
+ * Begin a new validation context with a given name,
+ * pushing it onto the validation context stack.
+ * @param name - The name for the validation context.
+ */
+function beginContext(name) {
+    contextState.nameStack.push(name);
+}
+exports.beginContext = beginContext;
+/**
+ * Traverses the validation context stack and collects all of the context names.
+ * @returns The names of all validation contexts on the stack, from oldest to newest.
+ */
+function getContextNames() {
+    if (contextState.nameStack.length === 0) {
+        return ["<empty stack>"];
+    }
+    return contextState.nameStack.slice(0);
+}
+exports.getContextNames = getContextNames;
+/**
+ * Ends the current validation context
+ */
+function endContext() {
+    if (contextState.nameStack.length === 0) {
+        console.warn("endContext() called without active validation context, ignoring");
+    }
+    contextState.nameStack.pop();
+}
+exports.endContext = endContext;
+/**
+ * Records validation incidents back into an object that implements Validatable.
+ *
+ * Note: This method has a side-effect that the incident queue and name stack are cleared
+ * to prepare for the next thread's invocation.
+ *
+ * @param possibleValidatable - An object that may conform to Validatable, onto which we
+ * want to stash our validation incidents
+ */
+function recordValidationIncidents(possibleValidatable) {
+    if (isValidatable(possibleValidatable)) {
+        possibleValidatable.$incidents = contextState.incidents;
+    }
+    contextState.incidents = [];
+    contextState.nameStack = [];
+    contextState.suppressedIncidentPaths = [];
+}
+exports.recordValidationIncidents = recordValidationIncidents;
+/**
+ * Create a transient validation context, and call a function that will return a value.
+ *
+ * Prefer this function over manually calling begin/endContext,
+ * it is exception safe.
+ *
+ * @param name - The name of the context
+ * @param producer - A function that produces a result
+ * @returns <Result> The resulting type
+ */
+function context(name, producer, suppressingPath) {
+    let suppressingName = null;
+    if ((0, optional_1.isSome)(suppressingPath) && suppressingPath.length > 0) {
+        suppressingName = name;
+        contextState.suppressedIncidentPaths.push(suppressingPath);
+    }
+    let result;
+    try {
+        beginContext(name);
+        result = producer();
+    }
+    catch (e) {
+        // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
+        if (!e.hasThrown) {
+            unexpectedType("defaultValue", "no exception", e.message);
+            e.hasThrown = true;
+        }
+        throw e;
+    }
+    finally {
+        if (name === suppressingName) {
+            contextState.suppressedIncidentPaths.pop();
+        }
+        endContext();
+    }
+    return result;
+}
+exports.context = context;
+/**
+ * Create a transient validation context, that catches errors and returns null
+ *
+ * @param name - The name of the context
+ * @param producer - A function that produces a result
+ * @param caught - An optional handler to provide a value when an error is caught
+ * @returns <Result> The resulting type
+ */
+function catchingContext(name, producer, caught) {
+    let result = null;
+    try {
+        result = context(name, producer);
+    }
+    catch (e) {
+        result = null;
+        if ((0, optional_1.isSome)(caught)) {
+            result = caught(e);
+        }
+    }
+    return result;
+}
+exports.catchingContext = catchingContext;
+/**
+ * Track an incident within the current validation context.
+ * @param incident - An incident object describing the problem.
+ */
+function trackIncident(incident) {
+    if (contextState.suppressedIncidentPaths.includes(incident.objectPath)) {
+        return;
+    }
+    contextState.incidents.push(incident);
+}
+// endregion
+// region Nullability
+/**
+ * Reports a non-fatal error indicating a value was unexpectedly null.
+ * @param recovery -      The recovery action taken when the null value was found.
+ * @param expected -      The expected type of the value.
+ * @param pathString -    A string containing the path to the value on the object which was null.
+ */
+function unexpectedNull(recovery, expected, pathString) {
+    const prettyPath = (0, optional_1.isSome)(pathString) && pathString.length > 0 ? pathString : "<this>";
+    trackIncident({
+        type: "nullValue",
+        expected: expected,
+        actual: "null",
+        objectPath: prettyPath,
+        contextNames: getContextNames(),
+        recoveryAction: recovery,
+        stack: new Error().stack,
+    });
+}
+exports.unexpectedNull = unexpectedNull;
+// endregion
+//# sourceMappingURL=validation.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/alert-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=alert-action.js.map

+ 22 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/compound-action.js

@@ -0,0 +1,22 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.makeCompoundAction = exports.isCompoundAction = void 0;
+/**
+ * Custom type guard to determine if an action is a CompoundAction.
+ */
+function isCompoundAction(action) {
+    return (action === null || action === void 0 ? void 0 : action.$kind) === "compoundAction";
+}
+exports.isCompoundAction = isCompoundAction;
+/**
+ * Helper that returns a CompoundAction, given an ActionMetrics and ActionModel[] of subactions.
+ */
+function makeCompoundAction(actionMetrics, subactions) {
+    return {
+        $kind: "compoundAction",
+        subactions,
+        actionMetrics,
+    };
+}
+exports.makeCompoundAction = makeCompoundAction;
+//# sourceMappingURL=compound-action.js.map

+ 21 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/empty-action.js

@@ -0,0 +1,21 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.makeEmptyAction = exports.isEmptyAction = void 0;
+/**
+ * Custom type guard to determine if an action is an EmptyAction.
+ */
+function isEmptyAction(action) {
+    return (action === null || action === void 0 ? void 0 : action.$kind) === "emptyAction";
+}
+exports.isEmptyAction = isEmptyAction;
+/**
+ * Helper that returns an EmptyAction, given an ActionMetrics.
+ */
+function makeEmptyAction(actionMetrics) {
+    return {
+        $kind: "emptyAction",
+        actionMetrics,
+    };
+}
+exports.makeEmptyAction = makeEmptyAction;
+//# sourceMappingURL=empty-action.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/external-url-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=external-url-action.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/flow-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=flow-action.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/flow-back-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=flow-back-action.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/http-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=http-action.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/http-template-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=http-template-action.js.map

+ 26 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/index.js

@@ -0,0 +1,26 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./alert-action"), exports);
+__exportStar(require("./compound-action"), exports);
+__exportStar(require("./empty-action"), exports);
+__exportStar(require("./external-url-action"), exports);
+__exportStar(require("./flow-action"), exports);
+__exportStar(require("./flow-back-action"), exports);
+__exportStar(require("./http-action"), exports);
+__exportStar(require("./http-template-action"), exports);
+__exportStar(require("./toast-action"), exports);
+//# sourceMappingURL=index.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/actions/toast-action.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=toast-action.js.map

+ 39 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/artwork.js

@@ -0,0 +1,39 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.makeArtworkURLTemplate = void 0;
+const validation = require("../json/validation");
+const optional_1 = require("../types/optional");
+const urls_1 = require("../util/urls");
+/**
+ * Regex to parse artwork URL template string.
+ */
+const URL_TEMPLATE_PARSER = new RegExp("^({w}|[0-9]+(?:.[0-9]*)?)x({h}|[0-9]+(?:.[0-9]*)?)({c}|[a-z]{2}).({f}|[a-z]+)$");
+/**
+ * Create an instance of artwork URL template from string.
+ * @param fromString - String to create artwork URL template from.
+ * @returns A new artwork URL template or `null` if string
+ * does not represent a valid artwork URL template.
+ */
+function makeArtworkURLTemplate(fromString) {
+    // A valid URL that ends with '{w}x{h}{c}.{f}'
+    // with any of placeholders possibly resolved to an actual value.
+    const url = new urls_1.URL(fromString);
+    if (url.pathname === undefined) {
+        validation.context("makeArtworkURLTemplate", () => {
+            validation.unexpectedType("ignoredValue", "A valid URL string", fromString);
+        });
+        return null;
+    }
+    // Expecting 5 matches: whole string + width, height, crop code and format.
+    const lastPathComponent = fromString.substring(fromString.lastIndexOf("/") + 1);
+    const matches = URL_TEMPLATE_PARSER.exec(lastPathComponent);
+    if ((0, optional_1.isNothing)(matches) || matches.length !== 5) {
+        validation.context("makeArtworkURLTemplate", () => {
+            validation.unexpectedType("ignoredValue", "A valid artwork URL template ending with {w}x{h}{c}.{f} format", lastPathComponent);
+        });
+        return null;
+    }
+    return fromString;
+}
+exports.makeArtworkURLTemplate = makeArtworkURLTemplate;
+//# sourceMappingURL=artwork.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/button.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=button.js.map

+ 196 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/color.js

@@ -0,0 +1,196 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.areEqual = exports.luminanceFrom = exports.dynamicWith = exports.named = exports.rgbWith = exports.htmlWith = exports.Color = void 0;
+const optional_1 = require("../types/optional");
+// endregion
+// region Constructors
+// eslint-disable-next-line no-redeclare, @typescript-eslint/no-redeclare
+exports.Color = {
+    /**
+     * Create new `HTMLColor` from hexadecimal string representation.
+     *
+     * @param hexString - Hexadecimal string representation.
+     */
+    fromHex(string) {
+        if ((0, optional_1.isNothing)(string)) {
+            return null;
+        }
+        return {
+            $kind: "html",
+            value: string,
+        };
+    },
+    /**
+     * Create new `RBGColor` with RGB components and opacity value.
+     *
+     * @param red - Red color value.
+     * @param green - Green color value.
+     * @param blue - Blue color value.
+     * @param alpha - Opacity value.
+     */
+    fromRGB(red, green, blue, alpha = 1.0) {
+        const newColor = {
+            $kind: "rgb",
+            red: red,
+            green: green,
+            blue: blue,
+            alpha: alpha,
+        };
+        return newColor;
+    },
+    /**
+     * Create new named color using the color name.
+     *
+     * @param name - The name of the color.
+     */
+    named(name) {
+        const newColor = {
+            $kind: "named",
+            name: name,
+        };
+        return newColor;
+    },
+    /**
+     * Create new dynamic color with light and dark color variants.
+     *
+     * @param lightColor - The light color variant.
+     * @param lightHighContrastColor - The light hight-contrast color variant.
+     * @param darkColor - The dark color variant.
+     * @param darkHighContrastColor - The dark hight-contrast color variant.
+     */
+    dynamicWith(lightColor, lightHighContrastColor, darkColor, darkHighContrastColor) {
+        const newColor = {
+            $kind: "dynamic",
+            lightColor: lightColor,
+            lightHighContrastColor: lightHighContrastColor,
+            darkColor: darkColor,
+            darkHighContrastColor: darkHighContrastColor,
+        };
+        return newColor;
+    },
+    // endregion
+    // region Properties
+    /**
+     * Get the luminance of the color.
+     *
+     * @param rgbColor - The RGB color to get luminance for.
+     */
+    luminanceFrom(rgbColor) {
+        // Note: This is lifted from UIColor_Private
+        // Using RGB color components, calculates and returns (0.2126 * r) + (0.7152 * g) + (0.0722 * b).
+        return rgbColor.red * 0.2126 + rgbColor.green * 0.7152 + rgbColor.blue * 0.0722;
+    },
+    // endregion
+    // region Identity
+    /**
+     * Compare two colors for equality.
+     *
+     * @param color1 - Left hand side color to compare.
+     * @param color2 - Right hand side color to compare.
+     * @returns A Boolean indicating whether the colors are equal.
+     */
+    areEqual(color1, color2) {
+        if ((0, optional_1.isNothing)(color1)) {
+            return (0, optional_1.isNothing)(color2);
+        }
+        else if ((0, optional_1.isNothing)(color2)) {
+            return (0, optional_1.isNothing)(color1);
+        }
+        const kind1 = color1.$kind;
+        const kind2 = color2.$kind;
+        if (kind1 === "named" && kind2 === "named") {
+            const namedColor1 = color1;
+            const namedColor2 = color2;
+            return namedColor1.name === namedColor2.name;
+        }
+        else if (kind1 === "rgb" && kind2 === "rgb") {
+            const rgbColor1 = color1;
+            const rgbColor2 = color2;
+            return (rgbColor1.red === rgbColor2.red &&
+                rgbColor1.green === rgbColor2.green &&
+                rgbColor1.blue === rgbColor2.blue &&
+                rgbColor1.alpha === rgbColor2.alpha);
+        }
+        else if (kind1 === "dynamic" && kind2 === "dynamic") {
+            const dynamicColor1 = color1;
+            const dynamicColor2 = color2;
+            return (exports.Color.areEqual(dynamicColor1.lightColor, dynamicColor2.lightColor) &&
+                exports.Color.areEqual(dynamicColor1.lightHighContrastColor, dynamicColor2.lightHighContrastColor) &&
+                exports.Color.areEqual(dynamicColor1.darkColor, dynamicColor2.darkColor) &&
+                exports.Color.areEqual(dynamicColor1.darkHighContrastColor, dynamicColor2.darkHighContrastColor));
+        }
+        else {
+            return false;
+        }
+    },
+};
+/**
+ * Create new `HTMLColor` from hexadecimal string representation.
+ *
+ * @param hexString - Hexadecimal string representation.
+ *
+ * @deprecated This symbol has been moved to `Color.fromHex` and will be removed
+ * in the future.
+ */
+const htmlWith = exports.Color.fromHex;
+exports.htmlWith = htmlWith;
+/**
+ * Create new `RBGColor` with RGB components and opacity value.
+ *
+ * @param red - Red color value.
+ * @param green - Green color value.
+ * @param blue - Blue color value.
+ * @param alpha - Opacity value.
+ *
+ * @deprecated This symbol has been moved to `Color.fromRGB` and will be removed
+ * in the future.
+ */
+const rgbWith = exports.Color.fromRGB;
+exports.rgbWith = rgbWith;
+/**
+ * Create new named color using the color name.
+ *
+ * @param name - The name of the color.
+ *
+ * @deprecated This symbol has been moved to `Color.named` and will be removed
+ * in the future.
+ */
+const named = exports.Color.named;
+exports.named = named;
+/**
+ * Create new dynamic color with light and dark color variants.
+ *
+ * @param lightColor - The light color variant.
+ * @param lightHighContrastColor - The light hight-contrast color variant.
+ * @param darkColor - The dark color variant.
+ * @param darkHighContrastColor - The dark hight-contrast color variant.
+ *
+ * @deprecated This symbol has been moved to `Color.dynamicWith` and will be removed
+ * in the future.
+ */
+const dynamicWith = exports.Color.dynamicWith;
+exports.dynamicWith = dynamicWith;
+/**
+ * Get the luminance of the color.
+ *
+ * @param rgbColor - The RGB color to get luminance for.
+ *
+ * @deprecated This symbol has been moved to `Color.luminanceFrom` and will be removed
+ * in the future.
+ */
+const luminanceFrom = exports.Color.luminanceFrom;
+exports.luminanceFrom = luminanceFrom;
+/**
+ * Compare two colors for equality.
+ *
+ * @param color1 - Left hand side color to compare.
+ * @param color2 - Right hand side color to compare.
+ * @returns A Boolean indicating whether the colors are equal.
+ *
+ * @deprecated This symbol has been moved to `Color.areEqual` and will be removed
+ * in the future.
+ */
+const areEqual = exports.Color.areEqual;
+exports.areEqual = areEqual;
+// endregion
+//# sourceMappingURL=color.js.map

+ 25 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/index.js

@@ -0,0 +1,25 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./actions"), exports);
+__exportStar(require("./artwork"), exports);
+__exportStar(require("./button"), exports);
+__exportStar(require("./color"), exports);
+__exportStar(require("./menu"), exports);
+__exportStar(require("./paragraph"), exports);
+__exportStar(require("./programmed-text"), exports);
+__exportStar(require("./video"), exports);
+//# sourceMappingURL=index.js.map

+ 8 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/menu.js

@@ -0,0 +1,8 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.menuSeparatorID = void 0;
+/**
+ * A standard identifier for including a separator in a menu.
+ */
+exports.menuSeparatorID = "com.apple.JetEngine.separator";
+//# sourceMappingURL=menu.js.map

+ 4 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/paragraph.js

@@ -0,0 +1,4 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+// endregion
+//# sourceMappingURL=paragraph.js.map

+ 5 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/programmed-text.js

@@ -0,0 +1,5 @@
+"use strict";
+// region ProgrammedText
+Object.defineProperty(exports, "__esModule", { value: true });
+// endregion
+//# sourceMappingURL=programmed-text.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/models/video.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=video.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/bag.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=bag.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/bundle.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=bundle.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/cookie-provider.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=cookie-provider.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/cryptography.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=cryptography.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/host.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=host.js.map

+ 55 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/index.js

@@ -0,0 +1,55 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+/* `preprocessor` and `testContent` are normally replaced by inline literals while bundling an app's JS.
+ *
+ * If these values have not been set we want to provide defaults however
+ * attempting to access them can trigger a ReferenceError as the
+ * variables are undefined (distinct from a defined variable being set to
+ * `undefined`).
+ *
+ * `typeof` checks can safely test undefined variables, note that these checks will become:
+ * `typeof { DEBUG_BUILD: true, ... }` when webpack's DefinePlugin is used in @jet/build's webpack task.
+ * When these variables have not been replaced we need to use `globalThis` to set them on the global scope
+ * in order to avoid ReferenceErrors attempting to access them.
+ */
+if (typeof preprocessor === "undefined") {
+    globalThis.preprocessor = {
+        PRODUCTION_BUILD: false,
+        CARRY_BUILD: false,
+        DEBUG_BUILD: false,
+        INTERNAL_BUILD: false,
+    };
+}
+if (typeof testContent === "undefined") {
+    globalThis.testContent = {
+        INCLUDE_TEST_CONTENT: false,
+    };
+}
+__exportStar(require("./bag"), exports);
+__exportStar(require("./bundle"), exports);
+__exportStar(require("./cookie-provider"), exports);
+__exportStar(require("./cryptography"), exports);
+__exportStar(require("./host"), exports);
+__exportStar(require("./jscookie"), exports);
+__exportStar(require("./net"), exports);
+__exportStar(require("./platform"), exports);
+__exportStar(require("./plist"), exports);
+__exportStar(require("./preprocessor"), exports);
+__exportStar(require("./random"), exports);
+__exportStar(require("./service"), exports);
+__exportStar(require("./types"), exports);
+//# sourceMappingURL=index.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/jscookie.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=jscookie.js.map

+ 19 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/net.js

@@ -0,0 +1,19 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ProxiedNetwork = void 0;
+/**
+ * `Network` object designed to wrap the bridged native network object,
+ * which automatically includes page intent instrumentation data in the fetch request.
+ */
+class ProxiedNetwork {
+    constructor(original, pageIntentInstrumentation) {
+        this.original = original;
+        this.pageIntentInstrumentation = pageIntentInstrumentation;
+    }
+    async fetch(request) {
+        request["$pageIntentInstrumentation"] = this.pageIntentInstrumentation;
+        return await this.original.fetch(request);
+    }
+}
+exports.ProxiedNetwork = ProxiedNetwork;
+//# sourceMappingURL=net.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/platform.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=platform.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/plist.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=plist.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/preprocessor.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=preprocessor.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/random.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=random.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/service.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=service.js.map

+ 16 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/globals/types.js

@@ -0,0 +1,16 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.services = exports.random = exports.plist = exports.platform = exports.net = exports.localizer = exports.host = exports.cryptography = exports.cookieProvider = exports.bundle = exports.bag = void 0;
+const metatype_1 = require("../../util/metatype");
+exports.bag = (0, metatype_1.makeMetatype)("jet-engine:bag");
+exports.bundle = (0, metatype_1.makeMetatype)("jet-engine:bundle");
+exports.cookieProvider = (0, metatype_1.makeMetatype)("jet-engine:cookieProvider");
+exports.cryptography = (0, metatype_1.makeMetatype)("jet-engine:cryptography");
+exports.host = (0, metatype_1.makeMetatype)("jet-engine:host");
+exports.localizer = (0, metatype_1.makeMetatype)("jet-engine:localizer");
+exports.net = (0, metatype_1.makeMetatype)("jet-engine:net");
+exports.platform = (0, metatype_1.makeMetatype)("jet-engine:platform");
+exports.plist = (0, metatype_1.makeMetatype)("jet-engine:plist");
+exports.random = (0, metatype_1.makeMetatype)("jet-engine:random");
+exports.services = (0, metatype_1.makeMetatype)("jet-engine:services");
+//# sourceMappingURL=types.js.map

+ 14 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/javascriptcore/console.js

@@ -0,0 +1,14 @@
+"use strict";
+/*
+ * Describes standard functionality available in JSContexts
+ *
+ * Types are defined here to allow us to match the behavior available in JSContext in the target OS
+ * which may not exactly match the definitions in standard TypeScript lib files, particularly on a
+ * pre-release OS.
+ *
+ * The living standard for the Console API is available at https://console.spec.whatwg.org
+ * The WebKit team has documented their interfaces at https://webkit.org/web-inspector/console-object-api/
+ * The equivalent interface in Node is https://nodejs.org/api/console.html
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=console.js.map

+ 18 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/javascriptcore/index.js

@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./console"), exports);
+//# sourceMappingURL=index.js.map

+ 57 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/metrics.js

@@ -0,0 +1,57 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.notInstrumented = exports.PageInvocationPoint = exports.EMPTY_LINTED_METRICS_EVENT = void 0;
+/**
+ * An empty linted metrics event.
+ *
+ * The empty events should be skipped from recording
+ * by metrics event recorders.
+ */
+exports.EMPTY_LINTED_METRICS_EVENT = {
+    fields: {},
+    issues: [],
+};
+var PageInvocationPoint;
+(function (PageInvocationPoint) {
+    PageInvocationPoint["pageEnter"] = "pageEnter";
+    PageInvocationPoint["pageExit"] = "pageExit";
+    PageInvocationPoint["appExit"] = "appExit";
+    PageInvocationPoint["appEnter"] = "appEnter";
+    PageInvocationPoint["backButton"] = "backButton";
+})(PageInvocationPoint = exports.PageInvocationPoint || (exports.PageInvocationPoint = {}));
+/**
+ * Returns an empty metrics instance of the specified metrics type.
+ * @param metricsType - Type of the metrics data to return.
+ *
+ * @deprecated Do not use, all metrics events should be instrumented.
+ */
+function notInstrumented(metricsType) {
+    switch (metricsType) {
+        case 0 /* NotInstrumentedMetricsType.ActionMetrics */:
+            return {
+                data: [],
+                custom: {},
+            };
+        case 1 /* NotInstrumentedMetricsType.FetchTimingMetrics */:
+            return {};
+        case 2 /* NotInstrumentedMetricsType.PageMetrics */:
+            return {
+                instructions: [],
+                custom: {},
+            };
+        case 3 /* NotInstrumentedMetricsType.ImpressionMetrics */:
+            return {
+                id: {
+                    id: "",
+                    impressionIndex: NaN,
+                },
+                fields: {},
+                custom: {},
+            };
+        default:
+            return {};
+    }
+}
+exports.notInstrumented = notInstrumented;
+// endregion
+//# sourceMappingURL=metrics.js.map

+ 3 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/models.js

@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=models.js.map

+ 71 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/types/optional.js

@@ -0,0 +1,71 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.flatMapOptional = exports.mapOptional = exports.unsafeUnwrapOptional = exports.unwrapOptional = exports.isSome = exports.isNothing = exports.unsafeUninitialized = void 0;
+/**
+ * Bypass the protection provided by the `Optional` type
+ * and pretend to produce a value of `Some<T>` while
+ * actually returning `Nothing`.
+ */
+function unsafeUninitialized() {
+    return undefined;
+}
+exports.unsafeUninitialized = unsafeUninitialized;
+/**
+ * Test whether an optional does not contain a value.
+ *
+ * @param value - An optional value to test.
+ */
+function isNothing(value) {
+    return value === undefined || value === null;
+}
+exports.isNothing = isNothing;
+/**
+ * Test whether an optional contains a value.
+ * @param value - An optional value to test.
+ */
+function isSome(value) {
+    return value !== undefined && value !== null;
+}
+exports.isSome = isSome;
+/**
+ * Unwrap the value contained in a given optional,
+ * throwing an error if there is no value.
+ *
+ * @param value - A value to unwrap.
+ */
+function unwrapOptional(value) {
+    if (isNothing(value)) {
+        throw new ReferenceError();
+    }
+    return value;
+}
+exports.unwrapOptional = unwrapOptional;
+/**
+ * Unwrap the value contained in a given optional
+ * without checking if the value exists.
+ *
+ * @param value - A value to unwrap.
+ */
+function unsafeUnwrapOptional(value) {
+    return value;
+}
+exports.unsafeUnwrapOptional = unsafeUnwrapOptional;
+function mapOptional(value, body) {
+    if (isSome(value)) {
+        return body(value);
+    }
+    else {
+        return value;
+    }
+}
+exports.mapOptional = mapOptional;
+function flatMapOptional(value, body) {
+    if (isSome(value)) {
+        return body(value);
+    }
+    else {
+        return value;
+    }
+}
+exports.flatMapOptional = flatMapOptional;
+//# sourceMappingURL=optional.js.map

+ 10 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/util/metatype.js

@@ -0,0 +1,10 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.makeMetatype = void 0;
+function makeMetatype(name) {
+    return {
+        name: name,
+    };
+}
+exports.makeMetatype = makeMetatype;
+//# sourceMappingURL=metatype.js.map

+ 373 - 0
node_modules/@apple-media-services/media-api/node_modules/@jet/environment/util/urls.js

@@ -0,0 +1,373 @@
+"use strict";
+// MARK: - Parsing Regular Expressions
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.URL = void 0;
+const optional_1 = require("../types/optional");
+const protocolRegex = /^([a-z][a-z0-9.+-]*:)(\/\/)?([\S\s]*)/i;
+const queryParamRegex = /([^=?&]+)=?([^&]*)/g;
+const componentOrder = ["hash", "query", "pathname", "host"];
+class URL {
+    constructor(url) {
+        var _a;
+        this.query = {};
+        if ((0, optional_1.isNothing)(url)) {
+            return;
+        }
+        // Split the protocol from the rest of the urls
+        let remainder = url;
+        const match = protocolRegex.exec(url);
+        if ((0, optional_1.isSome)(match)) {
+            // Pull out the protocol
+            let protocol = match[1];
+            if (protocol !== null && protocol !== undefined) {
+                protocol = protocol.split(":")[0];
+            }
+            this.protocol = protocol !== null && protocol !== void 0 ? protocol : undefined;
+            // Save the remainder
+            remainder = (_a = match[3]) !== null && _a !== void 0 ? _a : undefined;
+        }
+        // Then match each component in a specific order
+        let parse = { remainder: remainder, result: undefined };
+        for (const component of componentOrder) {
+            if (parse === undefined || parse.remainder === undefined) {
+                break;
+            }
+            switch (component) {
+                case "hash": {
+                    parse = splitUrlComponent(parse.remainder, "#", "suffix");
+                    this.hash = parse === null || parse === void 0 ? void 0 : parse.result;
+                    break;
+                }
+                case "query": {
+                    parse = splitUrlComponent(parse.remainder, "?", "suffix");
+                    if ((parse === null || parse === void 0 ? void 0 : parse.result) !== undefined) {
+                        this.query = URL.queryFromString(parse.result);
+                    }
+                    break;
+                }
+                case "pathname": {
+                    parse = splitUrlComponent(parse.remainder, "/", "suffix");
+                    if ((parse === null || parse === void 0 ? void 0 : parse.result) !== undefined) {
+                        // Replace the initial /, since paths require it
+                        this.pathname = "/" + parse.result;
+                    }
+                    break;
+                }
+                case "host": {
+                    const authorityParse = splitUrlComponent(parse.remainder, "@", "prefix");
+                    const userInfo = authorityParse === null || authorityParse === void 0 ? void 0 : authorityParse.result;
+                    const hostPort = authorityParse === null || authorityParse === void 0 ? void 0 : authorityParse.remainder;
+                    if (userInfo !== undefined) {
+                        const userInfoSplit = userInfo.split(":");
+                        this.username = decodeURIComponent(userInfoSplit[0]);
+                        this.password = decodeURIComponent(userInfoSplit[1]);
+                    }
+                    if (hostPort !== undefined) {
+                        const hostPortSplit = hostPort.split(":");
+                        this.host = hostPortSplit[0];
+                        this.port = hostPortSplit[1];
+                    }
+                    break;
+                }
+                default: {
+                    throw new Error("Unhandled case!");
+                }
+            }
+        }
+    }
+    get(component) {
+        switch (component) {
+            // Exhaustive match to make sure TS property minifiers and other
+            // transformer plugins do not break this code.
+            case "protocol":
+                return this.protocol;
+            case "username":
+                return this.username;
+            case "password":
+                return this.password;
+            case "port":
+                return this.port;
+            case "pathname":
+                return this.pathname;
+            case "query":
+                return this.query;
+            case "hash":
+                return this.hash;
+            default:
+                // The fallback for component which is not a property of URL object.
+                return this[component];
+        }
+    }
+    set(component, value) {
+        if (value === undefined) {
+            return this;
+        }
+        if (component === "query") {
+            if (typeof value === "string") {
+                value = URL.queryFromString(value);
+            }
+        }
+        switch (component) {
+            // Exhaustive match to make sure TS property minifiers and other
+            // transformer plugins do not break this code.
+            case "protocol":
+                this.protocol = value;
+                break;
+            case "username":
+                this.username = value;
+                break;
+            case "password":
+                this.password = value;
+                break;
+            case "port":
+                this.port = value;
+                break;
+            case "pathname":
+                this.pathname = value;
+                break;
+            case "query":
+                this.query = value;
+                break;
+            case "hash":
+                this.hash = value;
+                break;
+            default:
+                // The fallback for component which is not a property of URL object.
+                this[component] = value;
+                break;
+        }
+        return this;
+    }
+    append(component, value) {
+        let existingValue = this.get(component);
+        let newValue;
+        if (component === "query") {
+            if (existingValue === undefined) {
+                existingValue = {};
+            }
+            if (typeof value === "string") {
+                value = URL.queryFromString(value);
+            }
+            if (typeof existingValue === "string") {
+                newValue = { existingValue, ...value };
+            }
+            else {
+                newValue = { ...existingValue, ...value };
+            }
+        }
+        else {
+            if (existingValue === undefined) {
+                existingValue = "";
+            }
+            let existingValueString = existingValue;
+            if (existingValueString === undefined) {
+                existingValueString = "";
+            }
+            let newValueString = existingValueString;
+            if (component === "pathname") {
+                const pathLength = existingValueString.length;
+                if (pathLength === 0 || existingValue[pathLength - 1] !== "/") {
+                    newValueString += "/";
+                }
+            }
+            // The component is not "query" so we treat value as string.
+            // eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-plus-operands
+            newValueString += value;
+            newValue = newValueString;
+        }
+        return this.set(component, newValue);
+    }
+    param(key, value) {
+        if (key === null) {
+            return this;
+        }
+        if (this.query === undefined) {
+            this.query = {};
+        }
+        if (value === undefined) {
+            // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+            delete this.query[key];
+        }
+        else {
+            this.query[key] = value;
+        }
+        return this;
+    }
+    removeParam(key) {
+        if (key === undefined || this.query === undefined) {
+            return this;
+        }
+        if (key in this.query) {
+            // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+            delete this.query[key];
+        }
+        return this;
+    }
+    path(value) {
+        return this.append("pathname", value);
+    }
+    pathExtension() {
+        var _a, _b;
+        // Extract path extension if one exists
+        if (this.pathname === undefined) {
+            return undefined;
+        }
+        const lastFilenameComponents = (_b = (_a = this.pathname
+            .split("/")
+            .filter((item) => item.length > 0) // Remove any double or trailing slashes
+            .pop()) === null || _a === void 0 ? void 0 : _a.split(".")) !== null && _b !== void 0 ? _b : [];
+        if (lastFilenameComponents.filter(function (part) {
+            return part !== "";
+        }).length < 2 // Remove any empty parts (e.g. .ssh_config -> ["ssh_config"])
+        ) {
+            return undefined;
+        }
+        return lastFilenameComponents.pop();
+    }
+    /**
+     * Returns the path components of the URL
+     * @returns An array of non-empty path components from `urls`.
+     */
+    pathComponents() {
+        if (this.pathname === undefined) {
+            return [];
+        }
+        return this.pathname.split("/").filter((component) => component.length > 0);
+    }
+    /**
+     * Same as toString
+     *
+     * @returns A string representation of the URL
+     */
+    build() {
+        return this.toString();
+    }
+    /**
+     * Converts the URL to a string
+     *
+     * @returns A string representation of the URL
+     */
+    toString() {
+        let url = "";
+        if (this.protocol !== undefined) {
+            url += this.protocol + "://";
+        }
+        if (this.username !== undefined) {
+            url += encodeURIComponent(this.username);
+            if (this.password !== undefined) {
+                url += ":" + encodeURIComponent(this.password);
+            }
+            url += "@";
+        }
+        if (this.host !== undefined) {
+            url += this.host;
+            if (this.port !== undefined) {
+                url += ":" + this.port;
+            }
+        }
+        if (this.pathname !== undefined) {
+            url += this.pathname;
+        }
+        if (this.query !== undefined && Object.keys(this.query).length !== 0) {
+            url += "?" + URL.toQueryString(this.query);
+        }
+        if (this.hash !== undefined) {
+            url += "#" + this.hash;
+        }
+        return url;
+    }
+    // ----------------
+    // Static API
+    // ----------------
+    /**
+     * Converts a string into a query dictionary
+     * @param query - The string to parse
+     * @returns The query dictionary containing the key-value pairs in the query string
+     */
+    static queryFromString(query) {
+        const result = {};
+        let parseResult = queryParamRegex.exec(query);
+        while (parseResult !== null && parseResult.length >= 3) {
+            // We support the legacy query format for "application/x-www-form-urlencoded" which can represent spaces as "+" symbols.
+            // https://url.spec.whatwg.org/#concept-urlencoded-parser
+            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#decoding_query_parameters_from_a_url
+            const key = decodeURIComponent(parseResult[1].replace(/\+/g, " "));
+            const value = decodeURIComponent(parseResult[2].replace(/\+/g, " "));
+            result[key] = value;
+            parseResult = queryParamRegex.exec(query);
+        }
+        return result;
+    }
+    /**
+     * Converts a query dictionary into a query string
+     *
+     * @param query - The query dictionary
+     * @returns The string representation of the query dictionary
+     */
+    static toQueryString(query) {
+        let queryString = "";
+        let first = true;
+        for (const key of Object.keys(query)) {
+            if (!first) {
+                queryString += "&";
+            }
+            first = false;
+            queryString += encodeURIComponent(key);
+            const value = query[key];
+            if (value !== null && value.length > 0) {
+                queryString += "=" + encodeURIComponent(value);
+            }
+        }
+        return queryString;
+    }
+    /**
+     * Convenience method to instantiate a URL from a string
+     * @param url - The URL string to parse
+     * @returns The new URL object representing the URL
+     */
+    static from(url) {
+        return new URL(url);
+    }
+    /**
+     * Convenience method to instantiate a URL from numerous (optional) components
+     * @param protocol - The protocol type
+     * @param host - The host name
+     * @param path - The path
+     * @param query - The query
+     * @param hash - The hash
+     * @returns The new URL object representing the URL
+     */
+    static fromComponents(protocol, host, path, query, hash) {
+        const url = new URL();
+        url.protocol = protocol;
+        url.host = host;
+        url.pathname = path;
+        url.query = query !== null && query !== void 0 ? query : {};
+        url.hash = hash;
+        return url;
+    }
+}
+exports.URL = URL;
+// MARK: - Helpers
+function splitUrlComponent(input, marker, style) {
+    const index = input.indexOf(marker);
+    let result;
+    let remainder = input;
+    if (index !== -1) {
+        const prefix = input.slice(0, index);
+        const suffix = input.slice(index + marker.length, input.length);
+        if (style === "prefix") {
+            result = prefix;
+            remainder = suffix;
+        }
+        else {
+            result = suffix;
+            remainder = prefix;
+        }
+    }
+    return {
+        result: result,
+        remainder: remainder,
+    };
+}
+//# sourceMappingURL=urls.js.map

+ 289 - 0
node_modules/@apple-media-services/media-api/src/models/attributes.ts

@@ -0,0 +1,289 @@
+import { Opt, isNothing } from "@jet/environment/types/optional";
+import * as serverData from "./server-data";
+import * as media from "./data-structure";
+import { JSONValue, MapLike, JSONData } from "./json-types";
+import * as errors from "./errors";
+
+// region Generic Attribute retrieval
+
+// region Attribute retrieval
+
+/**
+ * Retrieve the specified attribute from the data, coercing it to a JSONData dictionary
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns The dictionary of data
+ */
+export function attributeAsDictionary<Type extends JSONValue>(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    defaultValue?: MapLike<Type>,
+): MapLike<Type> | null {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    return serverData.asDictionary(data.attributes, attributePath, defaultValue);
+}
+
+/**
+ * Retrieve the specified attribute from the data, coercing it to an Interface
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param defaultValue The object to return if the path search fails.
+ * @returns The dictionary of data as an interface
+ */
+export function attributeAsInterface<Interface>(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    defaultValue?: JSONData,
+): Interface | null {
+    return attributeAsDictionary(data, attributePath, defaultValue) as unknown as Interface;
+}
+
+/**
+ * Retrieve the specified attribute from the data as an array, coercing to an empty array if the object is not an array.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @returns {any[]} The attribute value as an array.
+ */
+export function attributeAsArrayOrEmpty<T extends JSONValue>(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+): T[] {
+    if (serverData.isNull(data)) {
+        return [];
+    }
+    return serverData.asArrayOrEmpty(data.attributes, attributePath);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a string.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The object path for the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {string} The attribute value as a string.
+ */
+export function attributeAsString(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    policy: serverData.ValidationPolicy = "coercible",
+): Opt<string> {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    return serverData.asString(data.attributes, attributePath, policy);
+}
+
+/**
+ * Retrieve the specified meta from the data as a string.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param metaPath The object path for the meta.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {string} The meta value as a string.
+ */
+export function metaAsString(
+    data: media.Data,
+    metaPath?: serverData.ObjectPath,
+    policy: serverData.ValidationPolicy = "coercible",
+): Opt<string> {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    return serverData.asString(data.meta, metaPath, policy);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a date.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The object path for the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {Date} The attribute value as a date.
+ */
+export function attributeAsDate(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    policy: serverData.ValidationPolicy = "coercible",
+): Opt<Date> {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    const dateString = serverData.asString(data.attributes, attributePath, policy);
+    if (isNothing(dateString)) {
+        return null;
+    }
+    return new Date(dateString);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a boolean.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {boolean} The attribute value as a boolean.
+ */
+export function attributeAsBoolean(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    policy: serverData.ValidationPolicy = "coercible",
+): boolean | null {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    return serverData.asBoolean(data.attributes, attributePath, policy);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a boolean, which will be `false` if the attribute does not exist.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @returns {boolean} The attribute value as a boolean, coercing to `false` if the value is not present..
+ */
+export function attributeAsBooleanOrFalse(data: media.Data, attributePath?: serverData.ObjectPath): boolean {
+    if (serverData.isNull(data)) {
+        return false;
+    }
+    return serverData.asBooleanOrFalse(data.attributes, attributePath);
+}
+
+/**
+ * Retrieve the specified attribute from the data as a number.
+ *
+ * @param data The data from which to retrieve the attribute.
+ * @param attributePath The path of the attribute.
+ * @param policy The validation policy to use when resolving this value.
+ * @returns {boolean} The attribute value as a number.
+ */
+export function attributeAsNumber(
+    data: media.Data,
+    attributePath?: serverData.ObjectPath,
+    policy: serverData.ValidationPolicy = "coercible",
+): Opt<number> {
+    if (serverData.isNull(data)) {
+        return null;
+    }
+    return serverData.asNumber(data.attributes, attributePath, policy);
+}
+
+export function hasAttributes(data: media.Data): boolean {
+    return !serverData.isNull(serverData.asDictionary(data, "attributes"));
+}
+
+/**
+ * The canonical way to detect if an item from Media API is hydrated or not.
+ *
+ * @param data The data from which to retrieve the attributes.
+ */
+export function isNotHydrated(data: media.Data): boolean {
+    return !hasAttributes(data);
+}
+
+// region Custom Attributes
+
+/**
+ * Performs conversion for a custom variant of given attribute, if any are available.
+ * @param attribute Attribute to get custom attribute key for, if any.
+ */
+export function attributeKeyAsCustomAttributeKey(attribute: string): string | undefined {
+    return customAttributeMapping[attribute];
+}
+
+/**
+ * Whether or not given custom attributes key allows fallback to default page with AB testing treatment within a nondefault page.
+ * This is to allow AB testing to affect only icons within custom product pages.
+ */
+export function attributeAllowsNonDefaultTreatmentInNonDefaultPage(customAttribute: string): boolean {
+    return customAttribute === "customArtwork" || customAttribute === "customIconArtwork"; // Only the icon artwork.
+}
+
+/**
+ * Defines mapping of attribute to custom attribute.
+ */
+const customAttributeMapping: { [key: string]: string } = {
+    artwork: "customArtwork",
+    iconArtwork: "customIconArtwork",
+    screenshotsByType: "customScreenshotsByType",
+    promotionalText: "customPromotionalText",
+    videoPreviewsByType: "customVideoPreviewsByType",
+    customScreenshotsByTypeForAd: "customScreenshotsByTypeForAd",
+    customVideoPreviewsByTypeForAd: "customVideoPreviewsByTypeForAd",
+};
+
+export function requiredAttributeAsString(data: media.Data, attributePath: serverData.ObjectPath): string {
+    const value = attributeAsString(data, attributePath);
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+    }
+    return value;
+}
+
+export function requiredAttributeAsDate(data: media.Data, attributePath: serverData.ObjectPath): Date {
+    const value = attributeAsDate(data, attributePath);
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+    }
+    return value;
+}
+
+export function requiredAttributeAsDictionary<Type extends JSONValue>(
+    data: media.Data,
+    attributePath: serverData.ObjectPath,
+): MapLike<Type> {
+    const value: MapLike<Type> | null = attributeAsDictionary(data, attributePath);
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, concatObjectPaths("attributes", attributePath));
+    }
+    return value;
+}
+
+export function requiredMeta(data: media.Data): MapLike<JSONValue> {
+    const value = serverData.asDictionary(data, "meta");
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, "meta");
+    }
+    return value;
+}
+
+export function requiredMetaAttributeAsString(data: media.Data, attributePath: serverData.ObjectPath): string {
+    const meta = requiredMeta(data);
+    const value = serverData.asString(meta, attributePath);
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, concatObjectPaths("meta", attributePath));
+    }
+    return value;
+}
+
+export function requiredMetaAttributeAsNumber(data: media.Data, attributePath: serverData.ObjectPath): number {
+    const meta = requiredMeta(data);
+    const value = serverData.asNumber(meta, attributePath);
+    if (isNothing(value)) {
+        throw new errors.MissingFieldError(data, concatObjectPaths("meta", attributePath));
+    }
+    return value;
+}
+
+export function concatObjectPaths(prefix: serverData.ObjectPath, suffix: serverData.ObjectPath): serverData.ObjectPath {
+    let finalPath: string[];
+    if (Array.isArray(prefix)) {
+        finalPath = prefix;
+    } else {
+        finalPath = [prefix];
+    }
+
+    if (Array.isArray(suffix)) {
+        finalPath.push(...suffix);
+    } else {
+        finalPath.push(suffix);
+    }
+    return finalPath;
+}
+
+// endregion

+ 476 - 0
node_modules/@apple-media-services/media-api/src/models/server-data.ts

@@ -0,0 +1,476 @@
+//
+//  server-data.ts
+//  AppStoreKit
+//
+//  Created by Kevin MacWhinnie on 8/17/16.
+//  Copyright (c) 2016 Apple Inc. All rights reserved.
+//
+
+// TODO: Replace this utility for JSON Parsing
+import * as validation from "@jet/environment/json/validation";
+import { Nothing, Opt, isNothing } from "@jet/environment/types/optional";
+import { JSONArray, JSONData, JSONValue, MapLike } from "./json-types";
+
+// region Traversal
+
+/**
+ * Union type that describes the possible representations for an object traversal path.
+ */
+export type ObjectPath = string | string[];
+
+/**
+ * Returns the string representation of a given object path.
+ * @param path  The object path to coerce to a string.
+ * @returns A string representation of `path`.
+ */
+export function objectPathToString(path: Opt<ObjectPath>): Opt<string> {
+    if (isNull(path)) {
+        return null;
+    } else if (Array.isArray(path)) {
+        return path.join(".");
+    } else {
+        return path;
+    }
+}
+
+const PARSED_PATH_CACHE: { [key: string]: string[] } = {};
+
+/**
+ *  Traverse a nested JSON object structure, short-circuiting
+ *  when finding `undefined` or `null` values. Usage:
+ *
+ *      const object = {x: {y: {z: 42}}};
+ *      const meaningOfLife = serverData.traverse(object, 'x.y.z');
+ *
+ *  @param  object  The JSON object to traverse.
+ *  @param  path    The path to search. If falsy, `object` will be returned without being traversed.
+ *  @param  defaultValue The object to return if the path search fails.
+ *  @return The value at `path` if found; default value otherwise.
+ */
+export function traverse(object: JSONValue, path?: ObjectPath, defaultValue?: JSONValue): JSONValue {
+    if (object === undefined || object === null) {
+        return defaultValue;
+    }
+
+    if (isNullOrEmpty(path)) {
+        return object;
+    }
+
+    let components: string[];
+    if (typeof path === "string") {
+        components = PARSED_PATH_CACHE[path];
+        if (isNullOrEmpty(components)) {
+            // Fast Path: If the path contains only a single component, we can skip
+            //            all of the work below here and speed up storefronts that
+            //            don't have JIT compilation enabled.
+            if (!path.includes(".")) {
+                const value = object[path];
+                if (value !== undefined && value !== null) {
+                    return value;
+                } else {
+                    return defaultValue;
+                }
+            }
+
+            components = path.split(".");
+            PARSED_PATH_CACHE[path] = components;
+        }
+    } else {
+        components = path;
+    }
+
+    let current: JSONValue = object;
+    for (const component of components) {
+        current = current[component];
+        if (current === undefined || current === null) {
+            return defaultValue;
+        }
+    }
+    return current;
+}
+
+// endregion
+
+// region Nullability
+
+/**
+ *  Returns a bool indicating whether or not a given object null or undefined.
+ *  @param  object  The object to test.
+ *  @return true if the object is null or undefined; false otherwise.
+ */
+export function isNull<Type>(object: Type | Nothing): object is Nothing {
+    return object === null || object === undefined;
+}
+
+/**
+ * Returns a bool indicating whether or not a given object is null or empty.
+ * @param object The object to test
+ * @return true if object is null or empty; false otherwise.
+ */
+export function isNullOrEmpty<Type>(object: Type | Nothing): object is Nothing {
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    return isNull(object) || Object.keys(object as any).length === 0;
+}
+
+/**
+ *  Returns a bool indicating whether or not a given object is non-null.
+ *  @param  object  The object to test.
+ *  @return true if the object is not null or undefined; false otherwise.
+ */
+export function isDefinedNonNull<Type>(object: Type | null | undefined): object is Type {
+    return typeof object !== "undefined" && object !== null;
+}
+
+/**
+ *  Returns a bool indicating whether or not a given object is non-null or empty.
+ *  @param  object  The object to test.
+ *  @return true if the object is not null or undefined and not empty; false otherwise.
+ */
+export function isDefinedNonNullNonEmpty<Type>(object: Type | Nothing): object is Type {
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    return isDefinedNonNull(object) && Object.keys(object as any).length !== 0;
+}
+
+/**
+ * Checks if the passed string or number is a number
+ *
+ * @param value The value to check
+ * @return True if the value is an number, false if not
+ */
+export function isNumber(value: number | string | null | undefined): value is number {
+    if (isNull(value)) {
+        return false;
+    }
+
+    let valueToCheck;
+    if (typeof value === "string") {
+        valueToCheck = parseInt(value);
+    } else {
+        valueToCheck = value;
+    }
+
+    return !Number.isNaN(valueToCheck);
+}
+
+/**
+ *  Returns a bool indicating whether or not a given object is defined but empty.
+ *  @param  object  The object to test.
+ *  @return true if the object is not null and empty; false otherwise.
+ */
+export function isArrayDefinedNonNullAndEmpty<Type extends JSONArray>(object: Type | null | undefined): object is Type {
+    return isDefinedNonNull(object) && object.length === 0;
+}
+
+// endregion
+
+// region Defaulting Casts
+
+/**
+ * Check that a given object is an array, substituting an empty array if not.
+ * @param object    The object to coerce.
+ * @param path      The path to traverse on `object` to find an array.
+ *                  Omit this parameter if `object` is itself an array.
+ * @returns An untyped array.
+ */
+export function asArrayOrEmpty<T extends JSONValue>(object: JSONValue, path?: ObjectPath): T[] {
+    const target = traverse(object, path, null);
+    if (Array.isArray(target)) {
+        // Note: This is kind of a nasty cast, but I don't think we want to validate that everything is of type T
+        return target as T[];
+    } else {
+        if (!isNull(target)) {
+            validation.context("asArrayOrEmpty", () => {
+                validation.unexpectedType("defaultValue", "array", target, objectPathToString(path));
+            });
+        }
+        return [];
+    }
+}
+
+/**
+ * Check that a given object is a boolean, substituting the value `false` if not.
+ * @param object    The object to coerce.
+ * @param path      The path to traverse on `object` to find a boolean.
+ *                  Omit this parameter if `object` is itself a boolean.
+ * @returns A boolean from `object`, or defaults to `false`.
+ */
+export function asBooleanOrFalse(object: JSONValue, path?: ObjectPath): boolean {
+    const target = traverse(object, path, null);
+    if (typeof target === "boolean") {
+        return target;
+    } else {
+        if (!isNull(target)) {
+            validation.context("asBooleanOrFalse", () => {
+                validation.unexpectedType("defaultValue", "boolean", target, objectPathToString(path));
+            });
+        }
+        return false;
+    }
+}
+
+// endregion
+
+// region Coercing Casts
+
+export type ValidationPolicy = "strict" | "coercible" | "none";
+
+/**
+ * Safely coerce an object into a string.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find a string.
+ *                          Omit this parameter if `object` is itself a string.
+ * @param policy            The validation policy to use when resolving this value
+ * @returns A string from `object`, or `null` if `object` is null.
+ */
+export function asString(object: JSONValue, path?: ObjectPath, policy: ValidationPolicy = "coercible"): Opt<string> {
+    const target = traverse(object, path, null);
+    if (isNull(target)) {
+        return target;
+    } else if (typeof target === "string") {
+        return target;
+    } else {
+        // We don't consider arbitrary objects as convertable to strings even through they will result in some value
+        const coercedValue = typeof target === "object" ? null : String(target);
+        switch (policy) {
+            case "strict": {
+                validation.context("asString", () => {
+                    validation.unexpectedType("coercedValue", "string", target, objectPathToString(path));
+                });
+                break;
+            }
+            case "coercible": {
+                if (isNull(coercedValue)) {
+                    validation.context("asString", () => {
+                        validation.unexpectedType("coercedValue", "string", target, objectPathToString(path));
+                    });
+                }
+                break;
+            }
+            case "none":
+            default: {
+                break;
+            }
+        }
+
+        return coercedValue;
+    }
+}
+
+/**
+ * Safely coerce an object into a date.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find a date.
+ * @param policy            The validation policy to use when resolving this value
+ * @returns A date from `object`, or `null` if `object` is null.
+ */
+export function asDate(object: JSONValue, path?: ObjectPath, policy: ValidationPolicy = "coercible"): Opt<Date> {
+    const dateString = asString(object, path, policy);
+    if (isNothing(dateString)) {
+        return null;
+    }
+    return new Date(dateString);
+}
+
+/**
+ * Safely coerce an object into a number.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find a number.
+ *                          Omit this parameter if `object` is itself a number.
+ * @param policy            The validation policy to use when resolving this value
+ * @returns A number from `object`, or `null` if `object` is null.
+ */
+export function asNumber(object: JSONValue, path?: ObjectPath, policy: ValidationPolicy = "coercible"): Opt<number> {
+    const target = traverse(object, path, null);
+    if (isNull(target) || typeof target === "number") {
+        return target;
+    } else {
+        const coercedValue = Number(target);
+        switch (policy) {
+            case "strict": {
+                validation.context("asNumber", () => {
+                    validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+                });
+                break;
+            }
+            case "coercible": {
+                if (isNaN(coercedValue)) {
+                    validation.context("asNumber", () => {
+                        validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+                    });
+                    return null;
+                }
+                break;
+            }
+            case "none":
+            default: {
+                break;
+            }
+        }
+
+        return coercedValue;
+    }
+}
+
+/**
+ * Safely coerce an object into a dictionary.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find the dictionary.
+ *                          Omit this parameter if `object` is itself a dictionary.
+ * @param  defaultValue The object to return if the path search fails.
+ * @returns A sub-dictionary from `object`, or `null` if `object` is null.
+ */
+export function asDictionary<Type extends JSONValue>(
+    object: JSONValue,
+    path?: ObjectPath,
+    defaultValue?: MapLike<Type>,
+): MapLike<Type> | null {
+    const target = traverse(object, path, null);
+    if (target instanceof Object && !Array.isArray(target)) {
+        // Note: It's too expensive to actually validate this is a dictionary of { string : Type } at run time
+        return target as MapLike<Type>;
+    } else {
+        if (!isNull(target)) {
+            validation.context("asDictionary", () => {
+                validation.unexpectedType("defaultValue", "object", target, objectPathToString(path));
+            });
+        }
+
+        if (isDefinedNonNull(defaultValue)) {
+            return defaultValue;
+        }
+        return null;
+    }
+}
+
+/**
+ * Safely coerce an object into a given interface.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find a string.
+ *                          Omit this parameter if `object` is itself a string.
+ * @param  defaultValue The object to return if the path search fails.
+ * @returns A sub-dictionary from `object`, or `null` if `object` is null.
+ */
+export function asInterface<Interface>(
+    object: JSONValue,
+    path?: ObjectPath,
+    defaultValue?: JSONData,
+): Interface | null {
+    return asDictionary(object, path, defaultValue) as unknown as Interface;
+}
+
+/**
+ * Coerce an object into a boolean.
+ * @param object            The object to coerce.
+ * @param path              The path to traverse on `object` to find a boolean.
+ *                          Omit this parameter if `object` is itself a boolean.
+ * @param policy            The validation policy to use when resolving this value
+ * @returns A boolean from `object`, or `null` if `object` is null.
+ * @note This is distinct from `asBooleanOrFalse` in that it doesn't default to false,
+ * and it tries to convert string boolean values into actual boolean types
+ */
+export function asBoolean(
+    object: JSONValue,
+    path?: ObjectPath,
+    policy: ValidationPolicy = "coercible",
+): boolean | null {
+    const target = traverse(object, path, null);
+
+    // Value was null
+    if (isNull(target)) {
+        return null;
+    }
+
+    // Value was boolean.
+    if (typeof target === "boolean") {
+        return target;
+    }
+
+    // Value was string.
+    if (typeof target === "string") {
+        if (target === "true") {
+            return true;
+        } else if (target === "false") {
+            return false;
+        }
+    }
+
+    // Else coerce.
+    const coercedValue = Boolean(target);
+    switch (policy) {
+        case "strict": {
+            validation.context("asBoolean", () => {
+                validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+            });
+            break;
+        }
+        case "coercible": {
+            if (isNull(coercedValue)) {
+                validation.context("asBoolean", () => {
+                    validation.unexpectedType("coercedValue", "number", target, objectPathToString(path));
+                });
+                return null;
+            }
+            break;
+        }
+        case "none":
+        default: {
+            break;
+        }
+    }
+
+    return coercedValue;
+}
+
+/**
+ * Attempts to coerce the passed value to a JSONValue
+ *
+ * Note: due to performance concerns this does not perform a deep inspection of Objects or Arrays.
+ *
+ * @param value The value to coerce
+ * @return A JSONValue or null if value is not a valid JSONValue type
+ */
+export function asJSONValue(value: unknown): JSONValue | null {
+    if (value === null || value === undefined) {
+        return null;
+    }
+    switch (typeof value) {
+        case "string":
+        case "number":
+        case "boolean":
+            return value as JSONValue;
+        case "object":
+            // Note: It's too expensive to actually validate this is an array of JSONValues at run time
+            if (Array.isArray(value)) {
+                return value as JSONValue;
+            }
+            // Note: It's too expensive to actually validate this is a dictionary of { string : JSONValue } at run time
+            return value as JSONValue;
+        default:
+            validation.context("asJSONValue", () => {
+                validation.unexpectedType("defaultValue", "JSONValue", typeof value);
+            });
+            return null;
+    }
+}
+
+/**
+ * Attempts to coerce the passed value to JSONData
+ *
+ * @param value The value to coerce
+ * @return A JSONData or null if the value is not a valid JSONData object
+ */
+export function asJSONData(value: unknown): JSONData | null {
+    if (value === null || value === undefined) {
+        return null;
+    }
+    if (value instanceof Object && !Array.isArray(value)) {
+        // Note: It's too expensive to actually validate this is a dictionary of { string : Type } at run time
+        return value as JSONData;
+    }
+    validation.context("asJSONValue", () => {
+        validation.unexpectedType("defaultValue", "object", typeof value);
+    });
+    return null;
+}
+
+// endregion

+ 469 - 0
node_modules/@apple-media-services/media-api/src/models/urls.ts

@@ -0,0 +1,469 @@
+/**
+ * Created by keithpk on 12/2/16.
+ */
+
+import { isNothing, Nothing, Opt } from "@jet/environment/types/optional";
+import { isDefinedNonNullNonEmpty, isNullOrEmpty } from "./server-data";
+
+export type Query = {
+    [key: string]: string | undefined;
+};
+
+export type URLComponent = "protocol" | "username" | "password" | "host" | "port" | "pathname" | "query" | "hash";
+
+const protocolRegex = /^([a-z][a-z0-9.+-]*:)(\/\/)?([\S\s]*)/i;
+const queryParamRegex = /([^=?&]+)=?([^&]*)/g;
+const componentOrder: URLComponent[] = ["hash", "query", "pathname", "host"];
+
+type URLSplitStyle = "prefix" | "suffix";
+
+type URLSplitResult = {
+    result?: string;
+    remainder: string;
+};
+
+function splitUrlComponent(input: string, marker: string, style: URLSplitStyle): URLSplitResult {
+    const index = input.indexOf(marker);
+    let result;
+    let remainder = input;
+    if (index !== -1) {
+        const prefix = input.slice(0, index);
+        const suffix = input.slice(index + marker.length, input.length);
+
+        if (style === "prefix") {
+            result = prefix;
+            remainder = suffix;
+        } else {
+            result = suffix;
+            remainder = prefix;
+        }
+    }
+
+    // log("Token: " + marker + " String: " + input, " Result: " + result + " Remainder: " + remainder)
+
+    return {
+        result: result,
+        remainder: remainder,
+    };
+}
+
+export class URL {
+    protocol?: Opt<string>;
+    username: string;
+    password: string;
+    host?: Opt<string>;
+    port: string;
+    pathname?: Opt<string>;
+    query?: Query = {};
+    hash?: string;
+
+    constructor(url?: string) {
+        if (isNullOrEmpty(url)) {
+            return;
+        }
+
+        // Split the protocol from the rest of the urls
+        let remainder = url;
+        const match = protocolRegex.exec(url);
+        if (match != null) {
+            // Pull out the protocol
+            let protocol = match[1];
+            if (protocol) {
+                protocol = protocol.split(":")[0];
+            }
+
+            this.protocol = protocol;
+
+            // Save the remainder
+            remainder = match[3];
+        }
+
+        // Then match each component in a specific order
+        let parse: URLSplitResult = { remainder: remainder, result: undefined };
+        for (const component of componentOrder) {
+            if (!parse.remainder) {
+                break;
+            }
+
+            switch (component) {
+                case "hash": {
+                    parse = splitUrlComponent(parse.remainder, "#", "suffix");
+                    this.hash = parse.result;
+                    break;
+                }
+                case "query": {
+                    parse = splitUrlComponent(parse.remainder, "?", "suffix");
+                    if (isDefinedNonNullNonEmpty(parse.result)) {
+                        this.query = URL.queryFromString(parse.result);
+                    }
+                    break;
+                }
+                case "pathname": {
+                    parse = splitUrlComponent(parse.remainder, "/", "suffix");
+
+                    if (isDefinedNonNullNonEmpty(parse.result)) {
+                        // Replace the initial /, since paths require it
+                        this.pathname = "/" + parse.result;
+                    }
+                    break;
+                }
+                case "host": {
+                    if (parse.remainder) {
+                        const authorityParse = splitUrlComponent(parse.remainder, "@", "prefix");
+                        const userInfo = authorityParse.result;
+                        const hostPort = authorityParse.remainder;
+                        if (isDefinedNonNullNonEmpty(userInfo)) {
+                            const userInfoSplit = userInfo.split(":");
+                            this.username = decodeURIComponent(userInfoSplit[0]);
+                            this.password = decodeURIComponent(userInfoSplit[1]);
+                        }
+
+                        if (hostPort) {
+                            const hostPortSplit = hostPort.split(":");
+                            this.host = hostPortSplit[0];
+                            this.port = hostPortSplit[1];
+                        }
+                    }
+                    break;
+                }
+                default: {
+                    throw new Error("Unhandled case!");
+                }
+            }
+        }
+    }
+
+    set(component: URLComponent, value: string | Query): URL {
+        if (isNullOrEmpty(value)) {
+            return this;
+        }
+
+        if (component === "query") {
+            if (typeof value === "string") {
+                value = URL.queryFromString(value);
+            }
+        }
+
+        switch (component) {
+            // Exhaustive match to make sure TS property minifiers and other
+            // transformer plugins do not break this code.
+            case "protocol":
+                this.protocol = value as string;
+                break;
+            case "username":
+                this.username = value as string;
+                break;
+            case "password":
+                this.password = value as string;
+                break;
+            case "port":
+                this.port = value as string;
+                break;
+            case "pathname":
+                this.pathname = value as string;
+                break;
+            case "query":
+                this.query = value as Query;
+                break;
+            case "hash":
+                this.hash = value as string;
+                break;
+            default:
+                // The fallback for component which is not a property of URL object.
+                this[component] = value as string;
+                break;
+        }
+        return this;
+    }
+
+    private get(component: URLComponent): string | Query | Nothing {
+        switch (component) {
+            // Exhaustive match to make sure TS property minifiers and other
+            // transformer plugins do not break this code.
+            case "protocol":
+                return this.protocol;
+            case "username":
+                return this.username;
+            case "password":
+                return this.password;
+            case "port":
+                return this.port;
+            case "pathname":
+                return this.pathname;
+            case "query":
+                return this.query;
+            case "hash":
+                return this.hash;
+            default:
+                // The fallback for component which is not a property of URL object.
+                return this[component];
+        }
+    }
+
+    append(component: URLComponent, value: string | Query): URL {
+        const existingValue = this.get(component);
+        let newValue;
+
+        if (component === "query") {
+            if (typeof value === "string") {
+                value = URL.queryFromString(value);
+            }
+
+            if (typeof existingValue === "string") {
+                newValue = { existingValue, ...value };
+            } else {
+                newValue = { ...existingValue, ...value };
+            }
+        } else {
+            let existingValueString = existingValue as string;
+
+            if (!existingValueString) {
+                existingValueString = "";
+            }
+
+            let newValueString = existingValueString;
+
+            if (component === "pathname") {
+                const pathLength = existingValueString.length;
+                if (!pathLength || existingValueString[pathLength - 1] !== "/") {
+                    newValueString += "/";
+                }
+            }
+
+            // eslint-disable-next-line @typescript-eslint/restrict-plus-operands, @typescript-eslint/no-base-to-string
+            newValueString += value;
+            newValue = newValueString;
+        }
+
+        return this.set(component, newValue);
+    }
+
+    param(key: string, value?: string): URL {
+        if (!key) {
+            return this;
+        }
+        if (this.query == null) {
+            this.query = {};
+        }
+        this.query[key] = value;
+        return this;
+    }
+
+    removeParam(key: string): URL {
+        if (!key || this.query == null) {
+            return this;
+        }
+        if (this.query[key] !== undefined) {
+            delete this.query[key];
+        }
+        return this;
+    }
+
+    /**
+     * Push a new string value onto the path for this url
+     * @returns URL this object with the updated path.
+     */
+    path(value: string): URL {
+        return this.append("pathname", value);
+    }
+
+    pathExtension(): Opt<string> {
+        // Extract path extension if one exists
+        if (isNothing(this.pathname)) {
+            return null;
+        }
+
+        const lastFilenameComponents = this.pathname
+            .split("/")
+            .filter((item) => item.length > 0) // Remove any double or trailing slashes
+            .pop()
+            ?.split(".");
+        if (lastFilenameComponents === undefined) {
+            return null;
+        }
+        if (
+            lastFilenameComponents.filter((part) => {
+                return part !== "";
+            }).length < 2 // Remove any empty parts (e.g. .ssh_config -> ["ssh_config"])
+        ) {
+            return null;
+        }
+
+        return lastFilenameComponents.pop();
+    }
+
+    /**
+     * Returns the path components of the URL
+     * @returns An array of non-empty path components from `urls`.
+     */
+    pathComponents(): string[] {
+        if (isNullOrEmpty(this.pathname)) {
+            return [];
+        }
+
+        return this.pathname.split("/").filter((component) => component.length > 0);
+    }
+
+    /**
+     * Returns the last path component from this url, updating the url to not include this path component
+     * @returns String the last path component from this url.
+     */
+    popPathComponent(): string | null {
+        if (isNullOrEmpty(this.pathname)) {
+            return null;
+        }
+
+        const lastPathComponent = this.pathname.slice(this.pathname.lastIndexOf("/") + 1);
+
+        if (lastPathComponent.length === 0) {
+            return null;
+        }
+
+        this.pathname = this.pathname.slice(0, this.pathname.lastIndexOf("/"));
+
+        return lastPathComponent;
+    }
+
+    /**
+     * Same as toString
+     *
+     * @returns {string} A string representation of the URL
+     */
+    build(): string {
+        return this.toString();
+    }
+
+    /**
+     * Converts the URL to a string
+     *
+     * @returns {string} A string representation of the URL
+     */
+    toString(): string {
+        let url = "";
+
+        if (isDefinedNonNullNonEmpty(this.protocol)) {
+            url += this.protocol + "://";
+        }
+
+        if (this.username) {
+            url += encodeURIComponent(this.username);
+
+            if (this.password) {
+                url += ":" + encodeURIComponent(this.password);
+            }
+
+            url += "@";
+        }
+
+        if (isDefinedNonNullNonEmpty(this.host)) {
+            url += this.host;
+
+            if (this.port) {
+                url += ":" + this.port;
+            }
+        }
+
+        if (isDefinedNonNullNonEmpty(this.pathname)) {
+            url += this.pathname;
+            /// Trim off trailing path separators when we have a valid path
+            /// We don't do this unless pathname has elements otherwise we will trim the `://`
+            if (url.endsWith("/") && this.pathname.length > 0) {
+                url = url.slice(0, -1);
+            }
+        }
+
+        if (this.query != null && Object.keys(this.query).length > 0) {
+            url += "?" + URL.toQueryString(this.query);
+        }
+
+        if (isDefinedNonNullNonEmpty(this.hash)) {
+            url += "#" + this.hash;
+        }
+
+        return url;
+    }
+
+    // ----------------
+    // Static API
+    // ----------------
+
+    /**
+     * Converts a string into a query dictionary
+     * @param query The string to parse
+     * @returns The query dictionary containing the key-value pairs in the query string
+     */
+    static queryFromString(query: string): Query {
+        const result = {};
+
+        let parseResult = queryParamRegex.exec(query);
+        while (parseResult != null) {
+            const key = decodeURIComponent(parseResult[1]);
+            const value = decodeURIComponent(parseResult[2]);
+            result[key] = value;
+            parseResult = queryParamRegex.exec(query);
+        }
+
+        return result;
+    }
+
+    /**
+     * Converts a query dictionary into a query string
+     *
+     * @param query The query dictionary
+     * @returns {string} The string representation of the query dictionary
+     */
+    static toQueryString(query: Query) {
+        let queryString = "";
+
+        let first = true;
+        for (const key of Object.keys(query)) {
+            if (!first) {
+                queryString += "&";
+            }
+            first = false;
+
+            queryString += encodeURIComponent(key);
+
+            const value = query[key];
+            if (isDefinedNonNullNonEmpty(value) && value.length) {
+                queryString += "=" + encodeURIComponent(value);
+            }
+        }
+
+        return queryString;
+    }
+
+    /**
+     * Convenience method to instantiate a URL from a string
+     * @param url The URL string to parse
+     * @returns {URL} The new URL object representing the URL
+     */
+    static from(url: string): URL {
+        return new URL(url);
+    }
+
+    /**
+     * Convenience method to instantiate a URL from numerous (optional) components
+     * @param protocol The protocol type
+     * @param host The host name
+     * @param path The path
+     * @param query The query
+     * @param hash The hash
+     * @returns {URL} The new URL object representing the URL
+     */
+    static fromComponents(
+        protocol?: Opt<string>,
+        host?: Opt<string>,
+        path?: Opt<string>,
+        query?: Query,
+        hash?: string,
+    ): URL {
+        const url = new URL();
+        url.protocol = protocol;
+        url.host = host;
+        url.pathname = path;
+        url.query = query;
+        url.hash = hash;
+        return url;
+    }
+}

+ 403 - 0
node_modules/@apple-media-services/media-api/src/network.ts

@@ -0,0 +1,403 @@
+/**
+ * Created by ls on 9/7/2018.
+ *
+ * This `network.ts` is the NON-MEDIA API arm of network fetch requests.
+ * It is built on `Network` object and provides standard functionality, such as:
+ *     1. Parsing the body into specific format.
+ *     2. Adding timing metrics onto blob.
+ *
+ * This should *only* be used for objects that should have timing metrics, i.e. requests to Non-MediaAPI endpoints
+ * that will ultimately render some whole page. Otherwise, use `objectGraph.network.fetch` directly.
+ *
+ * @see `src/media/network.ts` for fetching from Media API endpoints
+ */
+
+import { FetchRequest, FetchResponse, HTTPTimingMetrics } from "@jet/environment/types/globals/net";
+import { FetchTimingMetrics, MetricsFields } from "@jet/environment/types/metrics";
+import { FetchTimingMetricsBuilder } from "@jet/environment/metrics";
+import { isSome, Opt } from "@jet/environment/types/optional";
+import * as serverData from "./models/server-data";
+import { ParsedNetworkResponse } from "./models/data-structure";
+import { Request } from "./models/request";
+import * as urls from "./models/urls";
+import * as urlBuilder from "./url-builder";
+import { MediaConfigurationType, MediaTokenService } from "./models/mediapi-configuration";
+import { HTTPMethod, HTTPCachePolicy, HTTPSigningStyle, HTTPHeaders } from "@jet/environment";
+
+/** @public */
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace ResponseMetadata {
+    export const requestedUrl = "_jet-internal:metricsHelpers_requestedUrl";
+
+    /**
+     * Symbol used to place timing metrics values onto fetch responses
+     * without interfering with the data returned by the server.
+     */
+    export const timingValues = "_jet-internal:metricsHelpers_timingValues";
+
+    /**
+     * Key used to access the page information gathered from a response's headers
+     */
+    export const pageInformation = "_jet-internal:metricsHelpers_pageInformation";
+
+    /**
+     * Key used to access the content max-age gathered from a response's headers.
+     */
+    export const contentMaxAge = "_jet-internal:responseMetadata_contentMaxAge";
+}
+
+/**
+ * Module's private fetch implementation built off `net` global.
+ *
+ * @param {FetchRequest} request describes fetch request.
+ * @param {(value: string) => Type} parser Some function parsing response body `string` into specific type.
+ * @returns {Promise<Type>} Promise resolving to specific object.
+ * @throws {Error} Throws error if status code of request is not 200.
+ *
+ * @note Similar to `fetchWithToken` in `media` module, but excludes media token specific functionality.
+ * Top level data fetches to endpoints that don't do redirects, and can benefit from metrics should
+ * call methods that build off of this instead of calling `objectGraph.network.fetch(...)` directly.
+ */
+export async function fetch<Type>(
+    configuration: MediaConfigurationType,
+    request: FetchRequest,
+    parser: (value: Opt<string>) => Type,
+): Promise<Type & ParsedNetworkResponse> {
+    const response = await configuration.network.fetch(request);
+    if (!response.ok) {
+        throw Error(`Bad Status code ${response.status} for ${request.url}`);
+    }
+    const parseStartTime = Date.now();
+    const result = parser(response.body) as Type & ParsedNetworkResponse;
+    const parseEndTime = Date.now();
+
+    // Build full network timing metrics.
+    const completeTimingMetrics = networkTimingMetricsWithParseTime(response.metrics, parseStartTime, parseEndTime);
+    if (serverData.isDefinedNonNull(completeTimingMetrics)) {
+        result[ResponseMetadata.timingValues] = completeTimingMetrics;
+    }
+    result[ResponseMetadata.requestedUrl] = request.url.toString();
+    return result;
+}
+
+/**
+ * Fetch from an endpoint with JSON response body.
+ *
+ * @param {FetchRequest} request to fetch from endpoint with JSON response..
+ * @returns {Promise<Type>} Promise resolving to body of response parsed as `Type`.
+ * @throws {Error} Throws error if status code of request is not 200.
+ */
+export async function fetchJSON<Type>(configuration: MediaConfigurationType, request: FetchRequest): Promise<Type> {
+    return await fetch(configuration, request, (body) => {
+        if (isSome(body)) {
+            return JSON.parse(body) as Type;
+        } else {
+            // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+            return {} as Type;
+        }
+    });
+}
+
+/**
+ * Fetch from an endpoint with XML response body.
+ *
+ * @param {FetchRequest} request to fetch from endpoint with XML response.
+ * @returns {Promise<Type>} Promise resolving to body of response parsed as `Type`.
+ * @throws {Error} Throws error if status code of request is not 200.
+ */
+export async function fetchPlist<Type>(configuration: MediaConfigurationType, request: FetchRequest): Promise<Type> {
+    return await fetch(configuration, request, (body) => {
+        if (isSome(body)) {
+            return configuration.plist.parse(body) as Type;
+        } else {
+            throw new Error(`Could not fetch Plist, response body was not defined for ${request.url}`);
+        }
+    });
+}
+
+/**
+ * With network requests now being created and parsed in JS, different timing metrics are measured in both Native and JS.
+ * This function populates the missing values from `HTTPTimingMetrics`'s native counterpart, `JSNetworkPerformanceMetrics`.
+ *
+ * @param {HTTPTimingMetrics[] | null} responseMetrics Array of response metrics provided by native.
+ * @param {number} parseStartTime Time at which response body string parse began in JS.
+ * @param {number} parseEndTime Time at which response body string parse ended in JS.
+ * @returns {HTTPTimingMetrics | null} Fully populated timing metrics, or `null` if native response provided no metrics events to build off of.
+ */
+function networkTimingMetricsWithParseTime(
+    responseMetrics: HTTPTimingMetrics[] | null,
+    parseStartTime: number,
+    parseEndTime: number,
+): FetchTimingMetrics | null {
+    // No metrics events to build from.
+    if (serverData.isNull(responseMetrics) || responseMetrics.length === 0) {
+        return null;
+    }
+
+    // Append parse times to first partial timing metrics from native.
+    const firstPartialTimingMetrics: FetchTimingMetrics = {
+        ...responseMetrics[0],
+        parseStartTime: parseStartTime,
+        parseEndTime: parseEndTime,
+    };
+    // Timing metrics with all properties populated.
+    return firstPartialTimingMetrics;
+}
+
+export type FetchOptions = {
+    headers?: { [key: string]: string };
+    method?: "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE" | "PATCH";
+    requestBodyString?: string;
+    timeout?: number; // in seconds. Check for feature 'supportsRequestTimeoutOption'.
+    /// When true the fetch wont throw if we dont get any data back for given request.
+    allowEmptyDataResponse?: boolean;
+    excludeIdentifierHeadersForAccount?: boolean; // Defaults to false
+    alwaysIncludeAuthKitHeaders?: boolean; // Defaults to true
+    alwaysIncludeMMeClientInfoAndDeviceHeaders?: boolean; // Defaults to true
+};
+
+/**
+ * Implements the MAPI fetch, building URL from MAPI Request and opaquely managing initial token request and refreshes.
+ *
+ * @param {MediaConfigurationType} configuration Base media API configuration.
+ * @param {Request} request MAPI Request to fetch with.
+ * @param {FetchOptions} [options] FetchOptions for the MAPI request.
+ * @returns {Promise<Type>} Promise resolving to some type for given MAPI request.
+ */
+export async function fetchData<Type>(
+    configuration: MediaConfigurationType,
+    mediaToken: MediaTokenService,
+    request: Request,
+    options?: FetchOptions,
+): Promise<Type & ParsedNetworkResponse> {
+    const url = urlBuilder.buildURLFromRequest(configuration, request).toString();
+    const startTime = Date.now();
+    const token = await mediaToken.refreshToken();
+    const response = await fetchWithToken<Type>(
+        configuration,
+        mediaToken,
+        url,
+        token,
+        options,
+        false,
+        configuration.fetchTimingMetricsBuilder,
+    );
+    const endTime = Date.now();
+    if (request.canonicalUrl) {
+        response[ResponseMetadata.requestedUrl] = request.canonicalUrl;
+    }
+    const roundTripTimeIncludingWaiting = endTime - startTime;
+    if (roundTripTimeIncludingWaiting > 500) {
+        console.warn("Fetch took too long (" + roundTripTimeIncludingWaiting.toString() + "ms) " + url);
+    }
+    return response;
+}
+
+export function redirectParametersInUrl(configuration: MediaConfigurationType, url: urls.URL): string[] {
+    const redirectURLParams = configuration.redirectUrlWhitelistedQueryParams;
+    return redirectURLParams.filter((param) => serverData.isDefinedNonNull(url.query?.[param]));
+}
+
+export type MediaAPIFetchRequest = {
+    url: string;
+    excludeIdentifierHeadersForAccount?: boolean;
+    alwaysIncludeAuthKitHeaders?: boolean;
+    alwaysIncludeMMeClientInfoAndDeviceHeaders?: boolean;
+    method?: Opt<HTTPMethod>;
+    cache?: Opt<HTTPCachePolicy>;
+    signingStyle?: Opt<HTTPSigningStyle>;
+    headers?: Opt<HTTPHeaders>;
+    timeout?: Opt<number>;
+    body?: Opt<string>;
+};
+
+/**
+ * Given a built URL, token, and options, calls into native networking APIs to fetch content.
+ *
+ * @param {string} url URL to fetch data from.
+ * @param {string} token MAPI token key.
+ * @param {FetchOptions} options Fetch options for MAPI requests.
+ * @param {boolean} isRetry flag indicating whether this is a fetch retry following a 401 request, and media token was refreshed.
+ * @returns {Promise<Type>} Promise resolving to some type for given MAPI request.
+ */
+async function fetchWithToken<Type>(
+    configuration: MediaConfigurationType,
+    mediaToken: MediaTokenService,
+    url: string,
+    token: string,
+    options: FetchOptions = {},
+    isRetry = false,
+    fetchTimingMetricsBuilder: Opt<FetchTimingMetricsBuilder>,
+): Promise<Type & ParsedNetworkResponse> {
+    // Removes all affiliate/redirect params for caching (https://connectme.apple.com/docs/DOC-577671)
+    const filteredURL = new urls.URL(url);
+    const redirectParameters = redirectParametersInUrl(configuration, filteredURL);
+    for (const param of redirectParameters) {
+        filteredURL.removeParam(param);
+    }
+    const filteredUrlString = filteredURL.toString();
+
+    let headers = options.headers;
+    if (headers == null) {
+        headers = {};
+    }
+    headers["Authorization"] = "Bearer " + token;
+
+    const fetchRequest: MediaAPIFetchRequest = {
+        url: filteredUrlString,
+        excludeIdentifierHeadersForAccount: options.excludeIdentifierHeadersForAccount ?? false,
+        alwaysIncludeAuthKitHeaders: options.alwaysIncludeAuthKitHeaders ?? true,
+        alwaysIncludeMMeClientInfoAndDeviceHeaders: options.alwaysIncludeMMeClientInfoAndDeviceHeaders ?? true,
+        headers: headers,
+        method: options.method,
+        body: options.requestBodyString,
+        timeout: options.timeout,
+    };
+
+    const response = await configuration.network.fetch(fetchRequest);
+
+    try {
+        if (response.status === 401 || response.status === 403) {
+            if (isRetry) {
+                throw Error("We refreshed the token but we still get 401 from the API");
+            }
+            mediaToken.resetToken();
+            return await mediaToken.refreshToken().then(async (newToken) => {
+                // Explicitly re-fetch with the original request so logging and metrics are correct
+                return await fetchWithToken<Type>(
+                    configuration,
+                    mediaToken,
+                    url,
+                    newToken,
+                    options,
+                    true,
+                    fetchTimingMetricsBuilder,
+                );
+            });
+        } else if (response.status === 404) {
+            // item is not available in this storefront or perhaps not at all
+            throw noContentError();
+        } else if (!response.ok) {
+            const correlationKey = response.headers["x-apple-jingle-correlation-key"] ?? "N/A";
+            const error = new NetworkError(
+                `Bad Status code ${response.status} (correlationKey: ${correlationKey}) for ${filteredUrlString}, original ${url}`,
+            );
+            error.statusCode = response.status;
+            throw error;
+        }
+
+        const parser = (resp: FetchResponse) => {
+            const parseStartTime = Date.now();
+            let result: Type & ParsedNetworkResponse;
+            if (serverData.isNull(resp.body) || resp.body === "") {
+                if (resp.status === 204) {
+                    // 204 indicates a success, but the response will typically be empty
+                    // Create a fake result so that we don't throw an error when JSON parsing
+                    const emptyData: ParsedNetworkResponse = {};
+                    result = emptyData as Type & ParsedNetworkResponse;
+                } else {
+                    throw noContentError();
+                }
+            } else {
+                result = JSON.parse(resp.body) as Type & ParsedNetworkResponse;
+            }
+            const parseEndTime = Date.now();
+
+            result[ResponseMetadata.pageInformation] = serverData.asJSONData(
+                getPageInformationFromResponse(configuration, resp),
+            );
+            if (resp.metrics.length > 0) {
+                const metrics: FetchTimingMetrics = {
+                    ...resp.metrics[0],
+                    parseStartTime: parseStartTime,
+                    parseEndTime: parseEndTime,
+                };
+                result[ResponseMetadata.timingValues] = metrics;
+            } else {
+                const fallbackMetrics: FetchTimingMetrics = {
+                    pageURL: resp.url,
+                    parseStartTime,
+                    parseEndTime,
+                };
+                result[ResponseMetadata.timingValues] = fallbackMetrics;
+            }
+            result[ResponseMetadata.contentMaxAge] = getContentTimeToLiveFromResponse(resp);
+
+            // If we have an empty data object, throw a 204 (No Content).
+            if (
+                Array.isArray(result.data) &&
+                serverData.isArrayDefinedNonNullAndEmpty(result.data) &&
+                !serverData.asBooleanOrFalse(options.allowEmptyDataResponse)
+            ) {
+                throw noContentError();
+            }
+
+            result[ResponseMetadata.requestedUrl] = url;
+            return result;
+        };
+        if (isSome(fetchTimingMetricsBuilder)) {
+            return fetchTimingMetricsBuilder.measureParsing(response, parser);
+        } else {
+            return parser(response);
+        }
+    } catch (e) {
+        if (e instanceof NetworkError) {
+            throw e;
+        }
+        throw new Error(`Error Fetching - filtered: ${filteredUrlString}, original: ${url}, ${e.name}, ${e.message}`);
+    }
+}
+
+export class NetworkError extends Error {
+    statusCode?: number;
+}
+
+function noContentError(): NetworkError {
+    const error = new NetworkError(`No content`);
+    error.statusCode = 204;
+    return error;
+}
+
+const serverInstanceHeader = "x-apple-application-instance";
+
+const environmentDataCenterHeader = "x-apple-application-site";
+
+function getPageInformationFromResponse(
+    configuration: MediaConfigurationType,
+    response: FetchResponse,
+): MetricsFields | null {
+    const storeFrontHeader: string = configuration.storefrontIdentifier;
+
+    let storeFront: Opt<string> = null;
+    if (serverData.isDefinedNonNullNonEmpty(storeFrontHeader)) {
+        const storeFrontHeaderComponents: string[] = storeFrontHeader.split("-");
+        if (serverData.isDefinedNonNullNonEmpty(storeFrontHeaderComponents)) {
+            storeFront = storeFrontHeaderComponents[0];
+        }
+    }
+
+    return {
+        serverInstance: response.headers[serverInstanceHeader],
+        storeFrontHeader: storeFrontHeader,
+        language: configuration.bagLanguage,
+        storeFront: storeFront,
+        environmentDataCenter: response.headers[environmentDataCenterHeader],
+    };
+}
+
+function getContentTimeToLiveFromResponse(response: FetchResponse): Opt<number> {
+    const cacheControlHeaderKey = Object.keys(response.headers).find((key) => key.toLowerCase() === "cache-control");
+    if (serverData.isNull(cacheControlHeaderKey) || cacheControlHeaderKey === "") {
+        return null;
+    }
+
+    const headerValue = response.headers[cacheControlHeaderKey];
+    if (serverData.isNullOrEmpty(headerValue)) {
+        return null;
+    }
+    const matches = headerValue.match(/max-age=(\d+)/);
+    if (serverData.isNull(matches) || matches.length < 2) {
+        return null;
+    }
+    return serverData.asNumber(matches[1]);
+}

+ 1046 - 0
node_modules/@floating-ui/core/dist/floating-ui.core.mjs

@@ -0,0 +1,1046 @@
+import { getSideAxis, getAlignmentAxis, getAxisLength, getSide, getAlignment, evaluate, getPaddingObject, rectToClientRect, min, clamp, placements, getAlignmentSides, getOppositeAlignmentPlacement, getOppositePlacement, getExpandedPlacements, getOppositeAxisPlacements, sides, max, getOppositeAxis } from '@floating-ui/utils';
+export { rectToClientRect } from '@floating-ui/utils';
+
+function computeCoordsFromPlacement(_ref, placement, rtl) {
+  let {
+    reference,
+    floating
+  } = _ref;
+  const sideAxis = getSideAxis(placement);
+  const alignmentAxis = getAlignmentAxis(placement);
+  const alignLength = getAxisLength(alignmentAxis);
+  const side = getSide(placement);
+  const isVertical = sideAxis === 'y';
+  const commonX = reference.x + reference.width / 2 - floating.width / 2;
+  const commonY = reference.y + reference.height / 2 - floating.height / 2;
+  const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
+  let coords;
+  switch (side) {
+    case 'top':
+      coords = {
+        x: commonX,
+        y: reference.y - floating.height
+      };
+      break;
+    case 'bottom':
+      coords = {
+        x: commonX,
+        y: reference.y + reference.height
+      };
+      break;
+    case 'right':
+      coords = {
+        x: reference.x + reference.width,
+        y: commonY
+      };
+      break;
+    case 'left':
+      coords = {
+        x: reference.x - floating.width,
+        y: commonY
+      };
+      break;
+    default:
+      coords = {
+        x: reference.x,
+        y: reference.y
+      };
+  }
+  switch (getAlignment(placement)) {
+    case 'start':
+      coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
+      break;
+    case 'end':
+      coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
+      break;
+  }
+  return coords;
+}
+
+/**
+ * Computes the `x` and `y` coordinates that will place the floating element
+ * next to a given reference element.
+ *
+ * This export does not have any `platform` interface logic. You will need to
+ * write one for the platform you are using Floating UI with.
+ */
+const computePosition = async (reference, floating, config) => {
+  const {
+    placement = 'bottom',
+    strategy = 'absolute',
+    middleware = [],
+    platform
+  } = config;
+  const validMiddleware = middleware.filter(Boolean);
+  const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
+  let rects = await platform.getElementRects({
+    reference,
+    floating,
+    strategy
+  });
+  let {
+    x,
+    y
+  } = computeCoordsFromPlacement(rects, placement, rtl);
+  let statefulPlacement = placement;
+  let middlewareData = {};
+  let resetCount = 0;
+  for (let i = 0; i < validMiddleware.length; i++) {
+    const {
+      name,
+      fn
+    } = validMiddleware[i];
+    const {
+      x: nextX,
+      y: nextY,
+      data,
+      reset
+    } = await fn({
+      x,
+      y,
+      initialPlacement: placement,
+      placement: statefulPlacement,
+      strategy,
+      middlewareData,
+      rects,
+      platform,
+      elements: {
+        reference,
+        floating
+      }
+    });
+    x = nextX != null ? nextX : x;
+    y = nextY != null ? nextY : y;
+    middlewareData = {
+      ...middlewareData,
+      [name]: {
+        ...middlewareData[name],
+        ...data
+      }
+    };
+    if (reset && resetCount <= 50) {
+      resetCount++;
+      if (typeof reset === 'object') {
+        if (reset.placement) {
+          statefulPlacement = reset.placement;
+        }
+        if (reset.rects) {
+          rects = reset.rects === true ? await platform.getElementRects({
+            reference,
+            floating,
+            strategy
+          }) : reset.rects;
+        }
+        ({
+          x,
+          y
+        } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
+      }
+      i = -1;
+    }
+  }
+  return {
+    x,
+    y,
+    placement: statefulPlacement,
+    strategy,
+    middlewareData
+  };
+};
+
+/**
+ * Resolves with an object of overflow side offsets that determine how much the
+ * element is overflowing a given clipping boundary on each side.
+ * - positive = overflowing the boundary by that number of pixels
+ * - negative = how many pixels left before it will overflow
+ * - 0 = lies flush with the boundary
+ * @see https://floating-ui.com/docs/detectOverflow
+ */
+async function detectOverflow(state, options) {
+  var _await$platform$isEle;
+  if (options === void 0) {
+    options = {};
+  }
+  const {
+    x,
+    y,
+    platform,
+    rects,
+    elements,
+    strategy
+  } = state;
+  const {
+    boundary = 'clippingAncestors',
+    rootBoundary = 'viewport',
+    elementContext = 'floating',
+    altBoundary = false,
+    padding = 0
+  } = evaluate(options, state);
+  const paddingObject = getPaddingObject(padding);
+  const altContext = elementContext === 'floating' ? 'reference' : 'floating';
+  const element = elements[altBoundary ? altContext : elementContext];
+  const clippingClientRect = rectToClientRect(await platform.getClippingRect({
+    element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
+    boundary,
+    rootBoundary,
+    strategy
+  }));
+  const rect = elementContext === 'floating' ? {
+    x,
+    y,
+    width: rects.floating.width,
+    height: rects.floating.height
+  } : rects.reference;
+  const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
+  const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
+    x: 1,
+    y: 1
+  } : {
+    x: 1,
+    y: 1
+  };
+  const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
+    elements,
+    rect,
+    offsetParent,
+    strategy
+  }) : rect);
+  return {
+    top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
+    bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
+    left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
+    right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
+  };
+}
+
+/**
+ * Provides data to position an inner element of the floating element so that it
+ * appears centered to the reference element.
+ * @see https://floating-ui.com/docs/arrow
+ */
+const arrow = options => ({
+  name: 'arrow',
+  options,
+  async fn(state) {
+    const {
+      x,
+      y,
+      placement,
+      rects,
+      platform,
+      elements,
+      middlewareData
+    } = state;
+    // Since `element` is required, we don't Partial<> the type.
+    const {
+      element,
+      padding = 0
+    } = evaluate(options, state) || {};
+    if (element == null) {
+      return {};
+    }
+    const paddingObject = getPaddingObject(padding);
+    const coords = {
+      x,
+      y
+    };
+    const axis = getAlignmentAxis(placement);
+    const length = getAxisLength(axis);
+    const arrowDimensions = await platform.getDimensions(element);
+    const isYAxis = axis === 'y';
+    const minProp = isYAxis ? 'top' : 'left';
+    const maxProp = isYAxis ? 'bottom' : 'right';
+    const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
+    const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
+    const startDiff = coords[axis] - rects.reference[axis];
+    const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));
+    let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
+
+    // DOM platform can return `window` as the `offsetParent`.
+    if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {
+      clientSize = elements.floating[clientProp] || rects.floating[length];
+    }
+    const centerToReference = endDiff / 2 - startDiff / 2;
+
+    // If the padding is large enough that it causes the arrow to no longer be
+    // centered, modify the padding so that it is centered.
+    const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
+    const minPadding = min(paddingObject[minProp], largestPossiblePadding);
+    const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);
+
+    // Make sure the arrow doesn't overflow the floating element if the center
+    // point is outside the floating element's bounds.
+    const min$1 = minPadding;
+    const max = clientSize - arrowDimensions[length] - maxPadding;
+    const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
+    const offset = clamp(min$1, center, max);
+
+    // If the reference is small enough that the arrow's padding causes it to
+    // to point to nothing for an aligned placement, adjust the offset of the
+    // floating element itself. To ensure `shift()` continues to take action,
+    // a single reset is performed when this is true.
+    const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
+    const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
+    return {
+      [axis]: coords[axis] + alignmentOffset,
+      data: {
+        [axis]: offset,
+        centerOffset: center - offset - alignmentOffset,
+        ...(shouldAddOffset && {
+          alignmentOffset
+        })
+      },
+      reset: shouldAddOffset
+    };
+  }
+});
+
+function getPlacementList(alignment, autoAlignment, allowedPlacements) {
+  const allowedPlacementsSortedByAlignment = alignment ? [...allowedPlacements.filter(placement => getAlignment(placement) === alignment), ...allowedPlacements.filter(placement => getAlignment(placement) !== alignment)] : allowedPlacements.filter(placement => getSide(placement) === placement);
+  return allowedPlacementsSortedByAlignment.filter(placement => {
+    if (alignment) {
+      return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false);
+    }
+    return true;
+  });
+}
+/**
+ * Optimizes the visibility of the floating element by choosing the placement
+ * that has the most space available automatically, without needing to specify a
+ * preferred placement. Alternative to `flip`.
+ * @see https://floating-ui.com/docs/autoPlacement
+ */
+const autoPlacement = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'autoPlacement',
+    options,
+    async fn(state) {
+      var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE;
+      const {
+        rects,
+        middlewareData,
+        placement,
+        platform,
+        elements
+      } = state;
+      const {
+        crossAxis = false,
+        alignment,
+        allowedPlacements = placements,
+        autoAlignment = true,
+        ...detectOverflowOptions
+      } = evaluate(options, state);
+      const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;
+      const overflow = await detectOverflow(state, detectOverflowOptions);
+      const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;
+      const currentPlacement = placements$1[currentIndex];
+      if (currentPlacement == null) {
+        return {};
+      }
+      const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));
+
+      // Make `computeCoords` start from the right place.
+      if (placement !== currentPlacement) {
+        return {
+          reset: {
+            placement: placements$1[0]
+          }
+        };
+      }
+      const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];
+      const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {
+        placement: currentPlacement,
+        overflows: currentOverflows
+      }];
+      const nextPlacement = placements$1[currentIndex + 1];
+
+      // There are more placements to check.
+      if (nextPlacement) {
+        return {
+          data: {
+            index: currentIndex + 1,
+            overflows: allOverflows
+          },
+          reset: {
+            placement: nextPlacement
+          }
+        };
+      }
+      const placementsSortedByMostSpace = allOverflows.map(d => {
+        const alignment = getAlignment(d.placement);
+        return [d.placement, alignment && crossAxis ?
+        // Check along the mainAxis and main crossAxis side.
+        d.overflows.slice(0, 2).reduce((acc, v) => acc + v, 0) :
+        // Check only the mainAxis.
+        d.overflows[0], d.overflows];
+      }).sort((a, b) => a[1] - b[1]);
+      const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter(d => d[2].slice(0,
+      // Aligned placements should not check their opposite crossAxis
+      // side.
+      getAlignment(d[0]) ? 2 : 3).every(v => v <= 0));
+      const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0];
+      if (resetPlacement !== placement) {
+        return {
+          data: {
+            index: currentIndex + 1,
+            overflows: allOverflows
+          },
+          reset: {
+            placement: resetPlacement
+          }
+        };
+      }
+      return {};
+    }
+  };
+};
+
+/**
+ * Optimizes the visibility of the floating element by flipping the `placement`
+ * in order to keep it in view when the preferred placement(s) will overflow the
+ * clipping boundary. Alternative to `autoPlacement`.
+ * @see https://floating-ui.com/docs/flip
+ */
+const flip = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'flip',
+    options,
+    async fn(state) {
+      var _middlewareData$arrow, _middlewareData$flip;
+      const {
+        placement,
+        middlewareData,
+        rects,
+        initialPlacement,
+        platform,
+        elements
+      } = state;
+      const {
+        mainAxis: checkMainAxis = true,
+        crossAxis: checkCrossAxis = true,
+        fallbackPlacements: specifiedFallbackPlacements,
+        fallbackStrategy = 'bestFit',
+        fallbackAxisSideDirection = 'none',
+        flipAlignment = true,
+        ...detectOverflowOptions
+      } = evaluate(options, state);
+
+      // If a reset by the arrow was caused due to an alignment offset being
+      // added, we should skip any logic now since `flip()` has already done its
+      // work.
+      // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
+      if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
+        return {};
+      }
+      const side = getSide(placement);
+      const initialSideAxis = getSideAxis(initialPlacement);
+      const isBasePlacement = getSide(initialPlacement) === initialPlacement;
+      const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
+      const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
+      const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';
+      if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
+        fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
+      }
+      const placements = [initialPlacement, ...fallbackPlacements];
+      const overflow = await detectOverflow(state, detectOverflowOptions);
+      const overflows = [];
+      let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
+      if (checkMainAxis) {
+        overflows.push(overflow[side]);
+      }
+      if (checkCrossAxis) {
+        const sides = getAlignmentSides(placement, rects, rtl);
+        overflows.push(overflow[sides[0]], overflow[sides[1]]);
+      }
+      overflowsData = [...overflowsData, {
+        placement,
+        overflows
+      }];
+
+      // One or more sides is overflowing.
+      if (!overflows.every(side => side <= 0)) {
+        var _middlewareData$flip2, _overflowsData$filter;
+        const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
+        const nextPlacement = placements[nextIndex];
+        if (nextPlacement) {
+          var _overflowsData$;
+          const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;
+          const hasInitialMainAxisOverflow = ((_overflowsData$ = overflowsData[0]) == null ? void 0 : _overflowsData$.overflows[0]) > 0;
+          if (!ignoreCrossAxisOverflow || hasInitialMainAxisOverflow) {
+            // Try next placement and re-run the lifecycle.
+            return {
+              data: {
+                index: nextIndex,
+                overflows: overflowsData
+              },
+              reset: {
+                placement: nextPlacement
+              }
+            };
+          }
+        }
+
+        // First, find the candidates that fit on the mainAxis side of overflow,
+        // then find the placement that fits the best on the main crossAxis side.
+        let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
+
+        // Otherwise fallback.
+        if (!resetPlacement) {
+          switch (fallbackStrategy) {
+            case 'bestFit':
+              {
+                var _overflowsData$filter2;
+                const placement = (_overflowsData$filter2 = overflowsData.filter(d => {
+                  if (hasFallbackAxisSideDirection) {
+                    const currentSideAxis = getSideAxis(d.placement);
+                    return currentSideAxis === initialSideAxis ||
+                    // Create a bias to the `y` side axis due to horizontal
+                    // reading directions favoring greater width.
+                    currentSideAxis === 'y';
+                  }
+                  return true;
+                }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
+                if (placement) {
+                  resetPlacement = placement;
+                }
+                break;
+              }
+            case 'initialPlacement':
+              resetPlacement = initialPlacement;
+              break;
+          }
+        }
+        if (placement !== resetPlacement) {
+          return {
+            reset: {
+              placement: resetPlacement
+            }
+          };
+        }
+      }
+      return {};
+    }
+  };
+};
+
+function getSideOffsets(overflow, rect) {
+  return {
+    top: overflow.top - rect.height,
+    right: overflow.right - rect.width,
+    bottom: overflow.bottom - rect.height,
+    left: overflow.left - rect.width
+  };
+}
+function isAnySideFullyClipped(overflow) {
+  return sides.some(side => overflow[side] >= 0);
+}
+/**
+ * Provides data to hide the floating element in applicable situations, such as
+ * when it is not in the same clipping context as the reference element.
+ * @see https://floating-ui.com/docs/hide
+ */
+const hide = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'hide',
+    options,
+    async fn(state) {
+      const {
+        rects
+      } = state;
+      const {
+        strategy = 'referenceHidden',
+        ...detectOverflowOptions
+      } = evaluate(options, state);
+      switch (strategy) {
+        case 'referenceHidden':
+          {
+            const overflow = await detectOverflow(state, {
+              ...detectOverflowOptions,
+              elementContext: 'reference'
+            });
+            const offsets = getSideOffsets(overflow, rects.reference);
+            return {
+              data: {
+                referenceHiddenOffsets: offsets,
+                referenceHidden: isAnySideFullyClipped(offsets)
+              }
+            };
+          }
+        case 'escaped':
+          {
+            const overflow = await detectOverflow(state, {
+              ...detectOverflowOptions,
+              altBoundary: true
+            });
+            const offsets = getSideOffsets(overflow, rects.floating);
+            return {
+              data: {
+                escapedOffsets: offsets,
+                escaped: isAnySideFullyClipped(offsets)
+              }
+            };
+          }
+        default:
+          {
+            return {};
+          }
+      }
+    }
+  };
+};
+
+function getBoundingRect(rects) {
+  const minX = min(...rects.map(rect => rect.left));
+  const minY = min(...rects.map(rect => rect.top));
+  const maxX = max(...rects.map(rect => rect.right));
+  const maxY = max(...rects.map(rect => rect.bottom));
+  return {
+    x: minX,
+    y: minY,
+    width: maxX - minX,
+    height: maxY - minY
+  };
+}
+function getRectsByLine(rects) {
+  const sortedRects = rects.slice().sort((a, b) => a.y - b.y);
+  const groups = [];
+  let prevRect = null;
+  for (let i = 0; i < sortedRects.length; i++) {
+    const rect = sortedRects[i];
+    if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) {
+      groups.push([rect]);
+    } else {
+      groups[groups.length - 1].push(rect);
+    }
+    prevRect = rect;
+  }
+  return groups.map(rect => rectToClientRect(getBoundingRect(rect)));
+}
+/**
+ * Provides improved positioning for inline reference elements that can span
+ * over multiple lines, such as hyperlinks or range selections.
+ * @see https://floating-ui.com/docs/inline
+ */
+const inline = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'inline',
+    options,
+    async fn(state) {
+      const {
+        placement,
+        elements,
+        rects,
+        platform,
+        strategy
+      } = state;
+      // A MouseEvent's client{X,Y} coords can be up to 2 pixels off a
+      // ClientRect's bounds, despite the event listener being triggered. A
+      // padding of 2 seems to handle this issue.
+      const {
+        padding = 2,
+        x,
+        y
+      } = evaluate(options, state);
+      const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);
+      const clientRects = getRectsByLine(nativeClientRects);
+      const fallback = rectToClientRect(getBoundingRect(nativeClientRects));
+      const paddingObject = getPaddingObject(padding);
+      function getBoundingClientRect() {
+        // There are two rects and they are disjoined.
+        if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {
+          // Find the first rect in which the point is fully inside.
+          return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;
+        }
+
+        // There are 2 or more connected rects.
+        if (clientRects.length >= 2) {
+          if (getSideAxis(placement) === 'y') {
+            const firstRect = clientRects[0];
+            const lastRect = clientRects[clientRects.length - 1];
+            const isTop = getSide(placement) === 'top';
+            const top = firstRect.top;
+            const bottom = lastRect.bottom;
+            const left = isTop ? firstRect.left : lastRect.left;
+            const right = isTop ? firstRect.right : lastRect.right;
+            const width = right - left;
+            const height = bottom - top;
+            return {
+              top,
+              bottom,
+              left,
+              right,
+              width,
+              height,
+              x: left,
+              y: top
+            };
+          }
+          const isLeftSide = getSide(placement) === 'left';
+          const maxRight = max(...clientRects.map(rect => rect.right));
+          const minLeft = min(...clientRects.map(rect => rect.left));
+          const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);
+          const top = measureRects[0].top;
+          const bottom = measureRects[measureRects.length - 1].bottom;
+          const left = minLeft;
+          const right = maxRight;
+          const width = right - left;
+          const height = bottom - top;
+          return {
+            top,
+            bottom,
+            left,
+            right,
+            width,
+            height,
+            x: left,
+            y: top
+          };
+        }
+        return fallback;
+      }
+      const resetRects = await platform.getElementRects({
+        reference: {
+          getBoundingClientRect
+        },
+        floating: elements.floating,
+        strategy
+      });
+      if (rects.reference.x !== resetRects.reference.x || rects.reference.y !== resetRects.reference.y || rects.reference.width !== resetRects.reference.width || rects.reference.height !== resetRects.reference.height) {
+        return {
+          reset: {
+            rects: resetRects
+          }
+        };
+      }
+      return {};
+    }
+  };
+};
+
+// For type backwards-compatibility, the `OffsetOptions` type was also
+// Derivable.
+
+async function convertValueToCoords(state, options) {
+  const {
+    placement,
+    platform,
+    elements
+  } = state;
+  const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
+  const side = getSide(placement);
+  const alignment = getAlignment(placement);
+  const isVertical = getSideAxis(placement) === 'y';
+  const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1;
+  const crossAxisMulti = rtl && isVertical ? -1 : 1;
+  const rawValue = evaluate(options, state);
+
+  // eslint-disable-next-line prefer-const
+  let {
+    mainAxis,
+    crossAxis,
+    alignmentAxis
+  } = typeof rawValue === 'number' ? {
+    mainAxis: rawValue,
+    crossAxis: 0,
+    alignmentAxis: null
+  } : {
+    mainAxis: rawValue.mainAxis || 0,
+    crossAxis: rawValue.crossAxis || 0,
+    alignmentAxis: rawValue.alignmentAxis
+  };
+  if (alignment && typeof alignmentAxis === 'number') {
+    crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
+  }
+  return isVertical ? {
+    x: crossAxis * crossAxisMulti,
+    y: mainAxis * mainAxisMulti
+  } : {
+    x: mainAxis * mainAxisMulti,
+    y: crossAxis * crossAxisMulti
+  };
+}
+
+/**
+ * Modifies the placement by translating the floating element along the
+ * specified axes.
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
+ * object may be passed.
+ * @see https://floating-ui.com/docs/offset
+ */
+const offset = function (options) {
+  if (options === void 0) {
+    options = 0;
+  }
+  return {
+    name: 'offset',
+    options,
+    async fn(state) {
+      var _middlewareData$offse, _middlewareData$arrow;
+      const {
+        x,
+        y,
+        placement,
+        middlewareData
+      } = state;
+      const diffCoords = await convertValueToCoords(state, options);
+
+      // If the placement is the same and the arrow caused an alignment offset
+      // then we don't need to change the positioning coordinates.
+      if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
+        return {};
+      }
+      return {
+        x: x + diffCoords.x,
+        y: y + diffCoords.y,
+        data: {
+          ...diffCoords,
+          placement
+        }
+      };
+    }
+  };
+};
+
+/**
+ * Optimizes the visibility of the floating element by shifting it in order to
+ * keep it in view when it will overflow the clipping boundary.
+ * @see https://floating-ui.com/docs/shift
+ */
+const shift = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'shift',
+    options,
+    async fn(state) {
+      const {
+        x,
+        y,
+        placement
+      } = state;
+      const {
+        mainAxis: checkMainAxis = true,
+        crossAxis: checkCrossAxis = false,
+        limiter = {
+          fn: _ref => {
+            let {
+              x,
+              y
+            } = _ref;
+            return {
+              x,
+              y
+            };
+          }
+        },
+        ...detectOverflowOptions
+      } = evaluate(options, state);
+      const coords = {
+        x,
+        y
+      };
+      const overflow = await detectOverflow(state, detectOverflowOptions);
+      const crossAxis = getSideAxis(getSide(placement));
+      const mainAxis = getOppositeAxis(crossAxis);
+      let mainAxisCoord = coords[mainAxis];
+      let crossAxisCoord = coords[crossAxis];
+      if (checkMainAxis) {
+        const minSide = mainAxis === 'y' ? 'top' : 'left';
+        const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
+        const min = mainAxisCoord + overflow[minSide];
+        const max = mainAxisCoord - overflow[maxSide];
+        mainAxisCoord = clamp(min, mainAxisCoord, max);
+      }
+      if (checkCrossAxis) {
+        const minSide = crossAxis === 'y' ? 'top' : 'left';
+        const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
+        const min = crossAxisCoord + overflow[minSide];
+        const max = crossAxisCoord - overflow[maxSide];
+        crossAxisCoord = clamp(min, crossAxisCoord, max);
+      }
+      const limitedCoords = limiter.fn({
+        ...state,
+        [mainAxis]: mainAxisCoord,
+        [crossAxis]: crossAxisCoord
+      });
+      return {
+        ...limitedCoords,
+        data: {
+          x: limitedCoords.x - x,
+          y: limitedCoords.y - y,
+          enabled: {
+            [mainAxis]: checkMainAxis,
+            [crossAxis]: checkCrossAxis
+          }
+        }
+      };
+    }
+  };
+};
+/**
+ * Built-in `limiter` that will stop `shift()` at a certain point.
+ */
+const limitShift = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    options,
+    fn(state) {
+      const {
+        x,
+        y,
+        placement,
+        rects,
+        middlewareData
+      } = state;
+      const {
+        offset = 0,
+        mainAxis: checkMainAxis = true,
+        crossAxis: checkCrossAxis = true
+      } = evaluate(options, state);
+      const coords = {
+        x,
+        y
+      };
+      const crossAxis = getSideAxis(placement);
+      const mainAxis = getOppositeAxis(crossAxis);
+      let mainAxisCoord = coords[mainAxis];
+      let crossAxisCoord = coords[crossAxis];
+      const rawOffset = evaluate(offset, state);
+      const computedOffset = typeof rawOffset === 'number' ? {
+        mainAxis: rawOffset,
+        crossAxis: 0
+      } : {
+        mainAxis: 0,
+        crossAxis: 0,
+        ...rawOffset
+      };
+      if (checkMainAxis) {
+        const len = mainAxis === 'y' ? 'height' : 'width';
+        const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;
+        const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;
+        if (mainAxisCoord < limitMin) {
+          mainAxisCoord = limitMin;
+        } else if (mainAxisCoord > limitMax) {
+          mainAxisCoord = limitMax;
+        }
+      }
+      if (checkCrossAxis) {
+        var _middlewareData$offse, _middlewareData$offse2;
+        const len = mainAxis === 'y' ? 'width' : 'height';
+        const isOriginSide = ['top', 'left'].includes(getSide(placement));
+        const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);
+        const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);
+        if (crossAxisCoord < limitMin) {
+          crossAxisCoord = limitMin;
+        } else if (crossAxisCoord > limitMax) {
+          crossAxisCoord = limitMax;
+        }
+      }
+      return {
+        [mainAxis]: mainAxisCoord,
+        [crossAxis]: crossAxisCoord
+      };
+    }
+  };
+};
+
+/**
+ * Provides data that allows you to change the size of the floating element —
+ * for instance, prevent it from overflowing the clipping boundary or match the
+ * width of the reference element.
+ * @see https://floating-ui.com/docs/size
+ */
+const size = function (options) {
+  if (options === void 0) {
+    options = {};
+  }
+  return {
+    name: 'size',
+    options,
+    async fn(state) {
+      var _state$middlewareData, _state$middlewareData2;
+      const {
+        placement,
+        rects,
+        platform,
+        elements
+      } = state;
+      const {
+        apply = () => {},
+        ...detectOverflowOptions
+      } = evaluate(options, state);
+      const overflow = await detectOverflow(state, detectOverflowOptions);
+      const side = getSide(placement);
+      const alignment = getAlignment(placement);
+      const isYAxis = getSideAxis(placement) === 'y';
+      const {
+        width,
+        height
+      } = rects.floating;
+      let heightSide;
+      let widthSide;
+      if (side === 'top' || side === 'bottom') {
+        heightSide = side;
+        widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';
+      } else {
+        widthSide = side;
+        heightSide = alignment === 'end' ? 'top' : 'bottom';
+      }
+      const maximumClippingHeight = height - overflow.top - overflow.bottom;
+      const maximumClippingWidth = width - overflow.left - overflow.right;
+      const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
+      const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
+      const noShift = !state.middlewareData.shift;
+      let availableHeight = overflowAvailableHeight;
+      let availableWidth = overflowAvailableWidth;
+      if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
+        availableWidth = maximumClippingWidth;
+      }
+      if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
+        availableHeight = maximumClippingHeight;
+      }
+      if (noShift && !alignment) {
+        const xMin = max(overflow.left, 0);
+        const xMax = max(overflow.right, 0);
+        const yMin = max(overflow.top, 0);
+        const yMax = max(overflow.bottom, 0);
+        if (isYAxis) {
+          availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
+        } else {
+          availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
+        }
+      }
+      await apply({
+        ...state,
+        availableWidth,
+        availableHeight
+      });
+      const nextDimensions = await platform.getDimensions(elements.floating);
+      if (width !== nextDimensions.width || height !== nextDimensions.height) {
+        return {
+          reset: {
+            rects: true
+          }
+        };
+      }
+      return {};
+    }
+  };
+};
+
+export { arrow, autoPlacement, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, shift, size };

+ 759 - 0
node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs

@@ -0,0 +1,759 @@
+import { rectToClientRect, arrow as arrow$1, autoPlacement as autoPlacement$1, detectOverflow as detectOverflow$1, flip as flip$1, hide as hide$1, inline as inline$1, limitShift as limitShift$1, offset as offset$1, shift as shift$1, size as size$1, computePosition as computePosition$1 } from '@floating-ui/core';
+import { round, createCoords, max, min, floor } from '@floating-ui/utils';
+import { getComputedStyle, isHTMLElement, isElement, getWindow, isWebKit, getFrameElement, getNodeScroll, getDocumentElement, isTopLayer, getNodeName, isOverflowElement, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';
+export { getOverflowAncestors } from '@floating-ui/utils/dom';
+
+function getCssDimensions(element) {
+  const css = getComputedStyle(element);
+  // In testing environments, the `width` and `height` properties are empty
+  // strings for SVG elements, returning NaN. Fallback to `0` in this case.
+  let width = parseFloat(css.width) || 0;
+  let height = parseFloat(css.height) || 0;
+  const hasOffset = isHTMLElement(element);
+  const offsetWidth = hasOffset ? element.offsetWidth : width;
+  const offsetHeight = hasOffset ? element.offsetHeight : height;
+  const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
+  if (shouldFallback) {
+    width = offsetWidth;
+    height = offsetHeight;
+  }
+  return {
+    width,
+    height,
+    $: shouldFallback
+  };
+}
+
+function unwrapElement(element) {
+  return !isElement(element) ? element.contextElement : element;
+}
+
+function getScale(element) {
+  const domElement = unwrapElement(element);
+  if (!isHTMLElement(domElement)) {
+    return createCoords(1);
+  }
+  const rect = domElement.getBoundingClientRect();
+  const {
+    width,
+    height,
+    $
+  } = getCssDimensions(domElement);
+  let x = ($ ? round(rect.width) : rect.width) / width;
+  let y = ($ ? round(rect.height) : rect.height) / height;
+
+  // 0, NaN, or Infinity should always fallback to 1.
+
+  if (!x || !Number.isFinite(x)) {
+    x = 1;
+  }
+  if (!y || !Number.isFinite(y)) {
+    y = 1;
+  }
+  return {
+    x,
+    y
+  };
+}
+
+const noOffsets = /*#__PURE__*/createCoords(0);
+function getVisualOffsets(element) {
+  const win = getWindow(element);
+  if (!isWebKit() || !win.visualViewport) {
+    return noOffsets;
+  }
+  return {
+    x: win.visualViewport.offsetLeft,
+    y: win.visualViewport.offsetTop
+  };
+}
+function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
+  if (isFixed === void 0) {
+    isFixed = false;
+  }
+  if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
+    return false;
+  }
+  return isFixed;
+}
+
+function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
+  if (includeScale === void 0) {
+    includeScale = false;
+  }
+  if (isFixedStrategy === void 0) {
+    isFixedStrategy = false;
+  }
+  const clientRect = element.getBoundingClientRect();
+  const domElement = unwrapElement(element);
+  let scale = createCoords(1);
+  if (includeScale) {
+    if (offsetParent) {
+      if (isElement(offsetParent)) {
+        scale = getScale(offsetParent);
+      }
+    } else {
+      scale = getScale(element);
+    }
+  }
+  const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
+  let x = (clientRect.left + visualOffsets.x) / scale.x;
+  let y = (clientRect.top + visualOffsets.y) / scale.y;
+  let width = clientRect.width / scale.x;
+  let height = clientRect.height / scale.y;
+  if (domElement) {
+    const win = getWindow(domElement);
+    const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
+    let currentWin = win;
+    let currentIFrame = getFrameElement(currentWin);
+    while (currentIFrame && offsetParent && offsetWin !== currentWin) {
+      const iframeScale = getScale(currentIFrame);
+      const iframeRect = currentIFrame.getBoundingClientRect();
+      const css = getComputedStyle(currentIFrame);
+      const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
+      const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
+      x *= iframeScale.x;
+      y *= iframeScale.y;
+      width *= iframeScale.x;
+      height *= iframeScale.y;
+      x += left;
+      y += top;
+      currentWin = getWindow(currentIFrame);
+      currentIFrame = getFrameElement(currentWin);
+    }
+  }
+  return rectToClientRect({
+    width,
+    height,
+    x,
+    y
+  });
+}
+
+// If <html> has a CSS width greater than the viewport, then this will be
+// incorrect for RTL.
+function getWindowScrollBarX(element, rect) {
+  const leftScroll = getNodeScroll(element).scrollLeft;
+  if (!rect) {
+    return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;
+  }
+  return rect.left + leftScroll;
+}
+
+function getHTMLOffset(documentElement, scroll, ignoreScrollbarX) {
+  if (ignoreScrollbarX === void 0) {
+    ignoreScrollbarX = false;
+  }
+  const htmlRect = documentElement.getBoundingClientRect();
+  const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 :
+  // RTL <body> scrollbar.
+  getWindowScrollBarX(documentElement, htmlRect));
+  const y = htmlRect.top + scroll.scrollTop;
+  return {
+    x,
+    y
+  };
+}
+
+function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
+  let {
+    elements,
+    rect,
+    offsetParent,
+    strategy
+  } = _ref;
+  const isFixed = strategy === 'fixed';
+  const documentElement = getDocumentElement(offsetParent);
+  const topLayer = elements ? isTopLayer(elements.floating) : false;
+  if (offsetParent === documentElement || topLayer && isFixed) {
+    return rect;
+  }
+  let scroll = {
+    scrollLeft: 0,
+    scrollTop: 0
+  };
+  let scale = createCoords(1);
+  const offsets = createCoords(0);
+  const isOffsetParentAnElement = isHTMLElement(offsetParent);
+  if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
+    if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
+      scroll = getNodeScroll(offsetParent);
+    }
+    if (isHTMLElement(offsetParent)) {
+      const offsetRect = getBoundingClientRect(offsetParent);
+      scale = getScale(offsetParent);
+      offsets.x = offsetRect.x + offsetParent.clientLeft;
+      offsets.y = offsetRect.y + offsetParent.clientTop;
+    }
+  }
+  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0);
+  return {
+    width: rect.width * scale.x,
+    height: rect.height * scale.y,
+    x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
+    y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
+  };
+}
+
+function getClientRects(element) {
+  return Array.from(element.getClientRects());
+}
+
+// Gets the entire size of the scrollable document area, even extending outside
+// of the `<html>` and `<body>` rect bounds if horizontally scrollable.
+function getDocumentRect(element) {
+  const html = getDocumentElement(element);
+  const scroll = getNodeScroll(element);
+  const body = element.ownerDocument.body;
+  const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
+  const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
+  let x = -scroll.scrollLeft + getWindowScrollBarX(element);
+  const y = -scroll.scrollTop;
+  if (getComputedStyle(body).direction === 'rtl') {
+    x += max(html.clientWidth, body.clientWidth) - width;
+  }
+  return {
+    width,
+    height,
+    x,
+    y
+  };
+}
+
+function getViewportRect(element, strategy) {
+  const win = getWindow(element);
+  const html = getDocumentElement(element);
+  const visualViewport = win.visualViewport;
+  let width = html.clientWidth;
+  let height = html.clientHeight;
+  let x = 0;
+  let y = 0;
+  if (visualViewport) {
+    width = visualViewport.width;
+    height = visualViewport.height;
+    const visualViewportBased = isWebKit();
+    if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
+      x = visualViewport.offsetLeft;
+      y = visualViewport.offsetTop;
+    }
+  }
+  return {
+    width,
+    height,
+    x,
+    y
+  };
+}
+
+// Returns the inner client rect, subtracting scrollbars if present.
+function getInnerBoundingClientRect(element, strategy) {
+  const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
+  const top = clientRect.top + element.clientTop;
+  const left = clientRect.left + element.clientLeft;
+  const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
+  const width = element.clientWidth * scale.x;
+  const height = element.clientHeight * scale.y;
+  const x = left * scale.x;
+  const y = top * scale.y;
+  return {
+    width,
+    height,
+    x,
+    y
+  };
+}
+function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
+  let rect;
+  if (clippingAncestor === 'viewport') {
+    rect = getViewportRect(element, strategy);
+  } else if (clippingAncestor === 'document') {
+    rect = getDocumentRect(getDocumentElement(element));
+  } else if (isElement(clippingAncestor)) {
+    rect = getInnerBoundingClientRect(clippingAncestor, strategy);
+  } else {
+    const visualOffsets = getVisualOffsets(element);
+    rect = {
+      x: clippingAncestor.x - visualOffsets.x,
+      y: clippingAncestor.y - visualOffsets.y,
+      width: clippingAncestor.width,
+      height: clippingAncestor.height
+    };
+  }
+  return rectToClientRect(rect);
+}
+function hasFixedPositionAncestor(element, stopNode) {
+  const parentNode = getParentNode(element);
+  if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
+    return false;
+  }
+  return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
+}
+
+// A "clipping ancestor" is an `overflow` element with the characteristic of
+// clipping (or hiding) child elements. This returns all clipping ancestors
+// of the given element up the tree.
+function getClippingElementAncestors(element, cache) {
+  const cachedResult = cache.get(element);
+  if (cachedResult) {
+    return cachedResult;
+  }
+  let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
+  let currentContainingBlockComputedStyle = null;
+  const elementIsFixed = getComputedStyle(element).position === 'fixed';
+  let currentNode = elementIsFixed ? getParentNode(element) : element;
+
+  // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
+  while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
+    const computedStyle = getComputedStyle(currentNode);
+    const currentNodeIsContaining = isContainingBlock(currentNode);
+    if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
+      currentContainingBlockComputedStyle = null;
+    }
+    const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
+    if (shouldDropCurrentNode) {
+      // Drop non-containing blocks.
+      result = result.filter(ancestor => ancestor !== currentNode);
+    } else {
+      // Record last containing block for next iteration.
+      currentContainingBlockComputedStyle = computedStyle;
+    }
+    currentNode = getParentNode(currentNode);
+  }
+  cache.set(element, result);
+  return result;
+}
+
+// Gets the maximum area that the element is visible in due to any number of
+// clipping ancestors.
+function getClippingRect(_ref) {
+  let {
+    element,
+    boundary,
+    rootBoundary,
+    strategy
+  } = _ref;
+  const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
+  const clippingAncestors = [...elementClippingAncestors, rootBoundary];
+  const firstClippingAncestor = clippingAncestors[0];
+  const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
+    const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
+    accRect.top = max(rect.top, accRect.top);
+    accRect.right = min(rect.right, accRect.right);
+    accRect.bottom = min(rect.bottom, accRect.bottom);
+    accRect.left = max(rect.left, accRect.left);
+    return accRect;
+  }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
+  return {
+    width: clippingRect.right - clippingRect.left,
+    height: clippingRect.bottom - clippingRect.top,
+    x: clippingRect.left,
+    y: clippingRect.top
+  };
+}
+
+function getDimensions(element) {
+  const {
+    width,
+    height
+  } = getCssDimensions(element);
+  return {
+    width,
+    height
+  };
+}
+
+function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
+  const isOffsetParentAnElement = isHTMLElement(offsetParent);
+  const documentElement = getDocumentElement(offsetParent);
+  const isFixed = strategy === 'fixed';
+  const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
+  let scroll = {
+    scrollLeft: 0,
+    scrollTop: 0
+  };
+  const offsets = createCoords(0);
+
+  // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
+  // Firefox with layout.scrollbar.side = 3 in about:config to test this.
+  function setLeftRTLScrollbarOffset() {
+    offsets.x = getWindowScrollBarX(documentElement);
+  }
+  if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
+    if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
+      scroll = getNodeScroll(offsetParent);
+    }
+    if (isOffsetParentAnElement) {
+      const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
+      offsets.x = offsetRect.x + offsetParent.clientLeft;
+      offsets.y = offsetRect.y + offsetParent.clientTop;
+    } else if (documentElement) {
+      setLeftRTLScrollbarOffset();
+    }
+  }
+  if (isFixed && !isOffsetParentAnElement && documentElement) {
+    setLeftRTLScrollbarOffset();
+  }
+  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
+  const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
+  const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
+  return {
+    x,
+    y,
+    width: rect.width,
+    height: rect.height
+  };
+}
+
+function isStaticPositioned(element) {
+  return getComputedStyle(element).position === 'static';
+}
+
+function getTrueOffsetParent(element, polyfill) {
+  if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {
+    return null;
+  }
+  if (polyfill) {
+    return polyfill(element);
+  }
+  let rawOffsetParent = element.offsetParent;
+
+  // Firefox returns the <html> element as the offsetParent if it's non-static,
+  // while Chrome and Safari return the <body> element. The <body> element must
+  // be used to perform the correct calculations even if the <html> element is
+  // non-static.
+  if (getDocumentElement(element) === rawOffsetParent) {
+    rawOffsetParent = rawOffsetParent.ownerDocument.body;
+  }
+  return rawOffsetParent;
+}
+
+// Gets the closest ancestor positioned element. Handles some edge cases,
+// such as table ancestors and cross browser bugs.
+function getOffsetParent(element, polyfill) {
+  const win = getWindow(element);
+  if (isTopLayer(element)) {
+    return win;
+  }
+  if (!isHTMLElement(element)) {
+    let svgOffsetParent = getParentNode(element);
+    while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
+      if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
+        return svgOffsetParent;
+      }
+      svgOffsetParent = getParentNode(svgOffsetParent);
+    }
+    return win;
+  }
+  let offsetParent = getTrueOffsetParent(element, polyfill);
+  while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
+    offsetParent = getTrueOffsetParent(offsetParent, polyfill);
+  }
+  if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
+    return win;
+  }
+  return offsetParent || getContainingBlock(element) || win;
+}
+
+const getElementRects = async function (data) {
+  const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
+  const getDimensionsFn = this.getDimensions;
+  const floatingDimensions = await getDimensionsFn(data.floating);
+  return {
+    reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
+    floating: {
+      x: 0,
+      y: 0,
+      width: floatingDimensions.width,
+      height: floatingDimensions.height
+    }
+  };
+};
+
+function isRTL(element) {
+  return getComputedStyle(element).direction === 'rtl';
+}
+
+const platform = {
+  convertOffsetParentRelativeRectToViewportRelativeRect,
+  getDocumentElement,
+  getClippingRect,
+  getOffsetParent,
+  getElementRects,
+  getClientRects,
+  getDimensions,
+  getScale,
+  isElement,
+  isRTL
+};
+
+function rectsAreEqual(a, b) {
+  return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
+}
+
+// https://samthor.au/2021/observing-dom/
+function observeMove(element, onMove) {
+  let io = null;
+  let timeoutId;
+  const root = getDocumentElement(element);
+  function cleanup() {
+    var _io;
+    clearTimeout(timeoutId);
+    (_io = io) == null || _io.disconnect();
+    io = null;
+  }
+  function refresh(skip, threshold) {
+    if (skip === void 0) {
+      skip = false;
+    }
+    if (threshold === void 0) {
+      threshold = 1;
+    }
+    cleanup();
+    const elementRectForRootMargin = element.getBoundingClientRect();
+    const {
+      left,
+      top,
+      width,
+      height
+    } = elementRectForRootMargin;
+    if (!skip) {
+      onMove();
+    }
+    if (!width || !height) {
+      return;
+    }
+    const insetTop = floor(top);
+    const insetRight = floor(root.clientWidth - (left + width));
+    const insetBottom = floor(root.clientHeight - (top + height));
+    const insetLeft = floor(left);
+    const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
+    const options = {
+      rootMargin,
+      threshold: max(0, min(1, threshold)) || 1
+    };
+    let isFirstUpdate = true;
+    function handleObserve(entries) {
+      const ratio = entries[0].intersectionRatio;
+      if (ratio !== threshold) {
+        if (!isFirstUpdate) {
+          return refresh();
+        }
+        if (!ratio) {
+          // If the reference is clipped, the ratio is 0. Throttle the refresh
+          // to prevent an infinite loop of updates.
+          timeoutId = setTimeout(() => {
+            refresh(false, 1e-7);
+          }, 1000);
+        } else {
+          refresh(false, ratio);
+        }
+      }
+      if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
+        // It's possible that even though the ratio is reported as 1, the
+        // element is not actually fully within the IntersectionObserver's root
+        // area anymore. This can happen under performance constraints. This may
+        // be a bug in the browser's IntersectionObserver implementation. To
+        // work around this, we compare the element's bounding rect now with
+        // what it was at the time we created the IntersectionObserver. If they
+        // are not equal then the element moved, so we refresh.
+        refresh();
+      }
+      isFirstUpdate = false;
+    }
+
+    // Older browsers don't support a `document` as the root and will throw an
+    // error.
+    try {
+      io = new IntersectionObserver(handleObserve, {
+        ...options,
+        // Handle <iframe>s
+        root: root.ownerDocument
+      });
+    } catch (_e) {
+      io = new IntersectionObserver(handleObserve, options);
+    }
+    io.observe(element);
+  }
+  refresh(true);
+  return cleanup;
+}
+
+/**
+ * Automatically updates the position of the floating element when necessary.
+ * Should only be called when the floating element is mounted on the DOM or
+ * visible on the screen.
+ * @returns cleanup function that should be invoked when the floating element is
+ * removed from the DOM or hidden from the screen.
+ * @see https://floating-ui.com/docs/autoUpdate
+ */
+function autoUpdate(reference, floating, update, options) {
+  if (options === void 0) {
+    options = {};
+  }
+  const {
+    ancestorScroll = true,
+    ancestorResize = true,
+    elementResize = typeof ResizeObserver === 'function',
+    layoutShift = typeof IntersectionObserver === 'function',
+    animationFrame = false
+  } = options;
+  const referenceEl = unwrapElement(reference);
+  const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
+  ancestors.forEach(ancestor => {
+    ancestorScroll && ancestor.addEventListener('scroll', update, {
+      passive: true
+    });
+    ancestorResize && ancestor.addEventListener('resize', update);
+  });
+  const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
+  let reobserveFrame = -1;
+  let resizeObserver = null;
+  if (elementResize) {
+    resizeObserver = new ResizeObserver(_ref => {
+      let [firstEntry] = _ref;
+      if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
+        // Prevent update loops when using the `size` middleware.
+        // https://github.com/floating-ui/floating-ui/issues/1740
+        resizeObserver.unobserve(floating);
+        cancelAnimationFrame(reobserveFrame);
+        reobserveFrame = requestAnimationFrame(() => {
+          var _resizeObserver;
+          (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
+        });
+      }
+      update();
+    });
+    if (referenceEl && !animationFrame) {
+      resizeObserver.observe(referenceEl);
+    }
+    resizeObserver.observe(floating);
+  }
+  let frameId;
+  let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
+  if (animationFrame) {
+    frameLoop();
+  }
+  function frameLoop() {
+    const nextRefRect = getBoundingClientRect(reference);
+    if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
+      update();
+    }
+    prevRefRect = nextRefRect;
+    frameId = requestAnimationFrame(frameLoop);
+  }
+  update();
+  return () => {
+    var _resizeObserver2;
+    ancestors.forEach(ancestor => {
+      ancestorScroll && ancestor.removeEventListener('scroll', update);
+      ancestorResize && ancestor.removeEventListener('resize', update);
+    });
+    cleanupIo == null || cleanupIo();
+    (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
+    resizeObserver = null;
+    if (animationFrame) {
+      cancelAnimationFrame(frameId);
+    }
+  };
+}
+
+/**
+ * Resolves with an object of overflow side offsets that determine how much the
+ * element is overflowing a given clipping boundary on each side.
+ * - positive = overflowing the boundary by that number of pixels
+ * - negative = how many pixels left before it will overflow
+ * - 0 = lies flush with the boundary
+ * @see https://floating-ui.com/docs/detectOverflow
+ */
+const detectOverflow = detectOverflow$1;
+
+/**
+ * Modifies the placement by translating the floating element along the
+ * specified axes.
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
+ * object may be passed.
+ * @see https://floating-ui.com/docs/offset
+ */
+const offset = offset$1;
+
+/**
+ * Optimizes the visibility of the floating element by choosing the placement
+ * that has the most space available automatically, without needing to specify a
+ * preferred placement. Alternative to `flip`.
+ * @see https://floating-ui.com/docs/autoPlacement
+ */
+const autoPlacement = autoPlacement$1;
+
+/**
+ * Optimizes the visibility of the floating element by shifting it in order to
+ * keep it in view when it will overflow the clipping boundary.
+ * @see https://floating-ui.com/docs/shift
+ */
+const shift = shift$1;
+
+/**
+ * Optimizes the visibility of the floating element by flipping the `placement`
+ * in order to keep it in view when the preferred placement(s) will overflow the
+ * clipping boundary. Alternative to `autoPlacement`.
+ * @see https://floating-ui.com/docs/flip
+ */
+const flip = flip$1;
+
+/**
+ * Provides data that allows you to change the size of the floating element —
+ * for instance, prevent it from overflowing the clipping boundary or match the
+ * width of the reference element.
+ * @see https://floating-ui.com/docs/size
+ */
+const size = size$1;
+
+/**
+ * Provides data to hide the floating element in applicable situations, such as
+ * when it is not in the same clipping context as the reference element.
+ * @see https://floating-ui.com/docs/hide
+ */
+const hide = hide$1;
+
+/**
+ * Provides data to position an inner element of the floating element so that it
+ * appears centered to the reference element.
+ * @see https://floating-ui.com/docs/arrow
+ */
+const arrow = arrow$1;
+
+/**
+ * Provides improved positioning for inline reference elements that can span
+ * over multiple lines, such as hyperlinks or range selections.
+ * @see https://floating-ui.com/docs/inline
+ */
+const inline = inline$1;
+
+/**
+ * Built-in `limiter` that will stop `shift()` at a certain point.
+ */
+const limitShift = limitShift$1;
+
+/**
+ * Computes the `x` and `y` coordinates that will place the floating element
+ * next to a given reference element.
+ */
+const computePosition = (reference, floating, options) => {
+  // This caches the expensive `getClippingElementAncestors` function so that
+  // multiple lifecycle resets re-use the same result. It only lives for a
+  // single call. If other functions become expensive, we can add them as well.
+  const cache = new Map();
+  const mergedOptions = {
+    platform,
+    ...options
+  };
+  const platformWithCache = {
+    ...mergedOptions.platform,
+    _c: cache
+  };
+  return computePosition$1(reference, floating, {
+    ...mergedOptions,
+    platform: platformWithCache
+  });
+};
+
+export { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, platform, shift, size };

+ 154 - 0
node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs

@@ -0,0 +1,154 @@
+function hasWindow() {
+  return typeof window !== 'undefined';
+}
+function getNodeName(node) {
+  if (isNode(node)) {
+    return (node.nodeName || '').toLowerCase();
+  }
+  // Mocked nodes in testing environments may not be instances of Node. By
+  // returning `#document` an infinite loop won't occur.
+  // https://github.com/floating-ui/floating-ui/issues/2317
+  return '#document';
+}
+function getWindow(node) {
+  var _node$ownerDocument;
+  return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
+}
+function getDocumentElement(node) {
+  var _ref;
+  return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
+}
+function isNode(value) {
+  if (!hasWindow()) {
+    return false;
+  }
+  return value instanceof Node || value instanceof getWindow(value).Node;
+}
+function isElement(value) {
+  if (!hasWindow()) {
+    return false;
+  }
+  return value instanceof Element || value instanceof getWindow(value).Element;
+}
+function isHTMLElement(value) {
+  if (!hasWindow()) {
+    return false;
+  }
+  return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
+}
+function isShadowRoot(value) {
+  if (!hasWindow() || typeof ShadowRoot === 'undefined') {
+    return false;
+  }
+  return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
+}
+function isOverflowElement(element) {
+  const {
+    overflow,
+    overflowX,
+    overflowY,
+    display
+  } = getComputedStyle(element);
+  return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);
+}
+function isTableElement(element) {
+  return ['table', 'td', 'th'].includes(getNodeName(element));
+}
+function isTopLayer(element) {
+  return [':popover-open', ':modal'].some(selector => {
+    try {
+      return element.matches(selector);
+    } catch (e) {
+      return false;
+    }
+  });
+}
+function isContainingBlock(elementOrCss) {
+  const webkit = isWebKit();
+  const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
+
+  // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
+  // https://drafts.csswg.org/css-transforms-2/#individual-transforms
+  return ['transform', 'translate', 'scale', 'rotate', 'perspective'].some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
+}
+function getContainingBlock(element) {
+  let currentNode = getParentNode(element);
+  while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
+    if (isContainingBlock(currentNode)) {
+      return currentNode;
+    } else if (isTopLayer(currentNode)) {
+      return null;
+    }
+    currentNode = getParentNode(currentNode);
+  }
+  return null;
+}
+function isWebKit() {
+  if (typeof CSS === 'undefined' || !CSS.supports) return false;
+  return CSS.supports('-webkit-backdrop-filter', 'none');
+}
+function isLastTraversableNode(node) {
+  return ['html', 'body', '#document'].includes(getNodeName(node));
+}
+function getComputedStyle(element) {
+  return getWindow(element).getComputedStyle(element);
+}
+function getNodeScroll(element) {
+  if (isElement(element)) {
+    return {
+      scrollLeft: element.scrollLeft,
+      scrollTop: element.scrollTop
+    };
+  }
+  return {
+    scrollLeft: element.scrollX,
+    scrollTop: element.scrollY
+  };
+}
+function getParentNode(node) {
+  if (getNodeName(node) === 'html') {
+    return node;
+  }
+  const result =
+  // Step into the shadow DOM of the parent of a slotted node.
+  node.assignedSlot ||
+  // DOM Element detected.
+  node.parentNode ||
+  // ShadowRoot detected.
+  isShadowRoot(node) && node.host ||
+  // Fallback.
+  getDocumentElement(node);
+  return isShadowRoot(result) ? result.host : result;
+}
+function getNearestOverflowAncestor(node) {
+  const parentNode = getParentNode(node);
+  if (isLastTraversableNode(parentNode)) {
+    return node.ownerDocument ? node.ownerDocument.body : node.body;
+  }
+  if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
+    return parentNode;
+  }
+  return getNearestOverflowAncestor(parentNode);
+}
+function getOverflowAncestors(node, list, traverseIframes) {
+  var _node$ownerDocument2;
+  if (list === void 0) {
+    list = [];
+  }
+  if (traverseIframes === void 0) {
+    traverseIframes = true;
+  }
+  const scrollableAncestor = getNearestOverflowAncestor(node);
+  const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
+  const win = getWindow(scrollableAncestor);
+  if (isBody) {
+    const frameElement = getFrameElement(win);
+    return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
+  }
+  return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
+}
+function getFrameElement(win) {
+  return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
+}
+
+export { getComputedStyle, getContainingBlock, getDocumentElement, getFrameElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isTopLayer, isWebKit };

+ 138 - 0
node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs

@@ -0,0 +1,138 @@
+/**
+ * Custom positioning reference element.
+ * @see https://floating-ui.com/docs/virtual-elements
+ */
+
+const sides = ['top', 'right', 'bottom', 'left'];
+const alignments = ['start', 'end'];
+const placements = /*#__PURE__*/sides.reduce((acc, side) => acc.concat(side, side + "-" + alignments[0], side + "-" + alignments[1]), []);
+const min = Math.min;
+const max = Math.max;
+const round = Math.round;
+const floor = Math.floor;
+const createCoords = v => ({
+  x: v,
+  y: v
+});
+const oppositeSideMap = {
+  left: 'right',
+  right: 'left',
+  bottom: 'top',
+  top: 'bottom'
+};
+const oppositeAlignmentMap = {
+  start: 'end',
+  end: 'start'
+};
+function clamp(start, value, end) {
+  return max(start, min(value, end));
+}
+function evaluate(value, param) {
+  return typeof value === 'function' ? value(param) : value;
+}
+function getSide(placement) {
+  return placement.split('-')[0];
+}
+function getAlignment(placement) {
+  return placement.split('-')[1];
+}
+function getOppositeAxis(axis) {
+  return axis === 'x' ? 'y' : 'x';
+}
+function getAxisLength(axis) {
+  return axis === 'y' ? 'height' : 'width';
+}
+function getSideAxis(placement) {
+  return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x';
+}
+function getAlignmentAxis(placement) {
+  return getOppositeAxis(getSideAxis(placement));
+}
+function getAlignmentSides(placement, rects, rtl) {
+  if (rtl === void 0) {
+    rtl = false;
+  }
+  const alignment = getAlignment(placement);
+  const alignmentAxis = getAlignmentAxis(placement);
+  const length = getAxisLength(alignmentAxis);
+  let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
+  if (rects.reference[length] > rects.floating[length]) {
+    mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
+  }
+  return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
+}
+function getExpandedPlacements(placement) {
+  const oppositePlacement = getOppositePlacement(placement);
+  return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
+}
+function getOppositeAlignmentPlacement(placement) {
+  return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);
+}
+function getSideList(side, isStart, rtl) {
+  const lr = ['left', 'right'];
+  const rl = ['right', 'left'];
+  const tb = ['top', 'bottom'];
+  const bt = ['bottom', 'top'];
+  switch (side) {
+    case 'top':
+    case 'bottom':
+      if (rtl) return isStart ? rl : lr;
+      return isStart ? lr : rl;
+    case 'left':
+    case 'right':
+      return isStart ? tb : bt;
+    default:
+      return [];
+  }
+}
+function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
+  const alignment = getAlignment(placement);
+  let list = getSideList(getSide(placement), direction === 'start', rtl);
+  if (alignment) {
+    list = list.map(side => side + "-" + alignment);
+    if (flipAlignment) {
+      list = list.concat(list.map(getOppositeAlignmentPlacement));
+    }
+  }
+  return list;
+}
+function getOppositePlacement(placement) {
+  return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);
+}
+function expandPaddingObject(padding) {
+  return {
+    top: 0,
+    right: 0,
+    bottom: 0,
+    left: 0,
+    ...padding
+  };
+}
+function getPaddingObject(padding) {
+  return typeof padding !== 'number' ? expandPaddingObject(padding) : {
+    top: padding,
+    right: padding,
+    bottom: padding,
+    left: padding
+  };
+}
+function rectToClientRect(rect) {
+  const {
+    x,
+    y,
+    width,
+    height
+  } = rect;
+  return {
+    width,
+    height,
+    top: y,
+    left: x,
+    right: x + width,
+    bottom: y + height,
+    x,
+    y
+  };
+}
+
+export { alignments, clamp, createCoords, evaluate, expandPaddingObject, floor, getAlignment, getAlignmentAxis, getAlignmentSides, getAxisLength, getExpandedPlacements, getOppositeAlignmentPlacement, getOppositeAxis, getOppositeAxisPlacements, getOppositePlacement, getPaddingObject, getSide, getSideAxis, max, min, placements, rectToClientRect, round, sides };

+ 14 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/app-event-page-intent.js

@@ -0,0 +1,14 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+const APP_EVENT_PAGE_INTENT_KIND = "AppEventPageIntent";
+export function makeAppEventPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        $kind: APP_EVENT_PAGE_INTENT_KIND,
+        platform: normalizePreviewPlaform(platform),
+    };
+}
+export function isAppEventPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === APP_EVENT_PAGE_INTENT_KIND;
+}
+//# sourceMappingURL=app-event-page-intent.js.map

+ 10 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/arcade-grouping-page-intent.js

@@ -0,0 +1,10 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeArcadeGroupingPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: "ArcadeGroupingPageIntent",
+    };
+}
+//# sourceMappingURL=arcade-grouping-page-intent.js.map

+ 16 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/bundle-page-intent.js

@@ -0,0 +1,16 @@
+import { normalizeAdamID } from "../util";
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeBundlePageIntent(opts) {
+    const { id, platform, lic, ...rest } = opts;
+    return {
+        $kind: "BundlePageIntent",
+        id: normalizeAdamID(id),
+        platform: normalizePreviewPlaform(platform),
+        lic,
+        ...rest,
+    };
+}
+export function isBundlePageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === "BundlePageIntent";
+}
+//# sourceMappingURL=bundle-page-intent.js.map

+ 8 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/category-tabs-intent.js

@@ -0,0 +1,8 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeCategoryTabsIntent(opts) {
+    return {
+        $kind: "CategoryTabsIntent",
+        platform: normalizePreviewPlaform(opts.platform),
+    };
+}
+//# sourceMappingURL=category-tabs-intent.js.map

+ 13 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/charts-hub-page-intent.js

@@ -0,0 +1,13 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+/**
+ * Create a {@linkcode ChartsHubPageIntent}
+ */
+export function makeChartsHubPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: "ChartsHubPageIntent",
+    };
+}
+//# sourceMappingURL=charts-hub-page-intent.js.map

+ 13 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/charts-page-intent.js

@@ -0,0 +1,13 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+const CHARTS_PAGE_INTENT_KIND = "ChartsPageIntent";
+export function makeChartsPageIntent({ platform, ...rest }) {
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: CHARTS_PAGE_INTENT_KIND,
+    };
+}
+export function isChartsPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === CHARTS_PAGE_INTENT_KIND;
+}
+//# sourceMappingURL=charts-page-intent.js.map

+ 19 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/developer-page-intent.js

@@ -0,0 +1,19 @@
+import { normalizeAdamID } from "../util";
+const DEVELOPER_PAGE_INTENT_KIND = "DeveloperPageIntent";
+/**
+ * Determines if {@linkcode intent} is a {@linkcode DeveloperPageIntent}
+ */
+export function isDeveloperPageIntent(intent) {
+    return intent.$kind === DEVELOPER_PAGE_INTENT_KIND;
+}
+/**
+ * Creates a {@linkcode DeveloperPageIntent}
+ */
+export function makeDeveloperPageIntent({ id, ...rest }) {
+    return {
+        ...rest,
+        id: normalizeAdamID(id),
+        $kind: DEVELOPER_PAGE_INTENT_KIND,
+    };
+}
+//# sourceMappingURL=developer-page-intent.js.map

+ 37 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/editorial/editorial-page-intent.js

@@ -0,0 +1,37 @@
+import { normalizePreviewPlaform } from "../../models/preview-platform";
+export function isEditorialPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === "EditorialPageIntent";
+}
+export function isEditorialPageIntentByID(intent) {
+    return isEditorialPageIntent(intent) && "id" in intent;
+}
+export function isEditorialPageIntentByName(intent) {
+    return isEditorialPageIntent(intent) && "name" in intent;
+}
+/**
+ * Creates an {@link EditorialPageIntent} that fetches an Editorial Page by "name"
+ *
+ * @param options the properties of the created {@link EditorialPageIntentByName}
+ */
+export function makeEditorialPageIntentByName(options) {
+    const { platform, ...rest } = options;
+    return {
+        ...rest,
+        $kind: "EditorialPageIntent",
+        platform: normalizePreviewPlaform(platform),
+    };
+}
+/**
+ * Creates an {@link EditorialPageIntent} that fetches an Editorial Page by "id"
+ *
+ * @param options the properties of the created {@linkcode EditorialPageIntentById}
+ */
+export function makeEditorialPageIntentByID(options) {
+    const { platform, ...rest } = options;
+    return {
+        $kind: "EditorialPageIntent",
+        platform: normalizePreviewPlaform(platform),
+        ...rest,
+    };
+}
+//# sourceMappingURL=editorial-page-intent.js.map

+ 14 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/editorial/editorial-shelf-collection-page-intent.js

@@ -0,0 +1,14 @@
+import { normalizePreviewPlaform } from "../../models/preview-platform";
+const EDITORIAL_SHELF_COLLECTION_PAGE_INTENT_KIND = "EditorialShelfCollectionPageIntent";
+export function isEditorialShelfCollectionPageIntent(intent) {
+    return intent.$kind === EDITORIAL_SHELF_COLLECTION_PAGE_INTENT_KIND;
+}
+export function makeEditorialShelfCollectionPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        $kind: EDITORIAL_SHELF_COLLECTION_PAGE_INTENT_KIND,
+        platform: normalizePreviewPlaform(platform),
+    };
+}
+//# sourceMappingURL=editorial-shelf-collection-page-intent.js.map

+ 19 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/eula-page-intent.js

@@ -0,0 +1,19 @@
+const EULA_PAGE_INTENT_KIND = "EulaPageIntent";
+/**
+ * Determines if {@linkcode intent} is a {@linkcode EulaPageIntent}
+ */
+export function isEulaPageIntent(intent) {
+    return intent.$kind === EULA_PAGE_INTENT_KIND;
+}
+/**
+ * Creates a {@linkcode EulaPageIntent}
+ */
+export function makeEulaPageIntent({ resourceId, resourceType, ...rest }) {
+    return {
+        ...rest,
+        resourceId,
+        resourceType,
+        $kind: EULA_PAGE_INTENT_KIND,
+    };
+}
+//# sourceMappingURL=eula-page-intent.js.map

+ 33 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/grouping-page-intent.js

@@ -0,0 +1,33 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+import { normalizeAdamID } from "../util";
+export function isGroupingPageIntent(intent) {
+    return intent.$kind === "GroupingPageIntent";
+}
+/**
+ * Creates a {@link GroupingPageIntent} "by name"
+ *
+ * @param options the properties of the created {@link GroupingPageIntent}
+ */
+export function makeGroupingPageIntentByName(options) {
+    const { platform, ...rest } = options;
+    return {
+        ...rest,
+        $kind: "GroupingPageIntent",
+        platform: normalizePreviewPlaform(platform),
+    };
+}
+/**
+ * Creates a {@link GroupingPageIntent} "by ID"
+ *
+ * @param options the properties of the created {@link GroupingPageIntent}
+ */
+export function makeGroupingPageIntentByID(options) {
+    const { platform, id, ...rest } = options;
+    return {
+        ...rest,
+        $kind: "GroupingPageIntent",
+        id: normalizeAdamID(id),
+        platform: normalizePreviewPlaform(platform),
+    };
+}
+//# sourceMappingURL=grouping-page-intent.js.map

+ 17 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/product-page-intent.js

@@ -0,0 +1,17 @@
+import { normalizeAdamID } from "../util";
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeProductPageIntent(opts) {
+    const { id, platform, ppid, lic, ...rest } = opts;
+    return {
+        ...rest,
+        $kind: "ProductPageIntent",
+        id: normalizeAdamID(id),
+        platform: normalizePreviewPlaform(platform),
+        ppid,
+        lic,
+    };
+}
+export function isProductPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === "ProductPageIntent";
+}
+//# sourceMappingURL=product-page-intent.js.map

+ 16 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/room-page-intent.js

@@ -0,0 +1,16 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+import { normalizeAdamID } from "../util";
+const ROOM_PAGE_INTENT_KIND = "RoomPageIntent";
+export function makeRoomPageIntent(opts) {
+    const { platform, id, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        id: normalizeAdamID(id),
+        $kind: ROOM_PAGE_INTENT_KIND,
+    };
+}
+export function isRoomPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === ROOM_PAGE_INTENT_KIND;
+}
+//# sourceMappingURL=room-page-intent.js.map

+ 11 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/routable-arcade-see-all-page-intent.js

@@ -0,0 +1,11 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+const ROUTABLE_ARCADE_SEE_ALL_PAGE_INTENT_KIND = "RoutableArcadeSeeAllPageIntent";
+export function makeRoutableArcadeSeeAllPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: "RoutableArcadeSeeAllPageIntent",
+    };
+}
+//# sourceMappingURL=routable-arcade-see-all-page-intent.js.map

+ 13 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/routable-article-page-intent.js

@@ -0,0 +1,13 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+import { normalizeAdamID } from "../util";
+const ROUTABLE_ARTICLE_PAGE_INTENT_KIND = "RoutableArticlePageIntent";
+export function makeRoutableArticlePageIntent(opts) {
+    const { id, platform, ...rest } = opts;
+    return {
+        ...rest,
+        id: normalizeAdamID(id),
+        platform: normalizePreviewPlaform(platform),
+        $kind: ROUTABLE_ARTICLE_PAGE_INTENT_KIND,
+    };
+}
+//# sourceMappingURL=routable-article-page-intent.js.map

+ 4 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/routable-intent.js

@@ -0,0 +1,4 @@
+export function isRoutableIntent(intent) {
+    return "storefront" in intent && "language" in intent;
+}
+//# sourceMappingURL=routable-intent.js.map

+ 10 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/routable-today-page-intent.js

@@ -0,0 +1,10 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeRoutableTodayPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: "RoutableTodayPageIntent",
+    };
+}
+//# sourceMappingURL=routable-today-page-intent.js.map

+ 19 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/search-results-page-intent.js

@@ -0,0 +1,19 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+export function makeSearchResultsPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: "SearchResultsPageIntent",
+    };
+}
+export function makeSearchResultsPageIntentFromURLParams(opts) {
+    return makeSearchResultsPageIntent({
+        ...opts,
+        origin: "userText",
+    });
+}
+export function isSearchResultsPageIntent(intent) {
+    return intent.$kind === "SearchResultsPageIntent";
+}
+//# sourceMappingURL=search-results-page-intent.js.map

+ 14 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/search/search-landing-page-intent.js

@@ -0,0 +1,14 @@
+import { normalizePreviewPlaform } from "../../models/preview-platform";
+const SEARCH_LANDING_PAGE_INTENT_KIND = "SearchLandingPageIntent";
+export function makeSearchLandingPageIntent(opts) {
+    const { platform, ...rest } = opts;
+    return {
+        ...rest,
+        platform: normalizePreviewPlaform(platform),
+        $kind: SEARCH_LANDING_PAGE_INTENT_KIND,
+    };
+}
+export function isSearchLandingPageIntent(intent) {
+    return (intent === null || intent === void 0 ? void 0 : intent.$kind) === SEARCH_LANDING_PAGE_INTENT_KIND;
+}
+//# sourceMappingURL=search-landing-page-intent.js.map

+ 13 - 0
node_modules/@jet-app/app-store/tmp/src/api/intents/see-all-page-intent.js

@@ -0,0 +1,13 @@
+import { normalizePreviewPlaform } from "../models/preview-platform";
+import { normalizeAdamID } from "../util";
+export const SEE_ALL_TYPES = ["reviews", "customers-also-bought-apps", "developer-other-apps"];
+export function makeSeeAllPageIntent(opts) {
+    return {
+        ...opts,
+        "$kind": "SeeAllPageIntent",
+        "id": normalizeAdamID(opts.id),
+        "platform": normalizePreviewPlaform(opts.platform),
+        "see-all": opts["see-all"],
+    };
+}
+//# sourceMappingURL=see-all-page-intent.js.map

+ 37 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/accessibility.js

@@ -0,0 +1,37 @@
+import * as models from "./index";
+/**
+ * @public
+ * A model that represents an accessibility feature of a product.
+ */
+export class AccessibilityFeature extends models.Model {
+    constructor(title, description, artwork) {
+        super();
+        this.title = title;
+        this.description = description;
+        this.artwork = artwork;
+    }
+}
+/**
+ * @public
+ * A model that represents a set of accessibility features of a product.
+ */
+export class AccessibilityFeatures extends models.ViewModel {
+    constructor(title, artwork, features) {
+        super();
+        this.title = title;
+        this.artwork = artwork;
+        this.features = features;
+    }
+}
+/**
+ * @public
+ * A model that represents a paragraph of linkable text, displayed in the accessibility section.
+ */
+export class AccessibilityParagraph extends models.ViewModel {
+    constructor(text, actions) {
+        super();
+        this.text = text;
+        this.actions = actions;
+    }
+}
+//# sourceMappingURL=accessibility.js.map

+ 525 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/actions/actions.js

@@ -0,0 +1,525 @@
+/**
+ * Created by km on 2/13/17.
+ */
+import { isSome } from "@jet/environment/types/optional";
+import * as base from "../base";
+import { Action } from "./base-action";
+import { ActionMetrics } from "../metrics/metrics";
+/** @public */
+export class TabChangeAction extends Action {
+    constructor(navigationTab) {
+        super("TabChangeAction");
+        this.navigationTab = navigationTab;
+        this.actions = [];
+        this.popToRoot = false;
+    }
+}
+/** @public */
+export class TabBadgeAction extends Action {
+    constructor(navigationTab, text) {
+        super("TabBadgeAction");
+        this.navigationTab = navigationTab;
+        this.text = text;
+    }
+}
+/** @public */
+export class ExternalUrlAction extends Action {
+    constructor(url, isSensitive = true, actionMetrics = new ActionMetrics()) {
+        super("ExternalUrlAction", actionMetrics);
+        this.url = url;
+        this.isSensitive = isSensitive;
+    }
+}
+/** @public */
+export class CompoundAction extends Action {
+    constructor(actions) {
+        super("CompoundAction");
+        const sanitizedActions = [];
+        for (const action of actions) {
+            if (isSome(action.actionMetrics)) {
+                this.actionMetrics.addManyMetricsData(action.actionMetrics.data);
+                Object.assign(this.actionMetrics.custom, action.actionMetrics.custom);
+                action.actionMetrics.clearAll();
+            }
+            sanitizedActions.push(action);
+        }
+        this.actions = sanitizedActions;
+    }
+}
+/** @public */
+export class OfferAction extends Action {
+    constructor(title, adamId, purchaseConfiguration, parentAdamId) {
+        super("OfferAction");
+        this.title = title;
+        this.adamId = adamId;
+        this.parentAdamId = parentAdamId;
+        this.purchaseConfiguration = purchaseConfiguration;
+        if (purchaseConfiguration) {
+            this.bundleId = purchaseConfiguration.bundleId;
+            this.lineItem = purchaseConfiguration.lineItem;
+        }
+        this.includeBetaApps = false;
+    }
+}
+/** @public */
+export class OfferConfirmationAction extends Action {
+    constructor(buyAction, confirmationInitiationAction) {
+        super("OfferConfirmationAction");
+        this.buyAction = buyAction;
+        this.confirmationInitiationAction = confirmationInitiationAction;
+    }
+}
+/** @public */
+export class OfferAlertAction extends Action {
+    constructor() {
+        super("OfferAlertAction");
+        this.title = null;
+        this.message = null;
+        this.footerMessage = null;
+        this.isCancelable = true;
+        this.shouldCheckForAvailableDiskSpace = false;
+        this.checkRestrictionsForContentRating = null;
+        this.remoteControllerRequirement = "NO_BADGE";
+        this.spatialControllerRequirement = null;
+        this.shouldCheckForGameController = false;
+        this.shouldIncludeActiveAccountInFooterMessage = false;
+        this.shouldPromptForConfirmation = false;
+        this.completionAction = null;
+    }
+}
+/** @public */
+export class CancelPreorderAction extends Action {
+    constructor(preorderAdamId, isArcade) {
+        super("CancelPreorderAction");
+        this.preorderAdamId = preorderAdamId;
+        this.isArcade = isArcade;
+    }
+}
+/** @public */
+export class InAppPurchaseAction extends Action {
+    constructor(productIdentifier, appAdamId, appBundleId, installRequiredAction, minimumShortVersionSupportingInAppPurchaseFlow) {
+        super("InAppPurchaseAction");
+        this.productIdentifier = productIdentifier;
+        this.appAdamId = appAdamId;
+        this.appBundleId = appBundleId;
+        this.installRequiredAction = installRequiredAction;
+        this.minimumShortVersionSupportingInAppPurchaseFlow = minimumShortVersionSupportingInAppPurchaseFlow;
+    }
+}
+/** @public */
+export class OfferStateAction extends Action {
+    constructor(adamId, defaultAction) {
+        super("OfferStateAction");
+        this.title = defaultAction.title;
+        this.adamId = adamId;
+        this.defaultAction = defaultAction;
+        this.includeBetaApps = false;
+    }
+}
+/** @public */
+export class OpenAppAction extends Action {
+    constructor(adamId, destination = "app") {
+        super("OpenAppAction");
+        this.adamId = adamId;
+        this.destination = destination;
+    }
+}
+/** @public */
+export class OpenGamesUIAction extends Action {
+    constructor(target) {
+        super("OpenGamesUIAction");
+        this.target = target;
+    }
+}
+/** @public
+ * Purchase action that contains multiple offers for a set of Arcade games.
+ * It is used for "Get all" button in Arcade Download/Starter Pack feature
+ * to make a single purchase via App Store Daemon.
+ * The action implementation doesn't execute its `offerActions`
+ * but uses them as data objects, extracting required parameters.
+ * */
+export class ArcadePackOfferAction extends Action {
+    constructor(offerActions) {
+        super("ArcadePackOfferAction");
+        this.offerActions = offerActions;
+    }
+}
+/** @public
+ * An action representing the "selection" of an app, from the offer button.
+ * The intention is to communicate this app was selected to another process, not actually
+ * purchase/download/etc.
+ * Currently used for the browser selection flow.
+ */
+export class SelectAppAction extends Action {
+    constructor(adamId) {
+        super("SelectAppAction");
+        this.adamId = adamId;
+    }
+}
+/** @public */
+export class HttpAction extends Action {
+    constructor(url) {
+        super("HttpAction");
+        this.url = url;
+        this.method = "GET";
+        this.headers = {};
+        this.body = null;
+        this.isStoreRequest = false;
+        this.needsAuthentication = false;
+        this.needsMediaToken = false;
+        this.retryCount = 0;
+        this.disableCache = false;
+        this.successAction = null;
+        this.failureAction = null;
+    }
+}
+/** @public */
+export class HttpTemplateParameter {
+    constructor(key, target, inputType, title) {
+        this.key = key;
+        this.target = target;
+        this.inputType = inputType;
+        this.title = title;
+        this.isRequired = true;
+        this.maximumLength = null;
+    }
+}
+/** @public */
+export class HttpTemplateAction extends Action {
+    constructor(url) {
+        super("HttpTemplateAction");
+        this.message = null;
+        this.url = url;
+        this.method = "GET";
+        this.headers = {};
+        this.body = null;
+        this.bodyDictionary = {};
+        this.parameters = [];
+        this.isStoreRequest = false;
+        this.needsAuthentication = false;
+        this.needsMediaToken = false;
+        this.retryCount = 0;
+        this.disableCache = false;
+        this.successAction = null;
+        this.failureAction = null;
+    }
+}
+/** @public */
+export class RateAction extends HttpTemplateAction {
+}
+export class ShowSettingsAction extends Action {
+    constructor() {
+        super("ShowSettingsAction");
+    }
+}
+/** @public */
+export class WriteReviewAction extends Action {
+    constructor(adamId, url) {
+        super("WriteReviewAction");
+        this.adamId = adamId;
+        this.url = url;
+    }
+}
+/** @public */
+export class PageTabChangeAction extends Action {
+    constructor(selectedTabId, title, actionClass) {
+        super(actionClass !== null && actionClass !== void 0 ? actionClass : "PageTabChangeAction");
+        this.selectedTabId = selectedTabId;
+        this.title = title;
+    }
+}
+/** @public */
+export class SearchPageSegmentChangeAction extends PageTabChangeAction {
+    constructor(selectedTabId, selectedTabTitle, switchToOtherSegmentText) {
+        super(selectedTabId, "SearchPageSegmentChangeAction");
+        this.switchToOtherSegmentText = switchToOtherSegmentText;
+        this.title = selectedTabTitle;
+    }
+}
+/** @public */
+export class GameCenterDashboardAction extends Action {
+    constructor() {
+        super("GameCenterDashboardAction");
+    }
+}
+/** @public */
+export class SheetAction extends Action {
+    constructor(actions) {
+        super("SheetAction");
+        this.actions = actions;
+        this.isCancelable = false;
+        this.cancelTitle = null;
+        this.message = null;
+        this.style = "default";
+        this.isCustom = false;
+        this.destructiveActionIndex = null;
+    }
+}
+/** @public */
+export class AlertAction extends Action {
+    constructor(style) {
+        super("AlertAction");
+        this.style = style;
+        this.title = null;
+        this.message = null;
+        this.isCancelable = false;
+        this.cancelTitle = null;
+        this.cancelAction = null;
+        this.buttonActions = [];
+        this.buttonTitles = [];
+        this.destructiveActionIndex = null;
+        this.imageName = null;
+    }
+}
+/** @public */
+export class ScrollingAlertAction extends Action {
+    constructor(title, message) {
+        super("ScrollingAlertAction");
+        this.title = title;
+        this.message = message;
+    }
+}
+/**
+ * @public
+ * Describes a unique activity as used in a Share Sheet.
+ */
+export class ShareSheetActivity extends base.ViewModel {
+    constructor(activityType, action) {
+        super();
+        this.activityType = activityType;
+        this.action = action;
+    }
+}
+/** @public */
+export class ShareSheetAction extends Action {
+    constructor(data, activities, style = "expanded") {
+        super("ShareSheetAction");
+        this.data = data;
+        this.activities = activities;
+        this.shareSheetStyle = style;
+    }
+}
+/** @public */
+export class ReportConcernAction extends Action {
+    constructor(reasons) {
+        super("ReportConcernAction");
+        this.reasons = reasons;
+    }
+}
+/** @public */
+export class ReviewSummaryReportConcernAction extends Action {
+    constructor(concerns, title, explanation, sendAction) {
+        super("ReviewSummaryReportConcernAction");
+        this.concerns = concerns;
+        this.title = title;
+        this.explanation = explanation;
+        this.sendAction = sendAction;
+    }
+}
+/** @public */
+export class ProductPageScrollAction extends Action {
+    constructor(section, clicksOnScroll) {
+        super("ProductPageScrollAction");
+        this.section = section;
+        this.clicksOnScroll = clicksOnScroll;
+    }
+}
+/** @public */
+export class ArcadeAction extends Action {
+    constructor(productIdentifier, appAdamId, subscriptionToken, postSubscribeAction) {
+        super("ArcadeAction");
+        this.productIdentifier = productIdentifier;
+        this.appAdamId = appAdamId;
+        this.postSubscribeAction = postSubscribeAction;
+        this.subscriptionToken = subscriptionToken;
+    }
+}
+export class FamilyCircleAction extends Action {
+    constructor(clientName, eventType, additionalParameters) {
+        super("FamilyCircleAction");
+        this.clientName = clientName;
+        this.eventType = eventType;
+        this.additionalParameters = additionalParameters;
+    }
+}
+/** @public */
+export class BlankAction extends Action {
+    constructor() {
+        super("BlankAction");
+    }
+}
+/** @public */
+export class SearchAdAction extends Action {
+    constructor(action) {
+        super("SearchAdAction");
+        this.action = action;
+    }
+}
+/** @public */
+export class RateLimitedAction extends Action {
+    constructor(actionKey, primaryAction) {
+        super("RateLimitedAction");
+        this.actionKey = actionKey;
+        this.primaryAction = primaryAction;
+    }
+}
+/** @public */
+export class ArcadeSubscriptionStateAction extends Action {
+    constructor(notSubscribedAction, purchasingAction, subscribedAction, unknownAction) {
+        super("ArcadeSubscriptionStateAction");
+        this.notSubscribedAction = notSubscribedAction;
+        this.purchasingAction = purchasingAction;
+        this.subscribedAction = subscribedAction;
+        this.unknownAction = unknownAction;
+    }
+}
+/**
+ * @public
+ * An action for changing the page segment in the Arcade See All Games page.
+ */
+export class ArcadeSeeAllGamesPageSegmentChangeAction extends Action {
+    constructor(facet, selectedOption) {
+        super("ArcadeSeeAllGamesPageSegmentChangeAction");
+        this.facet = facet;
+        this.selectedOption = selectedOption;
+    }
+}
+/** @public */
+export class GameCenterPlayerProfileAction extends Action {
+    constructor(playerId) {
+        super("GameCenterPlayerProfileAction");
+        this.playerId = playerId;
+    }
+}
+/** @public */
+export class GameCenterAchievementsAction extends Action {
+    constructor(bundleId) {
+        super("GameCenterAchievementsAction");
+        this.bundleId = bundleId;
+    }
+}
+/** @public */
+export class LegacyGameCenterInvitePlayerAction extends Action {
+    constructor(contactId) {
+        super("GameCenterInvitePlayerAction");
+        this.contactId = contactId;
+    }
+}
+/** @public */
+export class GameCenterInvitePlayerAction extends Action {
+    constructor(invitationType) {
+        super("GameCenterInvitePlayerAction");
+        this.invitationType = invitationType;
+    }
+}
+/** @public */
+export class GameCenterDenylistPlayerAction extends Action {
+    constructor(contactId) {
+        super("GameCenterDenylistPlayerAction");
+        this.contactId = contactId;
+    }
+}
+/** @public */
+export class PageFacetsChangeAction extends Action {
+    constructor(filterParameter) {
+        super("PageFacetsChangeAction");
+        this.filterParameter = filterParameter;
+    }
+}
+/** @public */
+export class EngagementToggleAction extends Action {
+    constructor(identifier, value) {
+        super("EngagementToggleAction");
+        this.identifier = identifier;
+        this.value = value;
+    }
+}
+/** @public */
+export class ShelfBasedPageScrollAction extends Action {
+    constructor(shelfId, notPurchasedShelfId, purchasedShelfId, adamId, index, clicksOnScroll) {
+        super("ShelfBasedPageScrollAction");
+        this.shelfId = shelfId;
+        this.notPurchasedShelfId = notPurchasedShelfId;
+        this.purchasedShelfId = purchasedShelfId;
+        this.adamId = adamId;
+        this.index = index;
+        this.clicksOnScroll = clicksOnScroll;
+    }
+}
+/** @public */
+export class InvalidateAllWidgetsAction extends Action {
+    constructor() {
+        super("InvalidateAllWidgetsAction");
+    }
+}
+/** @public */
+export class AppLaunchTrampolineAction extends Action {
+    constructor(bundleId, payloadUrl, fallbackAction) {
+        super("AppLaunchTrampolineAction");
+        this.bundleId = bundleId;
+        this.payloadUrl = payloadUrl;
+        this.fallbackAction = fallbackAction;
+    }
+}
+/** @public */
+export class CreateCalendarEventAction extends Action {
+    constructor(startDate, endDate, isAllDay, name, location, notes, url, notAuthorizedAction, availability) {
+        super("CreateCalendarEventAction");
+        this.startDate = startDate;
+        this.endDate = endDate;
+        this.isAllDay = isAllDay;
+        this.name = name;
+        this.location = location;
+        this.notes = notes;
+        this.url = url;
+        this.notAuthorizedAction = notAuthorizedAction;
+        this.availability = availability;
+    }
+}
+/** @public
+ *
+ */
+export class CopyTextAction extends Action {
+    constructor(text) {
+        super("CopyTextAction");
+        this.text = text;
+    }
+}
+/** @public
+ *
+ */
+export class ClearAppUsageDataAction extends Action {
+    constructor() {
+        super("ClearAppUsageDataAction");
+    }
+}
+/** @public
+ * An action describing a request to delete all recent searches from on-device storage.
+ */
+export class ClearSearchHistoryAction extends Action {
+    constructor() {
+        super("ClearSearchHistoryAction");
+    }
+}
+/**
+ * @public
+ * An action describing an ad interaction, that passes data on to native ad instrumentation
+ * via Ad Platforms frameworks.
+ */
+export class AdInteractionAction extends Action {
+    constructor(adActionMetrics) {
+        super("AdInteractionAction");
+        this.adActionMetrics = adActionMetrics;
+    }
+}
+/**
+ * @public
+ * An action describes a begin of crossfire referral flow, that will pass the `ReferrerData` on to native to mark the beginning of crossfire flow.
+ */
+export class CrossfireReferralAction extends Action {
+    constructor(referrerData) {
+        super("CrossfireReferralAction");
+        this.referrerData = referrerData;
+    }
+}
+//# sourceMappingURL=actions.js.map

+ 15 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/actions/base-action.js

@@ -0,0 +1,15 @@
+import * as base from "../base";
+import { ActionMetrics } from "../metrics/metrics";
+/** @public */
+export class Action extends base.ViewModel {
+    constructor(actionClass, actionMetrics = new ActionMetrics()) {
+        super();
+        this.title = null;
+        this.artwork = null;
+        this.presentationStyle = [];
+        this.actionClass = actionClass;
+        this.$kind = actionClass;
+        this.actionMetrics = actionMetrics;
+    }
+}
+//# sourceMappingURL=base-action.js.map

+ 26 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/actions/flow-action.js

@@ -0,0 +1,26 @@
+import { Action } from "./base-action";
+/** @public */
+export class FlowBackAction extends Action {
+    constructor(dismissal) {
+        super("FlowBackAction");
+        this.dismissal = dismissal;
+    }
+}
+/** @public */
+export class FlowAction extends Action {
+    constructor(flowPage, pageUrl) {
+        super("FlowAction");
+        this.$kind = "flowAction";
+        this.page = flowPage;
+        this.pageUrl = pageUrl;
+        this.pageData = null;
+        this.referrerData = undefined;
+        this.presentationContext = "infer";
+        this.animationBehavior = "infer";
+        this.origin = "inapp";
+    }
+}
+export function isFlowAction(action) {
+    return action.$kind === "flowAction";
+}
+//# sourceMappingURL=flow-action.js.map

+ 26 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/ad-incidents.js

@@ -0,0 +1,26 @@
+/**
+ * Models for Ad Incidents that may occur while building model.
+ */
+import { Model } from "./base";
+/**
+ * @public
+ * Base Incident Type
+ */
+export class AdIncident extends Model {
+    constructor(incidentType) {
+        super();
+        this.incidentType = incidentType;
+    }
+}
+/**
+ * @public
+ * Type of Ad Incident where Ad was discarded due to some reason
+ */
+export class DiscardAdIncident extends AdIncident {
+    constructor(instanceId, reason) {
+        super("discard");
+        this.instanceId = instanceId;
+        this.reason = reason;
+    }
+}
+//# sourceMappingURL=ad-incidents.js.map

+ 50 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/annotation.js

@@ -0,0 +1,50 @@
+import * as base from "./base";
+/**
+ * The `Annotation` model describes a category of information about an app,
+ * such as supported languages, app size, content ratings, in-app-purchase
+ * info, etc.
+ *
+ * `Annotations` always have a title and summary, and most also have an `items`
+ * array of `AnnotationItem`s with more fine-grained details.
+ *
+ * @public
+ */
+export class Annotation extends base.Model {
+    constructor(title, items, summary, linkAction) {
+        super();
+        this.title = title;
+        this.summary = summary;
+        this.items = items;
+        this.items_V3 = [];
+        this.shouldAlwaysPresentExpanded = false;
+        this.linkAction = linkAction;
+    }
+}
+/**
+ * A single item used to show more details in an `Annotation`. This could be an
+ * In-App Purchase, supported language list, a link to an editorial item, etc.
+ * @public
+ */
+export class AnnotationItem extends base.Model {
+    constructor(text, options = {}) {
+        super();
+        this.text = text;
+        this.heading = options.heading;
+        this.headingArtworks = options.headingArtworks;
+        this.listText = options.listText;
+        this.textPairs = options.textPairs;
+    }
+}
+/**
+ * Used on tvOS to visually group related `Annotation` objects into a column.
+ * @public
+ */
+export class AnnotationGroup extends base.Model {
+    constructor(title, annotations, forceExpanded) {
+        super();
+        this.title = title;
+        this.annotations = annotations;
+        this.forceExpanded = forceExpanded;
+    }
+}
+//# sourceMappingURL=annotation.js.map

+ 186 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/app-promotions.js

@@ -0,0 +1,186 @@
+import * as base from "./base";
+import * as models from "./index";
+import * as metrics from "./metrics/metrics";
+/** @public */
+export class AppEventFormattedDate extends models.Model {
+    constructor(showLiveIndicator, displayFromDate, displayText, countdownToDate, countdownStringKey) {
+        super();
+        this.showLiveIndicator = showLiveIndicator;
+        this.displayFromDate = displayFromDate;
+        this.displayText = displayText;
+        this.countdownToDate = countdownToDate;
+        this.countdownStringKey = countdownStringKey;
+    }
+}
+/** @public */
+export var AppEventBadgeKind;
+(function (AppEventBadgeKind) {
+    AppEventBadgeKind["available"] = "available";
+    AppEventBadgeKind["happening"] = "happening";
+    AppEventBadgeKind["live"] = "live";
+})(AppEventBadgeKind || (AppEventBadgeKind = {}));
+export var AppPromotionType;
+(function (AppPromotionType) {
+    AppPromotionType["AppEvent"] = "appEvent";
+    AppPromotionType["ContingentOffer"] = "contingentOffer";
+    AppPromotionType["OfferItem"] = "offerItem";
+})(AppPromotionType || (AppPromotionType = {}));
+/** @public */
+export class AppPromotion extends base.ViewModel {
+    constructor(promotionType) {
+        super();
+        this.promotionType = promotionType;
+    }
+}
+/** @public */
+export class AppEvent extends AppPromotion {
+    constructor(appEventId, moduleArtwork, moduleVideo, title, subtitle, detail, startDate, endDate, appEventBadgeKind, kind, requirements, lockup, hideLockupWhenNotInstalled, formattedDates, mediaOverlayStyle, includeBorderInDarkMode) {
+        super(AppPromotionType.AppEvent);
+        this.appEventId = appEventId;
+        this.moduleArtwork = moduleArtwork;
+        this.moduleVideo = moduleVideo;
+        this.title = title;
+        this.subtitle = subtitle;
+        this.detail = detail;
+        this.startDate = startDate;
+        this.endDate = endDate;
+        this.kind = kind;
+        this.appEventBadgeKind = appEventBadgeKind;
+        this.requirements = requirements;
+        this.lockup = lockup;
+        this.hideLockupWhenNotInstalled = hideLockupWhenNotInstalled;
+        this.formattedDates = formattedDates;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.includeBorderInDarkMode = includeBorderInDarkMode;
+        this.clickAction = null;
+    }
+}
+/** @public */
+export class AppEventDetailPage extends models.Model {
+    constructor(appEvent, artwork, video, shareAction, mediaOverlayStyle, includeBorderInDarkMode) {
+        super();
+        this.appEvent = appEvent;
+        this.artwork = artwork;
+        this.video = video;
+        this.shareAction = shareAction;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.includeBorderInDarkMode = includeBorderInDarkMode;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+    }
+}
+/**
+ * Determines if a {@linkcode shelves.Shelf} is actually a {@linkcode AppEventDetailShelf}
+ */
+export function isAppEventDetailShelf(shelf) {
+    return shelf.contentType === "appEventDetail";
+}
+/**
+ * `Shelf` definition that wraps a single {@linkcode AppEventDetailPage}
+ *
+ * This is used to power the "web" client UI for an `app-event` detail page
+ *
+ * @public
+ */
+export class AppEventDetailShelf extends models.Shelf {
+    constructor(detailPage) {
+        super("appEventDetail", null, [detailPage]);
+    }
+}
+/** @public */
+export class AppEventNotificationConfig extends models.Model {
+    constructor(appEventId, title, detail, artworkUrl, displayTime, scheduledAction, notAuthorizedAction, failureAction, destinationUrl, scheduleClickEvent, cancelScheduleClickEvent) {
+        super();
+        this.appEventId = appEventId;
+        this.title = title;
+        this.detail = detail;
+        this.artworkUrl = artworkUrl;
+        this.displayTime = displayTime;
+        this.scheduledAction = scheduledAction;
+        this.notAuthorizedAction = notAuthorizedAction;
+        this.failureAction = failureAction;
+        this.destinationUrl = destinationUrl;
+        this.scheduleClickEvent = scheduleClickEvent;
+        this.cancelScheduleClickEvent = cancelScheduleClickEvent;
+    }
+}
+/** @public */
+export class ContingentOffer extends AppPromotion {
+    constructor(backgroundArtwork, mediaOverlayStyle, isStreamlinedBuy, learnMoreTitle, titleFormatted, subtitle, description, label, badge, additionalInfo, trunkAppIcon, offerLockup) {
+        super(AppPromotionType.ContingentOffer);
+        this.backgroundArtwork = backgroundArtwork;
+        this.isStreamlinedBuy = isStreamlinedBuy;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.titleFormatted = titleFormatted;
+        this.subtitle = subtitle;
+        this.additionalInfo = additionalInfo;
+        this.description = description;
+        this.label = label;
+        this.badge = badge;
+        this.offerLockup = offerLockup;
+        this.trunkAppIcon = trunkAppIcon;
+        this.learnMoreTitle = learnMoreTitle;
+        this.clickAction = null;
+    }
+}
+/** @public */
+export class AppPromotionDetailPage extends base.ViewModel {
+    constructor(promotionType) {
+        super();
+        this.promotionType = promotionType;
+    }
+}
+/** @public */
+export class ContingentOfferDetailPage extends AppPromotionDetailPage {
+    constructor(contingentOffer, artwork, mediaOverlayStyle) {
+        super(AppPromotionType.ContingentOffer);
+        this.contingentOffer = contingentOffer;
+        this.artwork = artwork;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+        this.learnMoreActionMetrics = new metrics.ActionMetrics();
+        this.backButtonActionMetrics = new metrics.ActionMetrics();
+        this.closeButtonActionMetrics = new metrics.ActionMetrics();
+    }
+}
+/** @public
+ *
+ *
+ */
+export class OfferItem extends AppPromotion {
+    constructor(moduleArtwork, moduleVideo, mediaOverlayStyle, isStreamlinedBuy, titleFormatted, expiryDateFormatted, subtitle, description, badge, endDate, iapArtwork, offerLockup) {
+        super(AppPromotionType.OfferItem);
+        this.moduleArtwork = moduleArtwork;
+        this.moduleVideo = moduleVideo;
+        this.isStreamlinedBuy = isStreamlinedBuy;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.titleFormatted = titleFormatted;
+        this.description = description;
+        this.badge = badge;
+        this.offerLockup = offerLockup;
+        this.subtitle = subtitle;
+        this.endDate = endDate;
+        this.expiryDateFormatted = expiryDateFormatted;
+        this.iapArtwork = iapArtwork;
+        this.clickAction = null;
+    }
+}
+/** @public */
+export class OfferItemDetailPage extends AppPromotionDetailPage {
+    constructor(offerItem, artwork, video, mediaOverlayStyle, includeBorderInDarkMode, learnMoreTitle, additionalInfo) {
+        super(AppPromotionType.OfferItem);
+        this.offerItem = offerItem;
+        this.artwork = artwork;
+        this.learnMoreTitle = learnMoreTitle;
+        this.video = video;
+        this.mediaOverlayStyle = mediaOverlayStyle;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.additionalInfo = additionalInfo;
+        this.pageRenderMetrics = {};
+        this.learnMoreActionMetrics = new metrics.ActionMetrics();
+        this.backButtonActionMetrics = new metrics.ActionMetrics();
+        this.closeButtonActionMetrics = new metrics.ActionMetrics();
+    }
+}
+//# sourceMappingURL=app-promotions.js.map

+ 18 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/arcade-upsell.js

@@ -0,0 +1,18 @@
+/**
+ * Created by Jellenbogen on 11/19/19.
+ */
+import * as base from "./base";
+/** @public */
+export class UpsellBreakout extends base.ViewModel {
+    constructor(details, offerDisplayProperties, displayProperties, offerButtonAction, buttonCallToAction, artwork, video) {
+        super();
+        this.details = details;
+        this.displayProperties = displayProperties;
+        this.offerButtonAction = offerButtonAction;
+        this.buttonCallToAction = buttonCallToAction;
+        this.offerDisplayProperties = offerDisplayProperties;
+        this.artwork = artwork;
+        this.video = video;
+    }
+}
+//# sourceMappingURL=arcade-upsell.js.map

+ 240 - 0
node_modules/@jet-app/app-store/tmp/src/api/models/arcade.js

@@ -0,0 +1,240 @@
+import * as models from "./index";
+import * as metrics from "./metrics/metrics";
+export function marketingItemContextFromString(context) {
+    var _a, _b;
+    if (preprocessor.GAMES_TARGET) {
+        switch (context) {
+            case "generic":
+                return "gameCenterGeneric";
+            case "groupingLockup":
+                return "gameCenterLockup";
+            case "arcadeTabHeader":
+                return "gameCenterEditorialPageHeader";
+            case "productPage":
+                return "gameCenterProductPage";
+            case "arcadeComingSoon":
+                return "gameCenterComingSoon";
+            case "gameCenterEditorialPage": // TBD
+                return "gameCenterEditorialPage";
+            default:
+                return (_a = context) !== null && _a !== void 0 ? _a : "gameCenterGeneric";
+        }
+    }
+    switch (context) {
+        case "askToBuy":
+            return "arcadeAskToBuy";
+        case "generic":
+            return "arcadeGeneric";
+        case "groupingLockup":
+            return "arcadeGroupingLockup";
+        case "launchRepair":
+            return "arcadeLaunchRepair";
+        case "productPage":
+            return "arcadeProductPage";
+        case "topShelfATV":
+            return "arcadeTopShelfATV";
+        case "topShelfATVClickThrough":
+            return "arcadeTopShelfATVClickThrough";
+        case "editorialItem":
+            return "arcadeTodayCard";
+        case "editorialItemCanvas":
+            return "arcadeStoryCanvas";
+        case "arcadeComingSoon":
+            return "arcadeComingSoon";
+        case "arcadeTabHeader":
+            return "arcadeTabHeader";
+        case "arcadeTabNavBar":
+            return "arcadeTabNavBar";
+        default:
+            return (_b = context) !== null && _b !== void 0 ? _b : "arcadeGeneric";
+    }
+}
+export function isContextualUpsellContext(context) {
+    if (preprocessor.GAMES_TARGET) {
+        switch (context) {
+            case "gameCenterLockup":
+            case "gameCenterProductPage":
+                return true;
+            default:
+                return false;
+        }
+    }
+    switch (context) {
+        case "arcadeGroupingLockup":
+        case "arcadeProductPage":
+        case "productPage":
+        case "groupingLockup":
+            return true;
+        default:
+            return false;
+    }
+}
+/** @public */
+export class ArcadeSubscribePage extends models.Model {
+    constructor(details, dismissButtonTitle, offerButtonAction, offerDisplayProperties) {
+        super();
+        this.details = details;
+        this.dismissButtonTitle = dismissButtonTitle;
+        this.offerButtonAction = offerButtonAction;
+        this.offerDisplayProperties = offerDisplayProperties;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+    }
+}
+/** @public */
+export class ArcadeWelcomeItem extends models.Model {
+    constructor(headline, body, artwork) {
+        super();
+        this.headline = headline;
+        this.body = body;
+        this.artwork = artwork;
+    }
+}
+/** @public */
+export class ArcadeWelcomeContent extends models.Model {
+    constructor(title, subtitle, items, continueAction, familyAction) {
+        super();
+        this.title = title;
+        this.subtitle = subtitle;
+        this.items = items;
+        this.continueAction = continueAction;
+        this.familyAction = familyAction;
+    }
+}
+/** @public */
+export class ArcadeWelcomePage extends models.Model {
+    constructor(individualContent, familyMemberContent) {
+        super();
+        this.individualContent = individualContent;
+        this.familyMemberContent = familyMemberContent;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+    }
+}
+/** @public */
+export class MarketingItemRequestInfo extends models.Model {
+    constructor(serviceType, placement, metricsTopic, seed, clientOptions) {
+        super();
+        this.serviceType = serviceType;
+        this.placement = placement;
+        this.seed = seed;
+        this.clientOptions = clientOptions;
+        this.metricsOverlay = { topic: metricsTopic };
+    }
+}
+/** @public */
+export class DynamicUIRequestInfo extends models.Model {
+    constructor(metricsTopic, clientOptions) {
+        super();
+        this.clientOptions = clientOptions;
+        this.metricsOverlay = { topic: metricsTopic };
+    }
+}
+/** @public */
+export class UpsellGridContent extends models.Model {
+    constructor(primaryIcon, icons) {
+        super();
+        this.primaryIcon = primaryIcon;
+        this.icons = icons;
+    }
+}
+/** @public */
+export class AppStoreEngagementTask extends models.Model {
+    constructor(action) {
+        super();
+        this.action = action;
+    }
+}
+/** @public
+ * A model for game category button on Arcade download pack screen.
+ */
+export class ArcadeDownloadPackCategory extends models.ViewModel {
+    constructor(id, title, artwork, gradientStartColor, gradientEndColor) {
+        super();
+        this.id = id;
+        this.title = title;
+        this.artwork = artwork;
+        this.gradientStartColor = gradientStartColor;
+        this.gradientEndColor = gradientEndColor;
+        this.selectActionMetrics = new models.ActionMetrics();
+        this.deselectActionMetrics = new models.ActionMetrics();
+    }
+}
+/** @public
+ * Initial Arcade download pack screen with game categories to select by user.
+ */
+export class ArcadeDownloadPackCategoriesPage extends models.Model {
+    constructor(title, categories, maxNumberOfCategoriesToChoose, maxNumberOfCategoriesToChooseTemplate, numberOfChosenCategoriesTemplate, primaryAction, dismissAction) {
+        super();
+        this.title = title;
+        this.categories = categories;
+        this.maxNumberOfCategoriesToChoose = maxNumberOfCategoriesToChoose;
+        this.maxNumberOfCategoriesToChooseTemplate = maxNumberOfCategoriesToChooseTemplate;
+        this.numberOfChosenCategoriesTemplate = numberOfChosenCategoriesTemplate;
+        this.primaryAction = primaryAction;
+        this.dismissAction = dismissAction;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+    }
+}
+/** @public
+ * A lockup model for Arcade download suggestions pack screen with linked Arcade category.
+ */
+export class ArcadeDownloadPackSuggestion extends models.Model {
+    constructor(lockup, categoryId) {
+        super();
+        this.lockup = lockup;
+        this.categoryId = categoryId;
+    }
+}
+/** @public
+ * Follow up Arcade download pack screen with the list of suggested games.
+ */
+export class ArcadeDownloadPackSuggestionsPage extends models.Model {
+    constructor(title, suggestions, getAllAction, getAllButtonStyle, primaryAction, primaryActionKind, primaryActionSecondaryTitle) {
+        super();
+        this.title = title;
+        this.suggestions = suggestions;
+        this.getAllAction = getAllAction;
+        this.getAllButtonStyle = getAllButtonStyle;
+        this.primaryAction = primaryAction;
+        this.primaryActionKind = primaryActionKind;
+        this.primaryActionSecondaryTitle = primaryActionSecondaryTitle;
+        this.pageMetrics = new metrics.PageMetrics();
+        this.pageRenderMetrics = {};
+    }
+}
+/**
+ * Matches untyped string with `ArcadeOnboardingSubscriptionStatus` typed value.
+ * It is used to convert opaque `string` value that is passed across JS bridge from native code.
+ * @param value `string` value with the same content.
+ */
+export function arcadeOnboardingSubscriptionStatusFromString(value) {
+    switch (value) {
+        case "new":
+            return "new";
+        case "existing":
+            return "existing";
+        default:
+            return "unknown";
+    }
+}
+/** @public
+ * Purchase params to use in`ASDPurchaseManager.purchaseBatch` call.
+ */
+export class BatchPurchaseParams {
+    constructor(items, commonBuyParams) {
+        this.items = items;
+        this.commonBuyParams = commonBuyParams;
+    }
+}
+/** @public
+ * Decorated purchase for a product with a separate buyParams map.
+ */
+export class BatchPurchaseItem {
+    constructor(purchase, buyParams) {
+        this.purchase = purchase;
+        this.buyParams = buyParams;
+    }
+}
+//# sourceMappingURL=arcade.js.map

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov