[DEV-3677] Refactor api layer for api data model#2056
[DEV-3677] Refactor api layer for api data model#2056tommaso1 wants to merge 11 commits intoDEV-3238-strapi-5-feature-branchfrom
Conversation
🦋 Changeset detectedLatest commit: c038fe4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
This PR refactors the Next.js website “API Data” data-access layer by moving Strapi fetching/mapping for API list pages and API detail pages into dedicated repository modules, and by centralizing buildEnv creation.
Changes:
- Extracted
buildEnvinitialization intosrc/lib/buildEnv.tsand reused it fromcmsApi. - Introduced
apiDataListPages/andapiDataList/modules (types, fetchers, mappers, repositories) and updated route pages/utilities to consume them. - Removed legacy API-data-related functions from
cmsApi/apiand added a changeset.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/nextjs-website/src/lib/cmsApi.ts | Switches to shared buildEnv import; removes legacy API data functions. |
| apps/nextjs-website/src/lib/buildEnv.ts | New shared BuildEnv initialization module. |
| apps/nextjs-website/src/lib/apiDataListPages/types.ts | New types for API data list pages + template prop re-export. |
| apps/nextjs-website/src/lib/apiDataListPages/fetcher.ts | New Strapi fetcher for API data list pages using buildEnv. |
| apps/nextjs-website/src/lib/apiDataListPages/mapper.ts | New mapper from Strapi API list pages to UI props. |
| apps/nextjs-website/src/lib/apiDataListPages/index.ts | Repository API for retrieving API list pages. |
| apps/nextjs-website/src/lib/apiDataList/types.ts | New types module for API data list + page props re-export. |
| apps/nextjs-website/src/lib/apiDataList/fetcher.ts | New Strapi fetcher for API data entries using buildEnv. |
| apps/nextjs-website/src/lib/apiDataList/mapper.ts | New mapper for API data entries to route page props. |
| apps/nextjs-website/src/lib/apiDataList/index.ts | Repository API for retrieving API data entries. |
| apps/nextjs-website/src/lib/api.ts | Updates API params generation to use the new repository. |
| apps/nextjs-website/src/app/[locale]/[productSlug]/api/page.tsx | Swaps to repository-based lookup for the API list page. |
| apps/nextjs-website/src/app/[locale]/[productSlug]/api/[apiDataSlug]/page.tsx | Swaps to repository-based lookup for API detail pages. |
| .changeset/soft-rats-cover.md | Records a patch-level changeset for the refactor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const ApiDataListPage = async (props: { params: Promise<Params> }) => { | ||
| const { locale, productSlug } = await props.params; | ||
| const apiDataListPageProps = await getApiDataListPages(locale, productSlug); | ||
| const apiDataListPageProps = | ||
| await ApiDataListPagesRepository.getByProductSlug(locale, productSlug); | ||
|
|
There was a problem hiding this comment.
After switching to ApiDataListPagesRepository.getByProductSlug, this page still has no explicit 404/missing-data handling. If apiDataListPageProps is undefined, the component currently renders nothing; return the locale not-found page or call notFound() when the lookup fails.
| if (!ApiDataProps) { | ||
| // eslint-disable-next-line functional/no-throw-statements | ||
| throw new Error('Failed to fetch data'); | ||
| } |
There was a problem hiding this comment.
Throwing a generic error here turns a missing API entry into a 500. Other routes in this app return the locale PageNotFound/notFound() for missing content; consider doing the same in generateMetadata to produce a 404 instead of crashing the request.
There was a problem hiding this comment.
I agree with the LLM here, I would use the same logic use elsewhere to address the missing data
| if (!apiDataProps) { | ||
| // eslint-disable-next-line functional/no-throw-statements | ||
| throw new Error('Failed to fetch data'); | ||
| } |
There was a problem hiding this comment.
Same as above: throwing here will surface as a 500 error for unknown slugs. Prefer returning <PageNotFound /> (as you already do later) or using notFound() so unknown API slugs correctly render a 404.
| import { makeBannerLinkProps } from '@/lib/strapi/makeProps/makeBannerLink'; | ||
| import { makeBaseProductWithoutLogoProps } from '@/lib/strapi/makeProps/makeProducts'; | ||
| import { StrapiApiDataListPages, ApiDataListPageTemplateProps } from './types'; | ||
| import { compact } from 'lodash'; | ||
| import { StrapiBaseApiData } from '@/lib/strapi/types/apiDataList'; | ||
|
|
||
| function makeApiDataListPageCard( | ||
| locale: string, | ||
| item: StrapiBaseApiData, | ||
| slug: string | ||
| ) { | ||
| if (!item.attributes.apiRestDetail && !item.attributes.apiSoapDetail) { | ||
| console.error( | ||
| `Error while processing API Data with title "${item.attributes.title}": missing API details. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| if ( | ||
| !item.attributes.apiRestDetail?.slug && | ||
| !item.attributes.apiSoapDetail?.slug | ||
| ) { | ||
| console.error(` | ||
| Error while processing API Data with title "${item.attributes.title}": missing API slug. Skipping...`); | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| labels: [ | ||
| { | ||
| label: item.attributes.apiSoapDetail ? 'SOAP' : 'REST', | ||
| }, | ||
| ].filter((label) => !!label.label), | ||
| title: item?.attributes?.title, | ||
| text: item?.attributes?.description || '', | ||
| icon: item?.attributes?.icon?.data?.attributes.url || undefined, | ||
| href: `/${locale}/${slug}/api/${ | ||
| item.attributes.apiRestDetail | ||
| ? item.attributes.apiRestDetail?.slug | ||
| : item.attributes.apiSoapDetail?.slug | ||
| }`, | ||
| tags: item.attributes.tags.data?.map((tag) => tag.attributes) || [], | ||
| }; | ||
| } | ||
|
|
||
| export function mapApiDataListPages( | ||
| locale: string, | ||
| strapiApiDataListPages: StrapiApiDataListPages | ||
| ): ReadonlyArray<ApiDataListPageTemplateProps> { | ||
| return compact( | ||
| strapiApiDataListPages.data.map(({ attributes }) => { | ||
| const slug = attributes.product.data?.attributes.slug; | ||
| if (!slug) { | ||
| console.error( | ||
| `Error while processing API Data List Page with title "${attributes.title}": missing product slug. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| // eslint-disable-next-line functional/no-try-statements | ||
| try { | ||
| const product = makeBaseProductWithoutLogoProps( | ||
| locale, | ||
| attributes.product.data | ||
| ); | ||
| return { | ||
| ...attributes, | ||
| hero: { | ||
| title: attributes.title, | ||
| subtitle: attributes.description || '', | ||
| }, | ||
| product, | ||
| apiDetailSlugs: compact( | ||
| attributes.apiData.data.map(({ attributes }) => | ||
| attributes.apiRestDetail | ||
| ? attributes.apiRestDetail.slug | ||
| : attributes.apiSoapDetail?.slug | ||
| ) | ||
| ), | ||
| cards: compact( | ||
| attributes.apiData.data.map((item) => | ||
| makeApiDataListPageCard(locale, item, slug) | ||
| ) | ||
| ), | ||
| bannerLinks: attributes.bannerLinks.map(makeBannerLinkProps), | ||
| seo: attributes.seo, | ||
| updatedAt: attributes.updatedAt, | ||
| enableFilters: attributes.enableFilters, | ||
| tags: product.tags, | ||
| }; | ||
| } catch (error) { | ||
| // eslint-disable-next-line functional/no-expression-statements | ||
| console.error( | ||
| `Error while processing API Data List Page with title "${attributes.title}":`, | ||
| error, | ||
| 'Skipping...' | ||
| ); | ||
| return null; | ||
| } | ||
| }) | ||
| ); |
There was a problem hiding this comment.
This mapping logic appears to be a near-copy of lib/strapi/makeProps/makeApiDataListPages.ts (which already has dedicated unit tests). To avoid duplicated logic drifting and losing coverage, consider reusing the existing makeApiDataListPagesProps implementation (or porting its tests to cover mapApiDataListPages).
| import { makeBannerLinkProps } from '@/lib/strapi/makeProps/makeBannerLink'; | |
| import { makeBaseProductWithoutLogoProps } from '@/lib/strapi/makeProps/makeProducts'; | |
| import { StrapiApiDataListPages, ApiDataListPageTemplateProps } from './types'; | |
| import { compact } from 'lodash'; | |
| import { StrapiBaseApiData } from '@/lib/strapi/types/apiDataList'; | |
| function makeApiDataListPageCard( | |
| locale: string, | |
| item: StrapiBaseApiData, | |
| slug: string | |
| ) { | |
| if (!item.attributes.apiRestDetail && !item.attributes.apiSoapDetail) { | |
| console.error( | |
| `Error while processing API Data with title "${item.attributes.title}": missing API details. Skipping...` | |
| ); | |
| return null; | |
| } | |
| if ( | |
| !item.attributes.apiRestDetail?.slug && | |
| !item.attributes.apiSoapDetail?.slug | |
| ) { | |
| console.error(` | |
| Error while processing API Data with title "${item.attributes.title}": missing API slug. Skipping...`); | |
| return null; | |
| } | |
| return { | |
| labels: [ | |
| { | |
| label: item.attributes.apiSoapDetail ? 'SOAP' : 'REST', | |
| }, | |
| ].filter((label) => !!label.label), | |
| title: item?.attributes?.title, | |
| text: item?.attributes?.description || '', | |
| icon: item?.attributes?.icon?.data?.attributes.url || undefined, | |
| href: `/${locale}/${slug}/api/${ | |
| item.attributes.apiRestDetail | |
| ? item.attributes.apiRestDetail?.slug | |
| : item.attributes.apiSoapDetail?.slug | |
| }`, | |
| tags: item.attributes.tags.data?.map((tag) => tag.attributes) || [], | |
| }; | |
| } | |
| export function mapApiDataListPages( | |
| locale: string, | |
| strapiApiDataListPages: StrapiApiDataListPages | |
| ): ReadonlyArray<ApiDataListPageTemplateProps> { | |
| return compact( | |
| strapiApiDataListPages.data.map(({ attributes }) => { | |
| const slug = attributes.product.data?.attributes.slug; | |
| if (!slug) { | |
| console.error( | |
| `Error while processing API Data List Page with title "${attributes.title}": missing product slug. Skipping...` | |
| ); | |
| return null; | |
| } | |
| // eslint-disable-next-line functional/no-try-statements | |
| try { | |
| const product = makeBaseProductWithoutLogoProps( | |
| locale, | |
| attributes.product.data | |
| ); | |
| return { | |
| ...attributes, | |
| hero: { | |
| title: attributes.title, | |
| subtitle: attributes.description || '', | |
| }, | |
| product, | |
| apiDetailSlugs: compact( | |
| attributes.apiData.data.map(({ attributes }) => | |
| attributes.apiRestDetail | |
| ? attributes.apiRestDetail.slug | |
| : attributes.apiSoapDetail?.slug | |
| ) | |
| ), | |
| cards: compact( | |
| attributes.apiData.data.map((item) => | |
| makeApiDataListPageCard(locale, item, slug) | |
| ) | |
| ), | |
| bannerLinks: attributes.bannerLinks.map(makeBannerLinkProps), | |
| seo: attributes.seo, | |
| updatedAt: attributes.updatedAt, | |
| enableFilters: attributes.enableFilters, | |
| tags: product.tags, | |
| }; | |
| } catch (error) { | |
| // eslint-disable-next-line functional/no-expression-statements | |
| console.error( | |
| `Error while processing API Data List Page with title "${attributes.title}":`, | |
| error, | |
| 'Skipping...' | |
| ); | |
| return null; | |
| } | |
| }) | |
| ); | |
| import { makeApiDataListPagesProps } from '@/lib/strapi/makeProps/makeApiDataListPages'; | |
| import { StrapiApiDataListPages, ApiDataListPageTemplateProps } from './types'; | |
| export function mapApiDataListPages( | |
| locale: string, | |
| strapiApiDataListPages: StrapiApiDataListPages | |
| ): ReadonlyArray<ApiDataListPageTemplateProps> { | |
| return makeApiDataListPagesProps(locale, strapiApiDataListPages); |
There was a problem hiding this comment.
Same as the other section.
I will not follow the copilot suggestion here, but this comment raises some questions about the existing tests.
There are some already existing tests that are related to the make function apps/nextjs-website/src/lib/strapi/tests/makeApiDataListPages.test.ts . I will move this test inside the apiDataList folder alongside other files and refactor that test to use the new mapper function.
|
|
||
| export async function mapApiDataList( | ||
| locale: string, | ||
| strapiApiDataList: StrapiApiDataList | ||
| ): Promise<ReadonlyArray<ApiDataPageProps>> { | ||
| const list = compact( | ||
| await Promise.all( | ||
| strapiApiDataList.data | ||
| .filter( | ||
| (apiPage) => | ||
| apiPage.attributes.apiRestDetail || apiPage.attributes.apiSoapDetail | ||
| ) | ||
| .map(async ({ attributes }) => { | ||
| if (!attributes.apiRestDetail && !attributes.apiSoapDetail) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing API details. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
| const apiDataSlug = | ||
| attributes.apiRestDetail?.slug || | ||
| attributes.apiSoapDetail?.slug || | ||
| ''; | ||
| if (!apiDataSlug) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing API slug. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| if (!attributes.product.data) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing product data. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| // eslint-disable-next-line functional/no-try-statements | ||
| try { | ||
| const product = makeBaseProductWithoutLogoProps( | ||
| locale, | ||
| attributes.product.data | ||
| ); | ||
| return { | ||
| ...attributes, | ||
| product, | ||
| apiType: attributes.apiRestDetail ? 'rest' : 'soap', | ||
| apiDataSlug: apiDataSlug, | ||
| restApiSpecUrls: attributes.apiRestDetail | ||
| ? [ | ||
| ...attributes.apiRestDetail.specUrls.map((spec) => ({ | ||
| ...spec, | ||
| })), | ||
| ] | ||
| : [], | ||
| apiSoapUrl: attributes.apiSoapDetail?.repositoryUrl, | ||
| specUrlsName: attributes.title, | ||
| apiSoapUrlList: attributes.apiSoapDetail | ||
| ? await makeApiSoapUrlList( | ||
| locale, | ||
| attributes.apiSoapDetail.dirName | ||
| ) | ||
| : [], | ||
| bannerLinks: | ||
| attributes.bannerLinks.length > 0 | ||
| ? attributes.bannerLinks.map(makeBannerLinkProps) | ||
| : attributes.product.data.attributes.bannerLinks?.map( | ||
| makeBannerLinkProps | ||
| ), | ||
| seo: attributes.seo, | ||
| } satisfies ApiDataPageProps; | ||
| } catch (error) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}":`, | ||
| error, | ||
| 'Skipping...' | ||
| ); | ||
| return null; | ||
| } | ||
| }) | ||
| ) | ||
| ); | ||
| return Promise.all(list); |
There was a problem hiding this comment.
This mapping logic appears to be a near-copy of lib/strapi/makeProps/makeApiDataList.ts (which already has unit tests under lib/strapi/__tests__/makeApiDataList.test.ts). Consider reusing the existing implementation or porting those tests to cover mapApiDataList so the refactor doesn’t reduce confidence in the transformation behavior.
| export async function mapApiDataList( | |
| locale: string, | |
| strapiApiDataList: StrapiApiDataList | |
| ): Promise<ReadonlyArray<ApiDataPageProps>> { | |
| const list = compact( | |
| await Promise.all( | |
| strapiApiDataList.data | |
| .filter( | |
| (apiPage) => | |
| apiPage.attributes.apiRestDetail || apiPage.attributes.apiSoapDetail | |
| ) | |
| .map(async ({ attributes }) => { | |
| if (!attributes.apiRestDetail && !attributes.apiSoapDetail) { | |
| console.error( | |
| `Error while processing API Data with title "${attributes.title}": missing API details. Skipping...` | |
| ); | |
| return null; | |
| } | |
| const apiDataSlug = | |
| attributes.apiRestDetail?.slug || | |
| attributes.apiSoapDetail?.slug || | |
| ''; | |
| if (!apiDataSlug) { | |
| console.error( | |
| `Error while processing API Data with title "${attributes.title}": missing API slug. Skipping...` | |
| ); | |
| return null; | |
| } | |
| if (!attributes.product.data) { | |
| console.error( | |
| `Error while processing API Data with title "${attributes.title}": missing product data. Skipping...` | |
| ); | |
| return null; | |
| } | |
| // eslint-disable-next-line functional/no-try-statements | |
| try { | |
| const product = makeBaseProductWithoutLogoProps( | |
| locale, | |
| attributes.product.data | |
| ); | |
| return { | |
| ...attributes, | |
| product, | |
| apiType: attributes.apiRestDetail ? 'rest' : 'soap', | |
| apiDataSlug: apiDataSlug, | |
| restApiSpecUrls: attributes.apiRestDetail | |
| ? [ | |
| ...attributes.apiRestDetail.specUrls.map((spec) => ({ | |
| ...spec, | |
| })), | |
| ] | |
| : [], | |
| apiSoapUrl: attributes.apiSoapDetail?.repositoryUrl, | |
| specUrlsName: attributes.title, | |
| apiSoapUrlList: attributes.apiSoapDetail | |
| ? await makeApiSoapUrlList( | |
| locale, | |
| attributes.apiSoapDetail.dirName | |
| ) | |
| : [], | |
| bannerLinks: | |
| attributes.bannerLinks.length > 0 | |
| ? attributes.bannerLinks.map(makeBannerLinkProps) | |
| : attributes.product.data.attributes.bannerLinks?.map( | |
| makeBannerLinkProps | |
| ), | |
| seo: attributes.seo, | |
| } satisfies ApiDataPageProps; | |
| } catch (error) { | |
| console.error( | |
| `Error while processing API Data with title "${attributes.title}":`, | |
| error, | |
| 'Skipping...' | |
| ); | |
| return null; | |
| } | |
| }) | |
| ) | |
| ); | |
| return Promise.all(list); | |
| import { makeApiDataList as makeStrapiApiDataList } from '@/lib/strapi/makeProps/makeApiDataList'; | |
| export async function mapApiDataList( | |
| locale: string, | |
| strapiApiDataList: StrapiApiDataList | |
| ): Promise<ReadonlyArray<ApiDataPageProps>> { | |
| return makeStrapiApiDataList(locale, strapiApiDataList); |
There was a problem hiding this comment.
I will not follow the copilot suggestion here, but this comment raises some questions about the existing tests.
There are some already existing tests that are related to the make function apps/nextjs-website/src/lib/strapi/__tests__/makeApiDataList.test.ts . I will move this test inside the apiDataList folder alongside other files and refactor that test to use the new mapper function.
|
@tommaso1 |
| export type { | ||
| ApiDataListPages, | ||
| ApiDataListPage, | ||
| ApiDataListPageWithoutProduct, | ||
| ApiDataListPageTemplateProps, | ||
| }; |
There was a problem hiding this comment.
Instead of exporting here the types, why not move here the whole type definition? So the previous apps/nextjs-website/src/lib/strapi/types/apiDataListPages.ts can be deleted, and all types will be centralized here?
| } from '@/lib/strapi/types/apiDataList'; | ||
| import { ApiDataPageProps } from '@/app/[locale]/[productSlug]/api/[apiDataSlug]/page'; | ||
|
|
||
| export type { ApiDataList, ApiData, ApiDataPageProps }; |
There was a problem hiding this comment.
Instead of exporting here the types, why not move here the whole type definition? So the previous apps/nextjs-website/src/lib/strapi/types/apiDataList.ts can be deleted, and all types will be centralized here?
|
|
||
| export async function mapApiDataList( | ||
| locale: string, | ||
| strapiApiDataList: StrapiApiDataList | ||
| ): Promise<ReadonlyArray<ApiDataPageProps>> { | ||
| const list = compact( | ||
| await Promise.all( | ||
| strapiApiDataList.data | ||
| .filter( | ||
| (apiPage) => | ||
| apiPage.attributes.apiRestDetail || apiPage.attributes.apiSoapDetail | ||
| ) | ||
| .map(async ({ attributes }) => { | ||
| if (!attributes.apiRestDetail && !attributes.apiSoapDetail) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing API details. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
| const apiDataSlug = | ||
| attributes.apiRestDetail?.slug || | ||
| attributes.apiSoapDetail?.slug || | ||
| ''; | ||
| if (!apiDataSlug) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing API slug. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| if (!attributes.product.data) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}": missing product data. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| // eslint-disable-next-line functional/no-try-statements | ||
| try { | ||
| const product = makeBaseProductWithoutLogoProps( | ||
| locale, | ||
| attributes.product.data | ||
| ); | ||
| return { | ||
| ...attributes, | ||
| product, | ||
| apiType: attributes.apiRestDetail ? 'rest' : 'soap', | ||
| apiDataSlug: apiDataSlug, | ||
| restApiSpecUrls: attributes.apiRestDetail | ||
| ? [ | ||
| ...attributes.apiRestDetail.specUrls.map((spec) => ({ | ||
| ...spec, | ||
| })), | ||
| ] | ||
| : [], | ||
| apiSoapUrl: attributes.apiSoapDetail?.repositoryUrl, | ||
| specUrlsName: attributes.title, | ||
| apiSoapUrlList: attributes.apiSoapDetail | ||
| ? await makeApiSoapUrlList( | ||
| locale, | ||
| attributes.apiSoapDetail.dirName | ||
| ) | ||
| : [], | ||
| bannerLinks: | ||
| attributes.bannerLinks.length > 0 | ||
| ? attributes.bannerLinks.map(makeBannerLinkProps) | ||
| : attributes.product.data.attributes.bannerLinks?.map( | ||
| makeBannerLinkProps | ||
| ), | ||
| seo: attributes.seo, | ||
| } satisfies ApiDataPageProps; | ||
| } catch (error) { | ||
| console.error( | ||
| `Error while processing API Data with title "${attributes.title}":`, | ||
| error, | ||
| 'Skipping...' | ||
| ); | ||
| return null; | ||
| } | ||
| }) | ||
| ) | ||
| ); | ||
| return Promise.all(list); |
There was a problem hiding this comment.
I will not follow the copilot suggestion here, but this comment raises some questions about the existing tests.
There are some already existing tests that are related to the make function apps/nextjs-website/src/lib/strapi/__tests__/makeApiDataList.test.ts . I will move this test inside the apiDataList folder alongside other files and refactor that test to use the new mapper function.
| import { makeBannerLinkProps } from '@/lib/strapi/makeProps/makeBannerLink'; | ||
| import { makeBaseProductWithoutLogoProps } from '@/lib/strapi/makeProps/makeProducts'; | ||
| import { StrapiApiDataListPages, ApiDataListPageTemplateProps } from './types'; | ||
| import { compact } from 'lodash'; | ||
| import { StrapiBaseApiData } from '@/lib/strapi/types/apiDataList'; | ||
|
|
||
| function makeApiDataListPageCard( | ||
| locale: string, | ||
| item: StrapiBaseApiData, | ||
| slug: string | ||
| ) { | ||
| if (!item.attributes.apiRestDetail && !item.attributes.apiSoapDetail) { | ||
| console.error( | ||
| `Error while processing API Data with title "${item.attributes.title}": missing API details. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| if ( | ||
| !item.attributes.apiRestDetail?.slug && | ||
| !item.attributes.apiSoapDetail?.slug | ||
| ) { | ||
| console.error(` | ||
| Error while processing API Data with title "${item.attributes.title}": missing API slug. Skipping...`); | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| labels: [ | ||
| { | ||
| label: item.attributes.apiSoapDetail ? 'SOAP' : 'REST', | ||
| }, | ||
| ].filter((label) => !!label.label), | ||
| title: item?.attributes?.title, | ||
| text: item?.attributes?.description || '', | ||
| icon: item?.attributes?.icon?.data?.attributes.url || undefined, | ||
| href: `/${locale}/${slug}/api/${ | ||
| item.attributes.apiRestDetail | ||
| ? item.attributes.apiRestDetail?.slug | ||
| : item.attributes.apiSoapDetail?.slug | ||
| }`, | ||
| tags: item.attributes.tags.data?.map((tag) => tag.attributes) || [], | ||
| }; | ||
| } | ||
|
|
||
| export function mapApiDataListPages( | ||
| locale: string, | ||
| strapiApiDataListPages: StrapiApiDataListPages | ||
| ): ReadonlyArray<ApiDataListPageTemplateProps> { | ||
| return compact( | ||
| strapiApiDataListPages.data.map(({ attributes }) => { | ||
| const slug = attributes.product.data?.attributes.slug; | ||
| if (!slug) { | ||
| console.error( | ||
| `Error while processing API Data List Page with title "${attributes.title}": missing product slug. Skipping...` | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| // eslint-disable-next-line functional/no-try-statements | ||
| try { | ||
| const product = makeBaseProductWithoutLogoProps( | ||
| locale, | ||
| attributes.product.data | ||
| ); | ||
| return { | ||
| ...attributes, | ||
| hero: { | ||
| title: attributes.title, | ||
| subtitle: attributes.description || '', | ||
| }, | ||
| product, | ||
| apiDetailSlugs: compact( | ||
| attributes.apiData.data.map(({ attributes }) => | ||
| attributes.apiRestDetail | ||
| ? attributes.apiRestDetail.slug | ||
| : attributes.apiSoapDetail?.slug | ||
| ) | ||
| ), | ||
| cards: compact( | ||
| attributes.apiData.data.map((item) => | ||
| makeApiDataListPageCard(locale, item, slug) | ||
| ) | ||
| ), | ||
| bannerLinks: attributes.bannerLinks.map(makeBannerLinkProps), | ||
| seo: attributes.seo, | ||
| updatedAt: attributes.updatedAt, | ||
| enableFilters: attributes.enableFilters, | ||
| tags: product.tags, | ||
| }; | ||
| } catch (error) { | ||
| // eslint-disable-next-line functional/no-expression-statements | ||
| console.error( | ||
| `Error while processing API Data List Page with title "${attributes.title}":`, | ||
| error, | ||
| 'Skipping...' | ||
| ); | ||
| return null; | ||
| } | ||
| }) | ||
| ); |
There was a problem hiding this comment.
Same as the other section.
I will not follow the copilot suggestion here, but this comment raises some questions about the existing tests.
There are some already existing tests that are related to the make function apps/nextjs-website/src/lib/strapi/tests/makeApiDataListPages.test.ts . I will move this test inside the apiDataList folder alongside other files and refactor that test to use the new mapper function.
MarcoPonchia
left a comment
There was a problem hiding this comment.
I will remove unused files now deprecated from new fetcher and mapper stack like:
- apps/nextjs-website/src/lib/strapi/fetches/fetchApiDataList.ts
- apps/nextjs-website/src/lib/strapi/fetches/fetchApiDataListPages.ts
- apps/nextjs-website/src/lib/strapi/makeProps/makeApiDataList.ts
- apps/nextjs-website/src/lib/strapi/makeProps/makeApiDataListPages.ts
There was a problem hiding this comment.
i will rename this file in mapper.test.ts
There was a problem hiding this comment.
Also here i will rename this file in mapper.test.ts
…-5' into DEV-3677 # Conflicts: # apps/nextjs-website/src/components/templates/ApiDataListTemplate/ApiDataListTemplate.tsx
Branch is not up to date with base branch@tommaso1 it seems this Pull Request is not updated with base branch. |
Jira Pull Request LinkThis Pull Request refers to the following Jira issue DEV-3677 |
|
This PR exceeds the recommended size of 800 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. |

List of Changes
Refactor api layer for api data model
Motivation and Context
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Checklist: