@se-studio/contentful-rest-api 1.0.36 → 1.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +13 -9
- package/dist/index.js +274 -68
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ type BaseMediaSkeleton = EntrySkeletonType<BaseMediaFields, 'media'>;
|
|
|
41
41
|
|
|
42
42
|
interface BaseSchemaFields {
|
|
43
43
|
cmsLabel: EntryFieldTypes.Symbol;
|
|
44
|
-
markup
|
|
44
|
+
markup?: EntryFieldTypes.Text;
|
|
45
45
|
}
|
|
46
46
|
type BaseSchemaSkeleton = EntrySkeletonType<BaseSchemaFields, 'schema'>;
|
|
47
47
|
|
|
@@ -61,7 +61,6 @@ interface BaseArticleTypeFields {
|
|
|
61
61
|
name: EntryFieldTypes.Symbol;
|
|
62
62
|
slug: EntryFieldTypes.Symbol;
|
|
63
63
|
indexPageName: EntryFieldTypes.Symbol;
|
|
64
|
-
indexPageSlug: EntryFieldTypes.Symbol;
|
|
65
64
|
indexPageDescription: EntryFieldTypes.Symbol;
|
|
66
65
|
featuredImage: EntryFieldTypes.AssetLink;
|
|
67
66
|
menu?: EntryFieldTypes.EntryLink<BaseNavigationSkeleton>;
|
|
@@ -324,7 +323,6 @@ interface BaseCustomTypeFields {
|
|
|
324
323
|
name: EntryFieldTypes.Symbol;
|
|
325
324
|
slug: EntryFieldTypes.Symbol;
|
|
326
325
|
indexPageName: EntryFieldTypes.Symbol;
|
|
327
|
-
indexPageSlug: EntryFieldTypes.Symbol;
|
|
328
326
|
indexPageDescription: EntryFieldTypes.Symbol;
|
|
329
327
|
featuredImage: EntryFieldTypes.AssetLink;
|
|
330
328
|
menu?: EntryFieldTypes.EntryLink<BaseNavigationSkeleton>;
|
|
@@ -383,7 +381,7 @@ interface CmsResponse<T> {
|
|
|
383
381
|
}
|
|
384
382
|
|
|
385
383
|
declare function baseArticleConverter(context: ConverterContext, entry: Entry<BaseArticleSkeleton, DefaultChainModifier, string>): IBaseArticle;
|
|
386
|
-
declare function baseArticleTypeConverter(context: ConverterContext, entry: Entry<BaseArticleTypeSkeleton, DefaultChainModifier, string>): IBaseArticleType;
|
|
384
|
+
declare function baseArticleTypeConverter(context: ConverterContext, entry: Entry<BaseArticleTypeSkeleton, DefaultChainModifier, string>, customTypeEntry?: Entry<BaseCustomTypeSkeleton, DefaultChainModifier, string>): IBaseArticleType;
|
|
387
385
|
|
|
388
386
|
type IContentfulCollection<TContents = BaseCollectionContent> = IBaseCollection<TContents> & {
|
|
389
387
|
body?: IContentfulRichText | null;
|
|
@@ -405,7 +403,7 @@ declare function basePageConverter(context: ConverterContext, entry: Entry<BaseP
|
|
|
405
403
|
declare function calculatePageHref(slug: string): string;
|
|
406
404
|
declare function calculatePageVariantHref(slug: string): string;
|
|
407
405
|
|
|
408
|
-
declare function baseTagConverter(context: ConverterContext, entry: Entry<BaseTagSkeleton, DefaultChainModifier, string>): IBaseTag;
|
|
406
|
+
declare function baseTagConverter(context: ConverterContext, entry: Entry<BaseTagSkeleton, DefaultChainModifier, string>, customTypeEntry?: Entry<BaseCustomTypeSkeleton, DefaultChainModifier, string>): IBaseTag;
|
|
409
407
|
|
|
410
408
|
declare function lookupAsset(context: ConverterContext, asset: UnresolvedLink<'Asset'> | undefined): IVisual | undefined;
|
|
411
409
|
type ContentResolverFunction = (context: ConverterContext, entry: Entry<BaseContent, DefaultChainModifier, string>) => unknown;
|
|
@@ -445,7 +443,10 @@ type ConverterContext = BaseConverterContext & {
|
|
|
445
443
|
|
|
446
444
|
declare function contentfulArticleRest(context: BaseConverterContext, config: ContentfulConfig, slug: string, articleTypeSlug: string, options?: FetchOptions): Promise<CmsResponse<IBaseArticle | null>>;
|
|
447
445
|
|
|
448
|
-
|
|
446
|
+
interface ArticleTypeFetchOptions extends FetchOptions {
|
|
447
|
+
customType?: string;
|
|
448
|
+
}
|
|
449
|
+
declare function contentfulArticleTypeRest(context: BaseConverterContext, config: ContentfulConfig, slug: string, options?: ArticleTypeFetchOptions): Promise<CmsResponse<IBaseArticleType | null>>;
|
|
449
450
|
|
|
450
451
|
interface ContentfulResponse<T = any> {
|
|
451
452
|
sys: {
|
|
@@ -523,7 +524,7 @@ declare function createDownloadHandler(config: DownloadHandlerConfig): (_request
|
|
|
523
524
|
|
|
524
525
|
declare function createBaseConverterContext(urlCalculators: UrlCalculators): BaseConverterContext;
|
|
525
526
|
|
|
526
|
-
declare function contentfulCustomTypeRest(context: BaseConverterContext, config: ContentfulConfig,
|
|
527
|
+
declare function contentfulCustomTypeRest(context: BaseConverterContext, config: ContentfulConfig, slug: string, options?: FetchOptions): Promise<CmsResponse<IBaseCustomType | null>>;
|
|
527
528
|
|
|
528
529
|
type DefaultChainModifier = 'WITHOUT_LINK_RESOLUTION';
|
|
529
530
|
interface IContentfulRichText {
|
|
@@ -595,7 +596,10 @@ declare function contentfulPersonSitemapEntries(context: BaseConverterContext, c
|
|
|
595
596
|
declare function getAllSitemapEntries(context: BaseConverterContext, config: ContentfulConfig, sitemapConfig: SitemapConfig, options?: FetchOptions): Promise<CmsResponse<ISitemapEntry[]>>;
|
|
596
597
|
declare function createSitemapProvider(fetcher: (context: BaseConverterContext, config: ContentfulConfig, sitemapConfig?: SitemapContentTypeConfig, options?: FetchOptions) => Promise<CmsResponse<ISitemapEntry[]>>, sitemapConfig?: SitemapContentTypeConfig): SitemapEntryProvider;
|
|
597
598
|
|
|
598
|
-
|
|
599
|
+
interface TagFetchOptions extends FetchOptions {
|
|
600
|
+
customType?: string;
|
|
601
|
+
}
|
|
602
|
+
declare function contentfulTagRest(context: BaseConverterContext, config: ContentfulConfig, slug: string, options?: TagFetchOptions): Promise<CmsResponse<IBaseTag | null>>;
|
|
599
603
|
|
|
600
604
|
interface IFetchedTemplate {
|
|
601
605
|
id: string;
|
|
@@ -705,4 +709,4 @@ declare class RateLimiter {
|
|
|
705
709
|
getIntervalMs(): number;
|
|
706
710
|
}
|
|
707
711
|
|
|
708
|
-
export { AllTags, ArticleTag, ArticleTypeTag, AssetTag, AuthenticationError, BannerTag, type BaseConverterContext, type CmsError, type CmsResponse, type ContentResolverFunction, ContentfulFetchClient as ContentfulClient, type ContentfulConfig, ContentfulError, ContentfulFetchClient, type ConverterContext, CustomTypeTag, type DefaultChainModifier, type DownloadHandlerConfig, type DownloadRouteParams, EntryNotFoundError, type FetchOptions, GlobalTag, type IContentfulCollection, type IContentfulComponent, type IContentfulPerson, type IContentfulRichText, type IFetchedTemplate, type ISitemapEntry, LocationTag, NavigationTag, PageTag, PersonTag, type PreviewContentType, type PreviewEntryInfo, RateLimitError, RateLimiter, type RelatedArticlesOptions, type RetryConfig, type RevalidationConfig, type SitemapChangeFrequency, type SitemapConfig, type SitemapContentTypeConfig, type SitemapEntryProvider, TagTag, TemplateTag, type UrlCalculators, ValidationError, arrayOrUndefined, articleTag, articleTypeIndexTag, articleTypeTag, assetTag, basePageConverter, calculateBackoffDelay, calculatePageHref, calculatePageVariantHref, contentfulAllArticleLinks, contentfulAllArticleTypeLinks, contentfulAllPageLinks, contentfulAllPersonLinks, contentfulAllTagLinks, contentfulArticleRest, contentfulArticleSitemapEntries, contentfulArticleTypeRest, contentfulArticleTypeSitemapEntries, contentfulAssetRest, contentfulCustomTypeRest, contentfulPageRest, contentfulPageSitemapEntries, contentfulPersonRest, contentfulPersonSitemapEntries, contentfulTagRest, contentfulTagSitemapEntries, contentfulTemplateRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createDownloadHandler, createResponsiveVisual, createRevalidationHandler, createSitemapProvider, customTypeTag, filterRelatedArticles, getAllSitemapEntries, getCacheTags, getCacheTagsForPreview, getCacheTagsForProduction, getContentfulClient, getPreviewEntryInfo, getRetryAfter, isBrowserViewable, isContentfulError, isRateLimitError, isRetryableError, isValidDate, locationTag, lookupAsset, notEmpty, pageTag, personTag, resolveLink, resolveLinks, resolveRichTextDocument, revalidateSingleTag, revalidateTags, safeDate, tagTag, templateTag, withRetry };
|
|
712
|
+
export { AllTags, ArticleTag, type ArticleTypeFetchOptions, ArticleTypeTag, AssetTag, AuthenticationError, BannerTag, type BaseConverterContext, type CmsError, type CmsResponse, type ContentResolverFunction, ContentfulFetchClient as ContentfulClient, type ContentfulConfig, ContentfulError, ContentfulFetchClient, type ConverterContext, CustomTypeTag, type DefaultChainModifier, type DownloadHandlerConfig, type DownloadRouteParams, EntryNotFoundError, type FetchOptions, GlobalTag, type IContentfulCollection, type IContentfulComponent, type IContentfulPerson, type IContentfulRichText, type IFetchedTemplate, type ISitemapEntry, LocationTag, NavigationTag, PageTag, type PersonFetchOptions, PersonTag, type PreviewContentType, type PreviewEntryInfo, RateLimitError, RateLimiter, type RelatedArticlesOptions, type RetryConfig, type RevalidationConfig, type SitemapChangeFrequency, type SitemapConfig, type SitemapContentTypeConfig, type SitemapEntryProvider, type TagFetchOptions, TagTag, TemplateTag, type UrlCalculators, ValidationError, arrayOrUndefined, articleTag, articleTypeIndexTag, articleTypeTag, assetTag, basePageConverter, calculateBackoffDelay, calculatePageHref, calculatePageVariantHref, contentfulAllArticleLinks, contentfulAllArticleTypeLinks, contentfulAllPageLinks, contentfulAllPersonLinks, contentfulAllTagLinks, contentfulArticleRest, contentfulArticleSitemapEntries, contentfulArticleTypeRest, contentfulArticleTypeSitemapEntries, contentfulAssetRest, contentfulCustomTypeRest, contentfulPageRest, contentfulPageSitemapEntries, contentfulPersonRest, contentfulPersonSitemapEntries, contentfulTagRest, contentfulTagSitemapEntries, contentfulTemplateRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createDownloadHandler, createResponsiveVisual, createRevalidationHandler, createSitemapProvider, customTypeTag, filterRelatedArticles, getAllSitemapEntries, getCacheTags, getCacheTagsForPreview, getCacheTagsForProduction, getContentfulClient, getPreviewEntryInfo, getRetryAfter, isBrowserViewable, isContentfulError, isRateLimitError, isRetryableError, isValidDate, locationTag, lookupAsset, notEmpty, pageTag, personTag, resolveLink, resolveLinks, resolveRichTextDocument, revalidateSingleTag, revalidateTags, safeDate, tagTag, templateTag, withRetry };
|
package/dist/index.js
CHANGED
|
@@ -1175,6 +1175,13 @@ async function fetchSingleEntity(context, config, fetchConfig, options) {
|
|
|
1175
1175
|
},
|
|
1176
1176
|
requestOptions
|
|
1177
1177
|
);
|
|
1178
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
|
|
1179
|
+
console.log(`[Contentful Fetch] ${fetchConfig.contentType}`, {
|
|
1180
|
+
query: fetchConfig.query,
|
|
1181
|
+
cacheTags,
|
|
1182
|
+
total: response.total
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1178
1185
|
const entry = response.items[0];
|
|
1179
1186
|
if (!entry || !entry.fields) {
|
|
1180
1187
|
return { data: null, errors: [] };
|
|
@@ -1315,20 +1322,97 @@ async function contentfulArticleRest(context, config, slug, articleTypeSlug, opt
|
|
|
1315
1322
|
}
|
|
1316
1323
|
|
|
1317
1324
|
// src/api/article-type.ts
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1325
|
+
init_utils();
|
|
1326
|
+
async function contentfulArticleTypeRest(context, config, slug, options) {
|
|
1327
|
+
const client = getContentfulClient(config, options?.preview);
|
|
1328
|
+
const articleTypeCacheTags = getCacheTags("articleType", slug, options?.preview);
|
|
1329
|
+
const customTypeCacheTags = options?.customType ? getCacheTags("customType", options.customType, options?.preview) : [];
|
|
1330
|
+
const requestOptions = {
|
|
1331
|
+
...options,
|
|
1332
|
+
next: {
|
|
1333
|
+
...options?.next,
|
|
1334
|
+
tags: [...articleTypeCacheTags, ...customTypeCacheTags]
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
const fetchFn = async () => {
|
|
1338
|
+
const articleTypePromise = client.getEntries(
|
|
1339
|
+
{
|
|
1340
|
+
content_type: "articleType",
|
|
1341
|
+
"fields.slug": slug,
|
|
1342
|
+
include: 10,
|
|
1343
|
+
locale: options?.locale,
|
|
1344
|
+
limit: 1
|
|
1345
|
+
},
|
|
1346
|
+
requestOptions
|
|
1347
|
+
);
|
|
1348
|
+
const customTypePromise = options?.customType ? client.getEntries(
|
|
1349
|
+
{
|
|
1350
|
+
content_type: "customType",
|
|
1351
|
+
"fields.slug": options.customType,
|
|
1352
|
+
include: 10,
|
|
1353
|
+
locale: options?.locale,
|
|
1354
|
+
limit: 1
|
|
1355
|
+
},
|
|
1356
|
+
requestOptions
|
|
1357
|
+
) : Promise.resolve(null);
|
|
1358
|
+
const [articleTypeResponse, customTypeResponse] = await Promise.all([
|
|
1359
|
+
articleTypePromise,
|
|
1360
|
+
customTypePromise
|
|
1361
|
+
]);
|
|
1362
|
+
const articleTypeEntry = articleTypeResponse.items[0];
|
|
1363
|
+
if (!articleTypeEntry || !articleTypeEntry.fields) {
|
|
1364
|
+
return { data: null, errors: [] };
|
|
1365
|
+
}
|
|
1366
|
+
const customTypeEntry = customTypeResponse?.items[0];
|
|
1367
|
+
try {
|
|
1368
|
+
const assets = convertAllAssets(articleTypeResponse, context);
|
|
1369
|
+
const rawAssets = convertAllRawAssets(articleTypeResponse);
|
|
1370
|
+
const includes = convertAllIncludes(articleTypeResponse);
|
|
1371
|
+
if (customTypeResponse) {
|
|
1372
|
+
const customAssets = convertAllAssets(customTypeResponse, context);
|
|
1373
|
+
const customRawAssets = convertAllRawAssets(customTypeResponse);
|
|
1374
|
+
const customIncludes = convertAllIncludes(customTypeResponse);
|
|
1375
|
+
for (const [key, value] of customAssets) assets.set(key, value);
|
|
1376
|
+
for (const [key, value] of customRawAssets) rawAssets.set(key, value);
|
|
1377
|
+
for (const [key, value] of customIncludes) includes.set(key, value);
|
|
1378
|
+
}
|
|
1379
|
+
const fullContext = {
|
|
1380
|
+
...context,
|
|
1381
|
+
includes,
|
|
1382
|
+
assets,
|
|
1383
|
+
rawAssets,
|
|
1384
|
+
errors: []
|
|
1385
|
+
};
|
|
1386
|
+
const converted = context.articleTypeResolver(fullContext, articleTypeEntry, customTypeEntry);
|
|
1387
|
+
if (converted?.icons && converted.icons.length > 0) {
|
|
1388
|
+
const processedIcons = await processIconsForSprite(converted.icons);
|
|
1389
|
+
converted.icons = processedIcons.length > 0 ? processedIcons : void 0;
|
|
1390
|
+
}
|
|
1391
|
+
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
1392
|
+
console.error(`CMS conversion errors for articleType:`, {
|
|
1393
|
+
entryId: articleTypeEntry.sys.id,
|
|
1394
|
+
slug,
|
|
1395
|
+
errors: fullContext.errors
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
return { data: converted, errors: fullContext.errors };
|
|
1399
|
+
} catch (error) {
|
|
1400
|
+
const entryId = articleTypeEntry?.sys.id || "unknown";
|
|
1401
|
+
const entryType = articleTypeEntry?.sys.contentType?.sys?.id;
|
|
1402
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1403
|
+
const cmsError = {
|
|
1404
|
+
entryId,
|
|
1405
|
+
entryType,
|
|
1406
|
+
message: errorMessage,
|
|
1407
|
+
error
|
|
1408
|
+
};
|
|
1409
|
+
return { data: null, errors: [cmsError] };
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
if (options?.retry) {
|
|
1413
|
+
return await withRetry(fetchFn, options.retry);
|
|
1414
|
+
}
|
|
1415
|
+
return await fetchFn();
|
|
1332
1416
|
}
|
|
1333
1417
|
|
|
1334
1418
|
// src/api/asset.ts
|
|
@@ -1405,6 +1489,18 @@ function createDownloadHandler(config) {
|
|
|
1405
1489
|
};
|
|
1406
1490
|
}
|
|
1407
1491
|
|
|
1492
|
+
// src/converters/schema.ts
|
|
1493
|
+
function baseSchemaConverter(_context, entry) {
|
|
1494
|
+
const { sys, fields } = entry;
|
|
1495
|
+
const { cmsLabel, markup } = fields;
|
|
1496
|
+
return {
|
|
1497
|
+
id: sys.id,
|
|
1498
|
+
name: cmsLabel,
|
|
1499
|
+
markup: markup ?? "",
|
|
1500
|
+
description: `Schema for ${cmsLabel}`
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1408
1504
|
// src/converters/resolver.ts
|
|
1409
1505
|
function resolveHelper(context, fromId, entry, getResolver) {
|
|
1410
1506
|
const id = entry.sys.id;
|
|
@@ -1431,6 +1527,14 @@ function resolveHelper(context, fromId, entry, getResolver) {
|
|
|
1431
1527
|
}
|
|
1432
1528
|
return possibleEntry.resolved;
|
|
1433
1529
|
}
|
|
1530
|
+
function resolveSchema(context, fromId, entry) {
|
|
1531
|
+
return resolveHelper(
|
|
1532
|
+
context,
|
|
1533
|
+
fromId,
|
|
1534
|
+
entry,
|
|
1535
|
+
() => baseSchemaConverter
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1434
1538
|
function resolveLink(context, fromId, entry) {
|
|
1435
1539
|
return resolveHelper(
|
|
1436
1540
|
context,
|
|
@@ -1853,6 +1957,7 @@ function baseArticleConverter(context, entry) {
|
|
|
1853
1957
|
topContent: topContentLinks,
|
|
1854
1958
|
bottomContent: bottomContentLinks,
|
|
1855
1959
|
articleType,
|
|
1960
|
+
structuredData,
|
|
1856
1961
|
...simpleFields
|
|
1857
1962
|
} = fields;
|
|
1858
1963
|
const articleTypeLink = resolveLink(context, id, articleType);
|
|
@@ -1887,6 +1992,7 @@ function baseArticleConverter(context, entry) {
|
|
|
1887
1992
|
tags: tags?.map((tag) => resolveLink(context, id, tag)),
|
|
1888
1993
|
contents,
|
|
1889
1994
|
icons,
|
|
1995
|
+
structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
|
|
1890
1996
|
...simpleFields,
|
|
1891
1997
|
// Note: summary field exists in Contentful but is not part of IArticle interface
|
|
1892
1998
|
// Keeping it in simpleFields for potential future use
|
|
@@ -1931,29 +2037,25 @@ function baseArticleTypeLinkConverter(context, entry) {
|
|
|
1931
2037
|
`Invalid content type: expected "articleType", got "${sys.contentType.sys.id}"`
|
|
1932
2038
|
);
|
|
1933
2039
|
}
|
|
2040
|
+
const { name, featuredImage, slug, ...simpleFields } = fields;
|
|
1934
2041
|
return createInternalLink(
|
|
1935
2042
|
sys.id,
|
|
1936
2043
|
{
|
|
1937
|
-
cmsLabel:
|
|
1938
|
-
title:
|
|
1939
|
-
featuredImage
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
indexed: fields.indexed,
|
|
1943
|
-
hidden: fields.hidden,
|
|
1944
|
-
slug: fields.slug
|
|
2044
|
+
cmsLabel: name,
|
|
2045
|
+
title: name,
|
|
2046
|
+
featuredImage,
|
|
2047
|
+
slug,
|
|
2048
|
+
...simpleFields
|
|
1945
2049
|
},
|
|
1946
2050
|
context,
|
|
1947
|
-
context.urlCalculators.articleType(
|
|
1948
|
-
"ArticleType"
|
|
1949
|
-
{ indexPageSlug: fields.indexPageSlug }
|
|
2051
|
+
context.urlCalculators.articleType(slug),
|
|
2052
|
+
"ArticleType"
|
|
1950
2053
|
);
|
|
1951
2054
|
}
|
|
1952
|
-
function baseArticleTypeConverter(context, entry) {
|
|
2055
|
+
function baseArticleTypeConverter(context, entry, customTypeEntry) {
|
|
1953
2056
|
const { sys, fields } = entry;
|
|
1954
2057
|
const { id } = sys;
|
|
1955
2058
|
const {
|
|
1956
|
-
indexPageSlug,
|
|
1957
2059
|
indexPageName,
|
|
1958
2060
|
indexPageDescription,
|
|
1959
2061
|
featuredImage,
|
|
@@ -1962,12 +2064,17 @@ function baseArticleTypeConverter(context, entry) {
|
|
|
1962
2064
|
indexPageTemplate: templateLink,
|
|
1963
2065
|
indexPageTopContent: topContentLinks,
|
|
1964
2066
|
structuredData,
|
|
1965
|
-
|
|
2067
|
+
indexPageStructuredData,
|
|
2068
|
+
slug,
|
|
1966
2069
|
...other
|
|
1967
2070
|
} = fields;
|
|
1968
|
-
const
|
|
1969
|
-
|
|
1970
|
-
|
|
2071
|
+
const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
|
|
2072
|
+
let template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
2073
|
+
if (!template && customTypeEntry?.fields.template) {
|
|
2074
|
+
template = resolveTemplate(context, customTypeEntry.fields.template);
|
|
2075
|
+
}
|
|
2076
|
+
const menu = menuLink ? resolveNavigation(context, menuLink) : customTypeEntry?.fields.menu ? resolveNavigation(context, customTypeEntry.fields.menu) : template?.menu;
|
|
2077
|
+
const footer = footerLink ? resolveNavigation(context, footerLink) : customTypeEntry?.fields.footer ? resolveNavigation(context, customTypeEntry.fields.footer) : template?.footer;
|
|
1971
2078
|
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1972
2079
|
const preContent = template?.preContent ?? [];
|
|
1973
2080
|
const postContent = template?.postContent ?? [];
|
|
@@ -1982,17 +2089,23 @@ function baseArticleTypeConverter(context, entry) {
|
|
|
1982
2089
|
const articleType = {
|
|
1983
2090
|
type: "Article type",
|
|
1984
2091
|
id,
|
|
1985
|
-
slug
|
|
2092
|
+
slug,
|
|
1986
2093
|
title: makeContentfulTitle(indexPageName, sys.id),
|
|
1987
2094
|
description: makeContentfulDescription(indexPageDescription, sys.id),
|
|
1988
2095
|
featuredImage: lookupAsset(context, featuredImage),
|
|
1989
2096
|
contents,
|
|
1990
2097
|
icons,
|
|
1991
|
-
structuredData
|
|
2098
|
+
structuredData: [
|
|
2099
|
+
...structuredData?.map((link) => resolveSchema(context, id, link)) ?? [],
|
|
2100
|
+
...indexPageStructuredData?.map((link) => resolveSchema(context, id, link)) ?? []
|
|
2101
|
+
].filter((item) => item !== null),
|
|
1992
2102
|
menu: finalMenu,
|
|
1993
2103
|
footer: finalFooter,
|
|
1994
2104
|
...other
|
|
1995
2105
|
};
|
|
2106
|
+
if (customType) {
|
|
2107
|
+
articleType.customType = customType;
|
|
2108
|
+
}
|
|
1996
2109
|
return articleType;
|
|
1997
2110
|
}
|
|
1998
2111
|
|
|
@@ -2106,7 +2219,6 @@ function baseCustomTypeConverter(context, entry) {
|
|
|
2106
2219
|
const { id } = sys;
|
|
2107
2220
|
const {
|
|
2108
2221
|
slug,
|
|
2109
|
-
indexPageSlug,
|
|
2110
2222
|
indexPageName,
|
|
2111
2223
|
indexPageDescription,
|
|
2112
2224
|
featuredImage,
|
|
@@ -2115,6 +2227,7 @@ function baseCustomTypeConverter(context, entry) {
|
|
|
2115
2227
|
indexPageTemplate: templateLink,
|
|
2116
2228
|
indexPageTopContent: topContentLinks,
|
|
2117
2229
|
structuredData,
|
|
2230
|
+
indexPageStructuredData,
|
|
2118
2231
|
...other
|
|
2119
2232
|
} = fields;
|
|
2120
2233
|
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
@@ -2133,7 +2246,6 @@ function baseCustomTypeConverter(context, entry) {
|
|
|
2133
2246
|
type: "Custom type",
|
|
2134
2247
|
id,
|
|
2135
2248
|
slug,
|
|
2136
|
-
indexPageSlug,
|
|
2137
2249
|
indexPageName: makeContentfulTitle(indexPageName, sys.id),
|
|
2138
2250
|
indexPageDescription: makeContentfulDescription(indexPageDescription, sys.id),
|
|
2139
2251
|
title: makeContentfulTitle(indexPageName, sys.id),
|
|
@@ -2141,7 +2253,10 @@ function baseCustomTypeConverter(context, entry) {
|
|
|
2141
2253
|
featuredImage: lookupAsset(context, featuredImage),
|
|
2142
2254
|
contents,
|
|
2143
2255
|
icons,
|
|
2144
|
-
structuredData
|
|
2256
|
+
structuredData: [
|
|
2257
|
+
...structuredData?.map((link) => resolveSchema(context, id, link)) ?? [],
|
|
2258
|
+
...indexPageStructuredData?.map((link) => resolveSchema(context, id, link)) ?? []
|
|
2259
|
+
].filter((item) => item !== null),
|
|
2145
2260
|
menu,
|
|
2146
2261
|
footer,
|
|
2147
2262
|
...other
|
|
@@ -2166,10 +2281,10 @@ function baseCustomTypeLinkConverter(context, entry) {
|
|
|
2166
2281
|
textColour: fields.textColour,
|
|
2167
2282
|
indexed: fields.indexed,
|
|
2168
2283
|
hidden: fields.hidden,
|
|
2169
|
-
slug: fields.
|
|
2284
|
+
slug: fields.slug
|
|
2170
2285
|
},
|
|
2171
2286
|
context,
|
|
2172
|
-
context.urlCalculators.customType(fields.
|
|
2287
|
+
context.urlCalculators.customType(fields.slug),
|
|
2173
2288
|
"CustomType"
|
|
2174
2289
|
);
|
|
2175
2290
|
}
|
|
@@ -2292,6 +2407,7 @@ function basePageConverter(context, entry) {
|
|
|
2292
2407
|
template: templateLink,
|
|
2293
2408
|
topContent: topContentLinks,
|
|
2294
2409
|
bottomContent: bottomContentLinks,
|
|
2410
|
+
structuredData,
|
|
2295
2411
|
...simpleFields
|
|
2296
2412
|
} = fields;
|
|
2297
2413
|
const pageMenuNav = pageMenu ? resolveNavigation(context, pageMenu) : void 0;
|
|
@@ -2327,6 +2443,7 @@ function basePageConverter(context, entry) {
|
|
|
2327
2443
|
tags: tags?.map((tag) => resolveLink(context, id, tag)),
|
|
2328
2444
|
contents,
|
|
2329
2445
|
icons,
|
|
2446
|
+
structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
|
|
2330
2447
|
...simpleFields,
|
|
2331
2448
|
menu: finalMenu,
|
|
2332
2449
|
footer: finalFooter
|
|
@@ -2442,7 +2559,16 @@ function basePersonConverter(context, entry, customTypeEntry) {
|
|
|
2442
2559
|
if (contentType.sys.id !== "person") {
|
|
2443
2560
|
throw new Error(`Invalid content type: expected "person", got "${contentType.sys.id}"`);
|
|
2444
2561
|
}
|
|
2445
|
-
const {
|
|
2562
|
+
const {
|
|
2563
|
+
slug,
|
|
2564
|
+
name,
|
|
2565
|
+
description,
|
|
2566
|
+
media,
|
|
2567
|
+
bio: bioField,
|
|
2568
|
+
content: contentLinks,
|
|
2569
|
+
structuredData,
|
|
2570
|
+
...rest
|
|
2571
|
+
} = fields;
|
|
2446
2572
|
const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
|
|
2447
2573
|
const template = customTypeEntry?.fields.template ? resolveTemplate(context, customTypeEntry.fields.template) : null;
|
|
2448
2574
|
const personContent = contentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
@@ -2471,6 +2597,7 @@ function basePersonConverter(context, entry, customTypeEntry) {
|
|
|
2471
2597
|
footer,
|
|
2472
2598
|
icons,
|
|
2473
2599
|
customType,
|
|
2600
|
+
structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
|
|
2474
2601
|
...rest
|
|
2475
2602
|
};
|
|
2476
2603
|
}
|
|
@@ -2493,7 +2620,7 @@ function baseTagLinkConverter(context, entry) {
|
|
|
2493
2620
|
"Tag"
|
|
2494
2621
|
);
|
|
2495
2622
|
}
|
|
2496
|
-
function baseTagConverter(context, entry) {
|
|
2623
|
+
function baseTagConverter(context, entry, customTypeEntry) {
|
|
2497
2624
|
const { sys, fields } = entry;
|
|
2498
2625
|
const { id } = sys;
|
|
2499
2626
|
const {
|
|
@@ -2506,11 +2633,16 @@ function baseTagConverter(context, entry) {
|
|
|
2506
2633
|
footer: footerLink,
|
|
2507
2634
|
template: templateLink,
|
|
2508
2635
|
topContent: topContentLinks,
|
|
2636
|
+
structuredData,
|
|
2509
2637
|
...rest
|
|
2510
2638
|
} = fields;
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
|
|
2639
|
+
const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
|
|
2640
|
+
let template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
2641
|
+
if (!template && customTypeEntry?.fields.template) {
|
|
2642
|
+
template = resolveTemplate(context, customTypeEntry.fields.template);
|
|
2643
|
+
}
|
|
2644
|
+
const menu = menuLink ? resolveNavigation(context, menuLink) : customTypeEntry?.fields.menu ? resolveNavigation(context, customTypeEntry.fields.menu) : template?.menu;
|
|
2645
|
+
const footer = footerLink ? resolveNavigation(context, footerLink) : customTypeEntry?.fields.footer ? resolveNavigation(context, customTypeEntry.fields.footer) : template?.footer;
|
|
2514
2646
|
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
2515
2647
|
const preContent = template?.preContent ?? [];
|
|
2516
2648
|
const postContent = template?.postContent ?? [];
|
|
@@ -2532,10 +2664,14 @@ function baseTagConverter(context, entry) {
|
|
|
2532
2664
|
tagType: tagTypeName ?? null,
|
|
2533
2665
|
contents,
|
|
2534
2666
|
icons,
|
|
2667
|
+
structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
|
|
2535
2668
|
...rest,
|
|
2536
2669
|
menu,
|
|
2537
2670
|
footer
|
|
2538
2671
|
};
|
|
2672
|
+
if (customType) {
|
|
2673
|
+
tag.customType = customType;
|
|
2674
|
+
}
|
|
2539
2675
|
return tag;
|
|
2540
2676
|
}
|
|
2541
2677
|
|
|
@@ -2578,17 +2714,17 @@ function createBaseConverterContext(urlCalculators) {
|
|
|
2578
2714
|
}
|
|
2579
2715
|
|
|
2580
2716
|
// src/api/custom-type.ts
|
|
2581
|
-
async function contentfulCustomTypeRest(context, config,
|
|
2717
|
+
async function contentfulCustomTypeRest(context, config, slug, options) {
|
|
2582
2718
|
return fetchSingleEntity(
|
|
2583
2719
|
context,
|
|
2584
2720
|
config,
|
|
2585
2721
|
{
|
|
2586
2722
|
contentType: "customType",
|
|
2587
2723
|
cacheTagType: "customType",
|
|
2588
|
-
cacheTagIdentifier:
|
|
2589
|
-
query: { "fields.
|
|
2724
|
+
cacheTagIdentifier: slug,
|
|
2725
|
+
query: { "fields.slug": slug },
|
|
2590
2726
|
resolver: (ctx, entry) => ctx.customTypeResolver(ctx, entry),
|
|
2591
|
-
errorLogContext: {
|
|
2727
|
+
errorLogContext: { slug }
|
|
2592
2728
|
},
|
|
2593
2729
|
options
|
|
2594
2730
|
);
|
|
@@ -2882,7 +3018,7 @@ async function getPreviewEntryInfo(context, config, entryId, options) {
|
|
|
2882
3018
|
};
|
|
2883
3019
|
}
|
|
2884
3020
|
case "articleType": {
|
|
2885
|
-
const slug = fields.
|
|
3021
|
+
const slug = fields.slug;
|
|
2886
3022
|
if (!slug) return null;
|
|
2887
3023
|
return {
|
|
2888
3024
|
contentType: "articleType",
|
|
@@ -2912,7 +3048,7 @@ async function getPreviewEntryInfo(context, config, entryId, options) {
|
|
|
2912
3048
|
};
|
|
2913
3049
|
}
|
|
2914
3050
|
case "customType": {
|
|
2915
|
-
const slug = fields.
|
|
3051
|
+
const slug = fields.slug;
|
|
2916
3052
|
if (!slug) return null;
|
|
2917
3053
|
return {
|
|
2918
3054
|
contentType: "customType",
|
|
@@ -3063,20 +3199,94 @@ function createSitemapProvider(fetcher, sitemapConfig) {
|
|
|
3063
3199
|
}
|
|
3064
3200
|
|
|
3065
3201
|
// src/api/tag.ts
|
|
3202
|
+
init_utils();
|
|
3066
3203
|
async function contentfulTagRest(context, config, slug, options) {
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3204
|
+
const client = getContentfulClient(config, options?.preview);
|
|
3205
|
+
const tagCacheTags = getCacheTags("tag", slug, options?.preview);
|
|
3206
|
+
const customTypeCacheTags = options?.customType ? getCacheTags("customType", options.customType, options?.preview) : [];
|
|
3207
|
+
const requestOptions = {
|
|
3208
|
+
...options,
|
|
3209
|
+
next: {
|
|
3210
|
+
...options?.next,
|
|
3211
|
+
tags: [...tagCacheTags, ...customTypeCacheTags]
|
|
3212
|
+
}
|
|
3213
|
+
};
|
|
3214
|
+
const fetchFn = async () => {
|
|
3215
|
+
const tagPromise = client.getEntries(
|
|
3216
|
+
{
|
|
3217
|
+
content_type: "tag",
|
|
3218
|
+
"fields.slug": slug,
|
|
3219
|
+
include: 10,
|
|
3220
|
+
locale: options?.locale,
|
|
3221
|
+
limit: 1
|
|
3222
|
+
},
|
|
3223
|
+
requestOptions
|
|
3224
|
+
);
|
|
3225
|
+
const customTypePromise = options?.customType ? client.getEntries(
|
|
3226
|
+
{
|
|
3227
|
+
content_type: "customType",
|
|
3228
|
+
"fields.slug": options.customType,
|
|
3229
|
+
include: 10,
|
|
3230
|
+
locale: options?.locale,
|
|
3231
|
+
limit: 1
|
|
3232
|
+
},
|
|
3233
|
+
requestOptions
|
|
3234
|
+
) : Promise.resolve(null);
|
|
3235
|
+
const [tagResponse, customTypeResponse] = await Promise.all([tagPromise, customTypePromise]);
|
|
3236
|
+
const tagEntry = tagResponse.items[0];
|
|
3237
|
+
if (!tagEntry || !tagEntry.fields) {
|
|
3238
|
+
return { data: null, errors: [] };
|
|
3239
|
+
}
|
|
3240
|
+
const customTypeEntry = customTypeResponse?.items[0];
|
|
3241
|
+
try {
|
|
3242
|
+
const assets = convertAllAssets(tagResponse, context);
|
|
3243
|
+
const rawAssets = convertAllRawAssets(tagResponse);
|
|
3244
|
+
const includes = convertAllIncludes(tagResponse);
|
|
3245
|
+
if (customTypeResponse) {
|
|
3246
|
+
const customAssets = convertAllAssets(customTypeResponse, context);
|
|
3247
|
+
const customRawAssets = convertAllRawAssets(customTypeResponse);
|
|
3248
|
+
const customIncludes = convertAllIncludes(customTypeResponse);
|
|
3249
|
+
for (const [key, value] of customAssets) assets.set(key, value);
|
|
3250
|
+
for (const [key, value] of customRawAssets) rawAssets.set(key, value);
|
|
3251
|
+
for (const [key, value] of customIncludes) includes.set(key, value);
|
|
3252
|
+
}
|
|
3253
|
+
const fullContext = {
|
|
3254
|
+
...context,
|
|
3255
|
+
includes,
|
|
3256
|
+
assets,
|
|
3257
|
+
rawAssets,
|
|
3258
|
+
errors: []
|
|
3259
|
+
};
|
|
3260
|
+
const converted = context.tagResolver(fullContext, tagEntry, customTypeEntry);
|
|
3261
|
+
if (converted?.icons && converted.icons.length > 0) {
|
|
3262
|
+
const processedIcons = await processIconsForSprite(converted.icons);
|
|
3263
|
+
converted.icons = processedIcons.length > 0 ? processedIcons : void 0;
|
|
3264
|
+
}
|
|
3265
|
+
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
3266
|
+
console.error(`CMS conversion errors for tag:`, {
|
|
3267
|
+
entryId: tagEntry.sys.id,
|
|
3268
|
+
slug,
|
|
3269
|
+
errors: fullContext.errors
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3272
|
+
return { data: converted, errors: fullContext.errors };
|
|
3273
|
+
} catch (error) {
|
|
3274
|
+
const entryId = tagEntry?.sys.id || "unknown";
|
|
3275
|
+
const entryType = tagEntry?.sys.contentType?.sys?.id;
|
|
3276
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
3277
|
+
const cmsError = {
|
|
3278
|
+
entryId,
|
|
3279
|
+
entryType,
|
|
3280
|
+
message: errorMessage,
|
|
3281
|
+
error
|
|
3282
|
+
};
|
|
3283
|
+
return { data: null, errors: [cmsError] };
|
|
3284
|
+
}
|
|
3285
|
+
};
|
|
3286
|
+
if (options?.retry) {
|
|
3287
|
+
return await withRetry(fetchFn, options.retry);
|
|
3288
|
+
}
|
|
3289
|
+
return await fetchFn();
|
|
3080
3290
|
}
|
|
3081
3291
|
|
|
3082
3292
|
// src/api/template.ts
|
|
@@ -3135,13 +3345,9 @@ init_utils();
|
|
|
3135
3345
|
var defaultLocale = "en-US";
|
|
3136
3346
|
var articleTypeHandler = {
|
|
3137
3347
|
extract: (data) => ({
|
|
3138
|
-
slug: data.fields?.slug?.[defaultLocale]
|
|
3139
|
-
indexPageSlug: data.fields?.indexPageSlug?.[defaultLocale]
|
|
3348
|
+
slug: data.fields?.slug?.[defaultLocale]
|
|
3140
3349
|
}),
|
|
3141
|
-
makeTags: (extracted) => [
|
|
3142
|
-
extracted.slug ? articleTypeTag(extracted.slug) : void 0,
|
|
3143
|
-
extracted.indexPageSlug ? articleTypeIndexTag(extracted.indexPageSlug) : void 0
|
|
3144
|
-
],
|
|
3350
|
+
makeTags: (extracted) => [extracted.slug ? articleTypeIndexTag(extracted.slug) : void 0],
|
|
3145
3351
|
getGlobalTags: () => [ArticleTypeTag, ArticleTypeIndexTag]
|
|
3146
3352
|
};
|
|
3147
3353
|
var articleHandler = {
|