/ src / jet / dependencies / seo.ts
seo.ts
  1  import type { Opt } from '@jet/environment/types/optional';
  2  import type {
  3      ArcadeSeeAllGamesPage,
  4      ArticlePage,
  5      ChartsHubPage,
  6      GenericPage,
  7      ReviewsPage,
  8      SearchLandingPage,
  9      SearchResultsPage,
 10      SeeAllPage,
 11      ShelfBasedProductPage,
 12      TodayPage,
 13      TopChartsPage,
 14  } from '@jet-app/app-store/api/models';
 15  import type { WebRenderablePage } from '@jet-app/app-store/api/models/web-renderable-page';
 16  import type { SEO as SEODependency } from '@jet-app/app-store/foundation/dependencies/seo';
 17  import type { AppStoreObjectGraph } from '@jet-app/app-store/foundation/runtime/app-store-object-graph';
 18  import type { DataContainer } from '@jet-app/app-store/foundation/media/data-structure';
 19  
 20  import type { SeoData } from '@amp/web-app-components/src/components/MetaTags/types';
 21  
 22  import type { Locale } from './locale';
 23  
 24  import { seoDataForAnyPage, updateCanonicalURL } from '~/utils/seo/common';
 25  import { seoDataForArticlePage } from '~/utils/seo/article-page';
 26  import { seoDataForChartsPage } from '~/utils/seo/charts-page';
 27  import { seoDataForChartsHubPage } from '~/utils/seo/charts-hub-page';
 28  import { seoDataForDeveloperPage } from '~/utils/seo/developer-page';
 29  import { seoDataForProductPage } from '~/utils/seo/product-page';
 30  import { seoDataForAppEventDetailPage } from '~/utils/seo/app-event-detail-page';
 31  import { seoDataForReviewsPage } from '~/utils/seo/reviews-page';
 32  import { seoDataForSearchLandingPage } from '~/utils/seo/search-landing-page';
 33  import { seoDataForSearchResultsPage } from '~/utils/seo/search-results-page';
 34  import { seoDataForEditorialShelfCollectionPage } from '~/utils/seo/editorial-shelf-collection-page';
 35  import { seoDataForArcadeSeeAllPage } from '~/utils/seo/arcade-see-all-page';
 36  import { seoDataForSeeAllPage } from '~/utils/seo/see-all-page';
 37  
 38  export class SEO implements SEODependency {
 39      private locale: Locale;
 40  
 41      constructor(locale: Locale) {
 42          this.locale = locale;
 43      }
 44  
 45      private get i18n() {
 46          if (this.locale.i18n) {
 47              return this.locale.i18n;
 48          }
 49  
 50          throw new Error('`i18n` not yet configured ');
 51      }
 52  
 53      private getSEODataForGenericPage(page: GenericPage): Opt<SeoData> {
 54          return {
 55              ...seoDataForAnyPage(page, this.i18n),
 56          };
 57      }
 58  
 59      updateCanonicalURL(page: WebRenderablePage, canonicalURL: string): void {
 60          updateCanonicalURL(page, canonicalURL);
 61      }
 62  
 63      /// MARK: Page SEO Data Hooks
 64  
 65      getSEODataForAppEventPage(
 66          objectGraph: AppStoreObjectGraph,
 67          page: GenericPage,
 68      ): Opt<SeoData> {
 69          return {
 70              ...seoDataForAnyPage(page, this.i18n),
 71              ...seoDataForAppEventDetailPage(
 72                  page,
 73                  this.i18n,
 74                  objectGraph.locale.activeLanguage,
 75              ),
 76          };
 77      }
 78  
 79      getSEODataForArcadeSeeAllPage(
 80          _objectGraph: AppStoreObjectGraph,
 81          page: ArcadeSeeAllGamesPage,
 82      ): Opt<SeoData> {
 83          return {
 84              ...seoDataForAnyPage(page, this.i18n),
 85              ...seoDataForArcadeSeeAllPage(page, this.i18n),
 86          };
 87      }
 88  
 89      getSEODataForArticlePage(
 90          objectGraph: AppStoreObjectGraph,
 91          page: ArticlePage,
 92          response: Opt<DataContainer>,
 93      ): Opt<SeoData> {
 94          return {
 95              ...seoDataForAnyPage(page, this.i18n),
 96              ...seoDataForArticlePage(
 97                  objectGraph,
 98                  this.i18n,
 99                  page,
100                  response,
101                  objectGraph.locale.activeLanguage,
102              ),
103          };
104      }
105  
106      getSEODataForBundlePage(
107          objectGraph: AppStoreObjectGraph,
108          page: ShelfBasedProductPage,
109          data: Opt<DataContainer>,
110      ): Opt<SeoData> {
111          return this.getSEODataForProductPage(objectGraph, page, data);
112      }
113  
114      getSEODataForChartsPage(
115          objectGraph: AppStoreObjectGraph,
116          page: TopChartsPage,
117      ): Opt<SeoData> {
118          return {
119              ...seoDataForAnyPage(page, this.i18n),
120              ...seoDataForChartsPage(
121                  page,
122                  this.i18n,
123                  objectGraph.locale.activeLanguage,
124              ),
125          };
126      }
127  
128      getSEODataForChartsHubPage(
129          objectGraph: AppStoreObjectGraph,
130          page: ChartsHubPage,
131      ): Opt<SeoData> {
132          return {
133              ...seoDataForAnyPage(page, this.i18n),
134              ...seoDataForChartsHubPage(
135                  page,
136                  this.i18n,
137                  objectGraph.locale.activeLanguage,
138              ),
139          };
140      }
141  
142      getSEODataForDeveloperPage(
143          objectGraph: AppStoreObjectGraph,
144          page: GenericPage,
145          response: Opt<DataContainer>,
146      ): Opt<SeoData> {
147          return {
148              ...seoDataForAnyPage(page, this.i18n),
149              ...seoDataForDeveloperPage(objectGraph, response, this.i18n),
150          };
151      }
152  
153      getSEODataForEditorialPage(
154          _objectGraph: AppStoreObjectGraph,
155          page: GenericPage,
156      ): Opt<SeoData> {
157          return this.getSEODataForGenericPage(page);
158      }
159  
160      getSEODataForEditorialShelfCollectionPage(
161          _objectGraph: AppStoreObjectGraph,
162          page: GenericPage,
163      ): Opt<SeoData> {
164          return {
165              ...seoDataForAnyPage(page, this.i18n),
166              ...seoDataForEditorialShelfCollectionPage(page, this.i18n),
167          };
168      }
169  
170      getSEODataForGroupingPage(
171          _objectGraph: AppStoreObjectGraph,
172          page: GenericPage,
173      ): Opt<SeoData> {
174          return this.getSEODataForGenericPage(page);
175      }
176  
177      getSEODataForProductPage(
178          objectGraph: AppStoreObjectGraph,
179          page: ShelfBasedProductPage,
180          data: Opt<DataContainer>,
181      ): Opt<SeoData> {
182          return {
183              ...seoDataForAnyPage(page, this.i18n),
184              ...seoDataForProductPage(
185                  objectGraph,
186                  page,
187                  data,
188                  this.i18n,
189                  objectGraph.locale.activeLanguage,
190              ),
191          };
192      }
193  
194      getSEODataForReviewsPage(
195          objectGraph: AppStoreObjectGraph,
196          page: ReviewsPage,
197          productPage: ShelfBasedProductPage,
198      ): Opt<SeoData> {
199          return {
200              ...this.getSEODataForGenericPage(page),
201              ...seoDataForReviewsPage(this.i18n, page, productPage, objectGraph),
202          };
203      }
204  
205      getSEODataForRoomPage(
206          _objectGraph: AppStoreObjectGraph,
207          page: GenericPage,
208      ): Opt<SeoData> {
209          return {
210              ...seoDataForAnyPage(page, this.i18n),
211          };
212      }
213  
214      getSEODataForSearchLandingPage(
215          _objectGraph: AppStoreObjectGraph,
216          page: SearchLandingPage,
217      ): Opt<SeoData> {
218          return {
219              ...seoDataForAnyPage(page, this.i18n),
220              ...seoDataForSearchLandingPage(page, this.i18n),
221          };
222      }
223  
224      getSEODataForSearchResultsPage(
225          objectGraph: AppStoreObjectGraph,
226          page: SearchResultsPage,
227      ): Opt<SeoData> {
228          return {
229              ...seoDataForAnyPage(page, this.i18n),
230              ...seoDataForSearchResultsPage(
231                  page,
232                  this.i18n,
233                  objectGraph.locale.activeLanguage,
234              ),
235          };
236      }
237  
238      getSEODataForTodayPage(
239          _objectGraph: AppStoreObjectGraph,
240          page: TodayPage,
241      ): Opt<SeoData> {
242          return seoDataForAnyPage(page, this.i18n);
243      }
244  
245      getSEODataForSeeAllPage(
246          _objectGraph: AppStoreObjectGraph,
247          page: SeeAllPage,
248      ): Opt<SeoData> {
249          return {
250              ...seoDataForAnyPage(page, this.i18n),
251              ...seoDataForSeeAllPage(page, this.i18n),
252          };
253      }
254  }