@se-studio/contentful-rest-api 1.0.35 → 1.0.37

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.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
1325
+ init_utils();
1318
1326
  async function contentfulArticleTypeRest(context, config, indexPageSlug, options) {
1319
- return fetchSingleEntity(
1320
- context,
1321
- config,
1322
- {
1323
- contentType: "articleType",
1324
- cacheTagType: "articleType",
1325
- cacheTagIdentifier: indexPageSlug,
1326
- query: { "fields.indexPageSlug": indexPageSlug },
1327
- resolver: (ctx, entry) => ctx.articleTypeResolver(ctx, entry),
1328
- errorLogContext: { indexPageSlug }
1329
- },
1330
- options
1331
- );
1327
+ const client = getContentfulClient(config, options?.preview);
1328
+ const articleTypeCacheTags = getCacheTags("articleType", indexPageSlug, 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.indexPageSlug": indexPageSlug,
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
+ indexPageSlug,
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
@@ -1895,12 +2001,6 @@ function baseArticleConverter(context, entry) {
1895
2001
  };
1896
2002
  return article;
1897
2003
  }
1898
- function calculateArticleTypeHref(slug) {
1899
- return `/${slug}/`;
1900
- }
1901
- function calculateArticleHref(articleTypeSlug, slug, _primaryTagSlug) {
1902
- return `${calculateArticleTypeHref(articleTypeSlug)}${slug}/`;
1903
- }
1904
2004
  function baseArticleLinkConverter(context, entry) {
1905
2005
  const { sys, fields } = entry;
1906
2006
  if (sys.contentType.sys.id !== "article") {
@@ -1955,7 +2055,7 @@ function baseArticleTypeLinkConverter(context, entry) {
1955
2055
  { indexPageSlug: fields.indexPageSlug }
1956
2056
  );
1957
2057
  }
1958
- function baseArticleTypeConverter(context, entry) {
2058
+ function baseArticleTypeConverter(context, entry, customTypeEntry) {
1959
2059
  const { sys, fields } = entry;
1960
2060
  const { id } = sys;
1961
2061
  const {
@@ -1968,12 +2068,17 @@ function baseArticleTypeConverter(context, entry) {
1968
2068
  indexPageTemplate: templateLink,
1969
2069
  indexPageTopContent: topContentLinks,
1970
2070
  structuredData,
2071
+ indexPageStructuredData,
1971
2072
  slug: _slug,
1972
2073
  ...other
1973
2074
  } = fields;
1974
- const template = templateLink ? resolveTemplate(context, templateLink) : null;
1975
- const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
1976
- const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
2075
+ const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
2076
+ let template = templateLink ? resolveTemplate(context, templateLink) : null;
2077
+ if (!template && customTypeEntry?.fields.indexPageTemplate) {
2078
+ template = resolveTemplate(context, customTypeEntry.fields.indexPageTemplate);
2079
+ }
2080
+ const menu = menuLink ? resolveNavigation(context, menuLink) : customTypeEntry?.fields.menu ? resolveNavigation(context, customTypeEntry.fields.menu) : template?.menu;
2081
+ const footer = footerLink ? resolveNavigation(context, footerLink) : customTypeEntry?.fields.footer ? resolveNavigation(context, customTypeEntry.fields.footer) : template?.footer;
1977
2082
  const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1978
2083
  const preContent = template?.preContent ?? [];
1979
2084
  const postContent = template?.postContent ?? [];
@@ -1994,11 +2099,17 @@ function baseArticleTypeConverter(context, entry) {
1994
2099
  featuredImage: lookupAsset(context, featuredImage),
1995
2100
  contents,
1996
2101
  icons,
1997
- structuredData,
2102
+ structuredData: [
2103
+ ...structuredData?.map((link) => resolveSchema(context, id, link)) ?? [],
2104
+ ...indexPageStructuredData?.map((link) => resolveSchema(context, id, link)) ?? []
2105
+ ].filter((item) => item !== null),
1998
2106
  menu: finalMenu,
1999
2107
  footer: finalFooter,
2000
2108
  ...other
2001
2109
  };
2110
+ if (customType) {
2111
+ articleType.customType = customType;
2112
+ }
2002
2113
  return articleType;
2003
2114
  }
2004
2115
 
@@ -2121,6 +2232,7 @@ function baseCustomTypeConverter(context, entry) {
2121
2232
  indexPageTemplate: templateLink,
2122
2233
  indexPageTopContent: topContentLinks,
2123
2234
  structuredData,
2235
+ indexPageStructuredData,
2124
2236
  ...other
2125
2237
  } = fields;
2126
2238
  const template = templateLink ? resolveTemplate(context, templateLink) : null;
@@ -2147,7 +2259,10 @@ function baseCustomTypeConverter(context, entry) {
2147
2259
  featuredImage: lookupAsset(context, featuredImage),
2148
2260
  contents,
2149
2261
  icons,
2150
- structuredData,
2262
+ structuredData: [
2263
+ ...structuredData?.map((link) => resolveSchema(context, id, link)) ?? [],
2264
+ ...indexPageStructuredData?.map((link) => resolveSchema(context, id, link)) ?? []
2265
+ ].filter((item) => item !== null),
2151
2266
  menu,
2152
2267
  footer,
2153
2268
  ...other
@@ -2179,9 +2294,6 @@ function baseCustomTypeLinkConverter(context, entry) {
2179
2294
  "CustomType"
2180
2295
  );
2181
2296
  }
2182
- function calculateCustomTypeHref(slug) {
2183
- return `/${slug}/`;
2184
- }
2185
2297
 
2186
2298
  // src/converters/externalComponent.ts
2187
2299
  function baseExternalComponentConverter(_context, entry) {
@@ -2301,6 +2413,7 @@ function basePageConverter(context, entry) {
2301
2413
  template: templateLink,
2302
2414
  topContent: topContentLinks,
2303
2415
  bottomContent: bottomContentLinks,
2416
+ structuredData,
2304
2417
  ...simpleFields
2305
2418
  } = fields;
2306
2419
  const pageMenuNav = pageMenu ? resolveNavigation(context, pageMenu) : void 0;
@@ -2336,6 +2449,7 @@ function basePageConverter(context, entry) {
2336
2449
  tags: tags?.map((tag) => resolveLink(context, id, tag)),
2337
2450
  contents,
2338
2451
  icons,
2452
+ structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
2339
2453
  ...simpleFields,
2340
2454
  menu: finalMenu,
2341
2455
  footer: finalFooter
@@ -2405,9 +2519,6 @@ function basePageVariantLinkConverter(context, entry) {
2405
2519
  }
2406
2520
 
2407
2521
  // src/converters/person.ts
2408
- function calculatePersonHref(slug) {
2409
- return `/people/${slug}/`;
2410
- }
2411
2522
  function basePersonLinkConverter(context, entry) {
2412
2523
  const { sys, fields } = entry;
2413
2524
  const {
@@ -2446,11 +2557,58 @@ function basePersonLinkConverter(context, entry) {
2446
2557
  }
2447
2558
  );
2448
2559
  }
2560
+ function basePersonConverter(context, entry, customTypeEntry) {
2561
+ const {
2562
+ sys: { id, contentType },
2563
+ fields
2564
+ } = entry;
2565
+ if (contentType.sys.id !== "person") {
2566
+ throw new Error(`Invalid content type: expected "person", got "${contentType.sys.id}"`);
2567
+ }
2568
+ const {
2569
+ slug,
2570
+ name,
2571
+ description,
2572
+ media,
2573
+ bio: bioField,
2574
+ content: contentLinks,
2575
+ structuredData,
2576
+ ...rest
2577
+ } = fields;
2578
+ const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
2579
+ const template = customTypeEntry?.fields.template ? resolveTemplate(context, customTypeEntry.fields.template) : null;
2580
+ const personContent = contentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
2581
+ const preContent = template?.preContent ?? [];
2582
+ const postContent = template?.postContent ?? [];
2583
+ const contents = addPositionMetadata([...preContent, ...personContent, ...postContent]);
2584
+ const menu = customTypeEntry?.fields.menu ? resolveNavigation(context, customTypeEntry.fields.menu) : template?.menu;
2585
+ const footer = customTypeEntry?.fields.footer ? resolveNavigation(context, customTypeEntry.fields.footer) : template?.footer;
2586
+ const icons = deduplicateIcons(
2587
+ collectIconsFromContent(contents),
2588
+ collectIconsFromNavigation(menu),
2589
+ collectIconsFromNavigation(footer)
2590
+ );
2591
+ return {
2592
+ type: "Person",
2593
+ id,
2594
+ slug,
2595
+ title: makeContentfulTitle(name, id),
2596
+ description: description ?? `Description for ${id}`,
2597
+ featuredImage: lookupAsset(context, media),
2598
+ // Person uses 'media' not 'featuredImage'
2599
+ href: context.urlCalculators.person(slug),
2600
+ bio: resolveRichTextDocument(context, id, bioField) ?? null,
2601
+ contents,
2602
+ menu,
2603
+ footer,
2604
+ icons,
2605
+ customType,
2606
+ structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
2607
+ ...rest
2608
+ };
2609
+ }
2449
2610
 
2450
2611
  // src/converters/tag.ts
2451
- function calculateTagHref(slug) {
2452
- return `/tag/${slug}/`;
2453
- }
2454
2612
  function baseTagLinkConverter(context, entry) {
2455
2613
  const { sys, fields } = entry;
2456
2614
  const { name, ...simpleFields } = fields;
@@ -2468,7 +2626,7 @@ function baseTagLinkConverter(context, entry) {
2468
2626
  "Tag"
2469
2627
  );
2470
2628
  }
2471
- function baseTagConverter(context, entry) {
2629
+ function baseTagConverter(context, entry, customTypeEntry) {
2472
2630
  const { sys, fields } = entry;
2473
2631
  const { id } = sys;
2474
2632
  const {
@@ -2481,11 +2639,16 @@ function baseTagConverter(context, entry) {
2481
2639
  footer: footerLink,
2482
2640
  template: templateLink,
2483
2641
  topContent: topContentLinks,
2642
+ structuredData,
2484
2643
  ...rest
2485
2644
  } = fields;
2486
- const template = templateLink ? resolveTemplate(context, templateLink) : null;
2487
- const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
2488
- const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
2645
+ const customType = customTypeEntry ? context.customTypeResolver(context, customTypeEntry) : void 0;
2646
+ let template = templateLink ? resolveTemplate(context, templateLink) : null;
2647
+ if (!template && customTypeEntry?.fields.template) {
2648
+ template = resolveTemplate(context, customTypeEntry.fields.template);
2649
+ }
2650
+ const menu = menuLink ? resolveNavigation(context, menuLink) : customTypeEntry?.fields.menu ? resolveNavigation(context, customTypeEntry.fields.menu) : template?.menu;
2651
+ const footer = footerLink ? resolveNavigation(context, footerLink) : customTypeEntry?.fields.footer ? resolveNavigation(context, customTypeEntry.fields.footer) : template?.footer;
2489
2652
  const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
2490
2653
  const preContent = template?.preContent ?? [];
2491
2654
  const postContent = template?.postContent ?? [];
@@ -2507,15 +2670,19 @@ function baseTagConverter(context, entry) {
2507
2670
  tagType: tagTypeName ?? null,
2508
2671
  contents,
2509
2672
  icons,
2673
+ structuredData: structuredData?.map((link) => resolveSchema(context, id, link)).filter((item) => item !== null),
2510
2674
  ...rest,
2511
2675
  menu,
2512
2676
  footer
2513
2677
  };
2678
+ if (customType) {
2679
+ tag.customType = customType;
2680
+ }
2514
2681
  return tag;
2515
2682
  }
2516
2683
 
2517
2684
  // src/api/context.ts
2518
- function createBaseConverterContext() {
2685
+ function createBaseConverterContext(urlCalculators) {
2519
2686
  const linkResolver = /* @__PURE__ */ new Map();
2520
2687
  linkResolver.set("page", basePageLinkConverter);
2521
2688
  linkResolver.set("article", baseArticleLinkConverter);
@@ -2535,21 +2702,13 @@ function createBaseConverterContext() {
2535
2702
  "externalComponent",
2536
2703
  baseExternalComponentConverter
2537
2704
  );
2538
- const urlCalculators = {
2539
- page: calculatePageHref,
2540
- pageVariant: calculatePageVariantHref,
2541
- article: calculateArticleHref,
2542
- articleType: calculateArticleTypeHref,
2543
- tag: calculateTagHref,
2544
- person: calculatePersonHref,
2545
- customType: calculateCustomTypeHref
2546
- };
2547
2705
  return {
2548
2706
  pageResolver: basePageConverter,
2549
2707
  navigationItemResolver: baseNavigationItemConverter,
2550
2708
  articleResolver: baseArticleConverter,
2551
2709
  articleTypeResolver: baseArticleTypeConverter,
2552
2710
  tagResolver: baseTagConverter,
2711
+ personResolver: basePersonConverter,
2553
2712
  customTypeResolver: baseCustomTypeConverter,
2554
2713
  componentResolver: baseComponentConverter,
2555
2714
  collectionResolver: baseCollectionConverter,
@@ -2717,6 +2876,100 @@ async function contentfulPageRest(context, config, slug, options) {
2717
2876
  );
2718
2877
  }
2719
2878
 
2879
+ // src/api/person.ts
2880
+ init_utils();
2881
+ async function contentfulPersonRest(context, config, slug, options) {
2882
+ const client = getContentfulClient(config, options?.preview);
2883
+ const personCacheTags = getCacheTags("person", slug, options?.preview);
2884
+ const customTypeCacheTags = options?.customType ? getCacheTags("customType", options.customType, options?.preview) : [];
2885
+ const requestOptions = {
2886
+ ...options,
2887
+ next: {
2888
+ ...options?.next,
2889
+ tags: [...personCacheTags, ...customTypeCacheTags]
2890
+ }
2891
+ };
2892
+ const fetchFn = async () => {
2893
+ const personPromise = client.getEntries(
2894
+ {
2895
+ content_type: "person",
2896
+ "fields.slug": slug,
2897
+ include: 10,
2898
+ locale: options?.locale,
2899
+ limit: 1
2900
+ },
2901
+ requestOptions
2902
+ );
2903
+ const customTypePromise = options?.customType ? client.getEntries(
2904
+ {
2905
+ content_type: "customType",
2906
+ "fields.slug": options.customType,
2907
+ include: 10,
2908
+ locale: options?.locale,
2909
+ limit: 1
2910
+ },
2911
+ requestOptions
2912
+ ) : Promise.resolve(null);
2913
+ const [personResponse, customTypeResponse] = await Promise.all([
2914
+ personPromise,
2915
+ customTypePromise
2916
+ ]);
2917
+ const personEntry = personResponse.items[0];
2918
+ if (!personEntry || !personEntry.fields) {
2919
+ return { data: null, errors: [] };
2920
+ }
2921
+ const customTypeEntry = customTypeResponse?.items[0];
2922
+ try {
2923
+ const assets = convertAllAssets(personResponse, context);
2924
+ const rawAssets = convertAllRawAssets(personResponse);
2925
+ const includes = convertAllIncludes(personResponse);
2926
+ if (customTypeResponse) {
2927
+ const customAssets = convertAllAssets(customTypeResponse, context);
2928
+ const customRawAssets = convertAllRawAssets(customTypeResponse);
2929
+ const customIncludes = convertAllIncludes(customTypeResponse);
2930
+ for (const [key, value] of customAssets) assets.set(key, value);
2931
+ for (const [key, value] of customRawAssets) rawAssets.set(key, value);
2932
+ for (const [key, value] of customIncludes) includes.set(key, value);
2933
+ }
2934
+ const fullContext = {
2935
+ ...context,
2936
+ includes,
2937
+ assets,
2938
+ rawAssets,
2939
+ errors: []
2940
+ };
2941
+ const converted = context.personResolver(fullContext, personEntry, customTypeEntry);
2942
+ if (converted?.icons && converted.icons.length > 0) {
2943
+ const processedIcons = await processIconsForSprite(converted.icons);
2944
+ converted.icons = processedIcons.length > 0 ? processedIcons : void 0;
2945
+ }
2946
+ if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
2947
+ console.error(`CMS conversion errors for person:`, {
2948
+ entryId: personEntry.sys.id,
2949
+ slug,
2950
+ errors: fullContext.errors
2951
+ });
2952
+ }
2953
+ return { data: converted, errors: fullContext.errors };
2954
+ } catch (error) {
2955
+ const entryId = personEntry?.sys.id || "unknown";
2956
+ const entryType = personEntry?.sys.contentType?.sys?.id;
2957
+ const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
2958
+ const cmsError = {
2959
+ entryId,
2960
+ entryType,
2961
+ message: errorMessage,
2962
+ error
2963
+ };
2964
+ return { data: null, errors: [cmsError] };
2965
+ }
2966
+ };
2967
+ if (options?.retry) {
2968
+ return await withRetry(fetchFn, options.retry);
2969
+ }
2970
+ return await fetchFn();
2971
+ }
2972
+
2720
2973
  // src/api/preview.ts
2721
2974
  async function getPreviewEntryInfo(context, config, entryId, options) {
2722
2975
  const client = getContentfulClient(config, true);
@@ -2952,20 +3205,94 @@ function createSitemapProvider(fetcher, sitemapConfig) {
2952
3205
  }
2953
3206
 
2954
3207
  // src/api/tag.ts
3208
+ init_utils();
2955
3209
  async function contentfulTagRest(context, config, slug, options) {
2956
- return fetchSingleEntity(
2957
- context,
2958
- config,
2959
- {
2960
- contentType: "tag",
2961
- cacheTagType: "tag",
2962
- cacheTagIdentifier: slug,
2963
- query: { "fields.slug": slug },
2964
- resolver: (ctx, entry) => ctx.tagResolver(ctx, entry),
2965
- errorLogContext: { slug }
2966
- },
2967
- options
2968
- );
3210
+ const client = getContentfulClient(config, options?.preview);
3211
+ const tagCacheTags = getCacheTags("tag", slug, options?.preview);
3212
+ const customTypeCacheTags = options?.customType ? getCacheTags("customType", options.customType, options?.preview) : [];
3213
+ const requestOptions = {
3214
+ ...options,
3215
+ next: {
3216
+ ...options?.next,
3217
+ tags: [...tagCacheTags, ...customTypeCacheTags]
3218
+ }
3219
+ };
3220
+ const fetchFn = async () => {
3221
+ const tagPromise = client.getEntries(
3222
+ {
3223
+ content_type: "tag",
3224
+ "fields.slug": slug,
3225
+ include: 10,
3226
+ locale: options?.locale,
3227
+ limit: 1
3228
+ },
3229
+ requestOptions
3230
+ );
3231
+ const customTypePromise = options?.customType ? client.getEntries(
3232
+ {
3233
+ content_type: "customType",
3234
+ "fields.slug": options.customType,
3235
+ include: 10,
3236
+ locale: options?.locale,
3237
+ limit: 1
3238
+ },
3239
+ requestOptions
3240
+ ) : Promise.resolve(null);
3241
+ const [tagResponse, customTypeResponse] = await Promise.all([tagPromise, customTypePromise]);
3242
+ const tagEntry = tagResponse.items[0];
3243
+ if (!tagEntry || !tagEntry.fields) {
3244
+ return { data: null, errors: [] };
3245
+ }
3246
+ const customTypeEntry = customTypeResponse?.items[0];
3247
+ try {
3248
+ const assets = convertAllAssets(tagResponse, context);
3249
+ const rawAssets = convertAllRawAssets(tagResponse);
3250
+ const includes = convertAllIncludes(tagResponse);
3251
+ if (customTypeResponse) {
3252
+ const customAssets = convertAllAssets(customTypeResponse, context);
3253
+ const customRawAssets = convertAllRawAssets(customTypeResponse);
3254
+ const customIncludes = convertAllIncludes(customTypeResponse);
3255
+ for (const [key, value] of customAssets) assets.set(key, value);
3256
+ for (const [key, value] of customRawAssets) rawAssets.set(key, value);
3257
+ for (const [key, value] of customIncludes) includes.set(key, value);
3258
+ }
3259
+ const fullContext = {
3260
+ ...context,
3261
+ includes,
3262
+ assets,
3263
+ rawAssets,
3264
+ errors: []
3265
+ };
3266
+ const converted = context.tagResolver(fullContext, tagEntry, customTypeEntry);
3267
+ if (converted?.icons && converted.icons.length > 0) {
3268
+ const processedIcons = await processIconsForSprite(converted.icons);
3269
+ converted.icons = processedIcons.length > 0 ? processedIcons : void 0;
3270
+ }
3271
+ if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
3272
+ console.error(`CMS conversion errors for tag:`, {
3273
+ entryId: tagEntry.sys.id,
3274
+ slug,
3275
+ errors: fullContext.errors
3276
+ });
3277
+ }
3278
+ return { data: converted, errors: fullContext.errors };
3279
+ } catch (error) {
3280
+ const entryId = tagEntry?.sys.id || "unknown";
3281
+ const entryType = tagEntry?.sys.contentType?.sys?.id;
3282
+ const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
3283
+ const cmsError = {
3284
+ entryId,
3285
+ entryType,
3286
+ message: errorMessage,
3287
+ error
3288
+ };
3289
+ return { data: null, errors: [cmsError] };
3290
+ }
3291
+ };
3292
+ if (options?.retry) {
3293
+ return await withRetry(fetchFn, options.retry);
3294
+ }
3295
+ return await fetchFn();
2969
3296
  }
2970
3297
 
2971
3298
  // src/api/template.ts
@@ -3240,6 +3567,6 @@ function createRevalidationHandler(config = {}) {
3240
3567
  init_tags();
3241
3568
  init_utils();
3242
3569
 
3243
- export { AllTags, ArticleTag, ArticleTypeTag, AssetTag, AuthenticationError, BannerTag, ContentfulError, CustomTypeTag, EntryNotFoundError, GlobalTag, LocationTag, NavigationTag, PageTag, PersonTag, RateLimitError, RateLimiter, TagTag, TemplateTag, ValidationError, arrayOrUndefined, articleTag, articleTypeIndexTag, articleTypeTag, assetTag, basePageConverter, calculateBackoffDelay, contentfulAllArticleLinks, contentfulAllArticleTypeLinks, contentfulAllPageLinks, contentfulAllPersonLinks, contentfulAllTagLinks, contentfulArticleRest, contentfulArticleSitemapEntries, contentfulArticleTypeRest, contentfulArticleTypeSitemapEntries, contentfulAssetRest, contentfulCustomTypeRest, contentfulPageRest, contentfulPageSitemapEntries, 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 };
3570
+ export { AllTags, ArticleTag, ArticleTypeTag, AssetTag, AuthenticationError, BannerTag, ContentfulError, CustomTypeTag, EntryNotFoundError, GlobalTag, LocationTag, NavigationTag, PageTag, PersonTag, RateLimitError, RateLimiter, TagTag, TemplateTag, 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 };
3244
3571
  //# sourceMappingURL=index.js.map
3245
3572
  //# sourceMappingURL=index.js.map