@se-studio/contentful-rest-api 1.0.18 → 1.0.20

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
@@ -36,6 +36,9 @@ function personTag(slug) {
36
36
  function assetTag(assetId) {
37
37
  return `${AssetTag}#${assetId}`;
38
38
  }
39
+ function templateTag(label) {
40
+ return `${TemplateTag}#${label}`;
41
+ }
39
42
  function locationTag(slug) {
40
43
  return `${LocationTag}#${slug}`;
41
44
  }
@@ -209,6 +212,27 @@ function buildQueryString(query) {
209
212
  });
210
213
  return params.toString();
211
214
  }
215
+ function sleep(ms) {
216
+ return new Promise((resolve) => setTimeout(resolve, ms));
217
+ }
218
+ function calculateRetryDelay(attempt, retryAfterSeconds) {
219
+ let baseDelay;
220
+ if (retryAfterSeconds !== void 0 && retryAfterSeconds > 0) {
221
+ baseDelay = retryAfterSeconds * 1e3;
222
+ } else {
223
+ baseDelay = 1e3 * 2 ** attempt;
224
+ }
225
+ const jitter = Math.random() * baseDelay;
226
+ return Math.min(baseDelay + jitter, 15e3);
227
+ }
228
+ function parseRetryAfter(response) {
229
+ const retryAfterHeader = response.headers.get("X-Contentful-RateLimit-Reset") || response.headers.get("Retry-After");
230
+ if (retryAfterHeader) {
231
+ const parsed = Number.parseInt(retryAfterHeader, 10);
232
+ return Number.isNaN(parsed) ? void 0 : parsed;
233
+ }
234
+ return void 0;
235
+ }
212
236
  async function parseErrorResponse(response) {
213
237
  const statusCode = response.status;
214
238
  let errorData;
@@ -247,7 +271,7 @@ var ContentfulFetchClient = class {
247
271
  this.accessToken = config.accessToken;
248
272
  }
249
273
  /**
250
- * Fetches entries from Contentful
274
+ * Fetches entries from Contentful with automatic retry on rate limit errors
251
275
  */
252
276
  async getEntries(query, options) {
253
277
  const queryString = buildQueryString(query);
@@ -261,11 +285,26 @@ var ContentfulFetchClient = class {
261
285
  if (options?.next) {
262
286
  fetchOptions.next = options.next;
263
287
  }
264
- const response = await fetch(url, fetchOptions);
265
- if (!response.ok) {
288
+ const maxRetries = 3;
289
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
290
+ const response = await fetch(url, fetchOptions);
291
+ if (response.ok) {
292
+ return response.json();
293
+ }
294
+ if (response.status === 429 && attempt < maxRetries) {
295
+ const retryAfter = parseRetryAfter(response);
296
+ const delay3 = calculateRetryDelay(attempt, retryAfter);
297
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
298
+ console.warn(
299
+ `[Contentful] Rate limited, retrying in ${delay3}ms (attempt ${attempt + 1}/${maxRetries})`
300
+ );
301
+ }
302
+ await sleep(delay3);
303
+ continue;
304
+ }
266
305
  throw await parseErrorResponse(response);
267
306
  }
268
- return response.json();
307
+ throw new ContentfulError("Unexpected error in retry loop", 500);
269
308
  }
270
309
  };
271
310
  function createContentfulClient(config) {
@@ -306,14 +345,25 @@ var DEFAULT_POSITION_FIELDS = {
306
345
  indexOfType: 0
307
346
  };
308
347
  function createInternalLink(id, fields, context, href, internalType, additionalProps) {
309
- const { cmsLabel, title, featuredImage, backgroundColour, textColour, indexed, hidden, slug } = fields;
348
+ const {
349
+ cmsLabel,
350
+ title,
351
+ featuredImage,
352
+ backgroundColour,
353
+ textColour,
354
+ indexed,
355
+ hidden,
356
+ slug,
357
+ description
358
+ } = fields;
359
+ const text = makeContentfulTitle(title, id);
310
360
  return {
311
361
  type: "Internal link",
312
362
  internalType,
313
363
  id,
314
364
  name: cmsLabel ?? "",
315
365
  useName: true,
316
- text: makeContentfulTitle(title, id),
366
+ text,
317
367
  visual: lookupAsset(context, featuredImage),
318
368
  backgroundColour,
319
369
  textColour,
@@ -321,6 +371,8 @@ function createInternalLink(id, fields, context, href, internalType, additionalP
321
371
  hidden,
322
372
  slug,
323
373
  href,
374
+ title,
375
+ description,
324
376
  ...additionalProps
325
377
  };
326
378
  }
@@ -573,6 +625,9 @@ function lookupMediaEntry(context, link) {
573
625
  return void 0;
574
626
  }
575
627
 
628
+ // src/api/helpers.ts
629
+ init_utils();
630
+
576
631
  // src/utils/arrayUtils.ts
577
632
  function notEmpty(value) {
578
633
  if (value === null || value === void 0) return false;
@@ -615,16 +670,24 @@ var DEFAULT_RETRY_CONFIG = {
615
670
  // 30 seconds
616
671
  backoffMultiplier: 2
617
672
  };
618
- function sleep(ms) {
673
+ function sleep2(ms) {
619
674
  return new Promise((resolve) => setTimeout(resolve, ms));
620
675
  }
621
676
  function calculateBackoffDelay(attempt, config, retryAfter) {
622
677
  if (retryAfter !== void 0) {
623
- return Math.min(retryAfter * 1e3, config.maxDelay);
678
+ const result2 = Math.min(retryAfter * 1e3, config.maxDelay);
679
+ console.log(
680
+ `Calculated backoff delay: ${result2}ms (attempt ${attempt + 1}), retryAfter: ${retryAfter}`
681
+ );
682
+ return result2;
624
683
  }
625
684
  const exponentialDelay = config.initialDelay * config.backoffMultiplier ** attempt;
626
685
  const jitter = Math.random() * exponentialDelay;
627
- return Math.min(exponentialDelay + jitter, config.maxDelay);
686
+ const result = Math.min(exponentialDelay + jitter, config.maxDelay);
687
+ console.log(
688
+ `Calculated backoff delay: ${result}ms (attempt ${attempt + 1}), exponentialDelay: ${exponentialDelay}, jitter: ${jitter}`
689
+ );
690
+ return result;
628
691
  }
629
692
  async function withRetry(fn, config) {
630
693
  const retryConfig = {
@@ -651,7 +714,7 @@ async function withRetry(fn, config) {
651
714
  error
652
715
  );
653
716
  }
654
- await sleep(delay3);
717
+ await sleep2(delay3);
655
718
  }
656
719
  }
657
720
  throw lastError;
@@ -693,7 +756,7 @@ var RateLimiter = class {
693
756
  async consume() {
694
757
  while (!this.tryConsume()) {
695
758
  const waitTime = 1 / this.refillRate * 1e3;
696
- await sleep(waitTime);
759
+ await sleep2(waitTime);
697
760
  }
698
761
  }
699
762
  /**
@@ -705,6 +768,211 @@ var RateLimiter = class {
705
768
  }
706
769
  };
707
770
 
771
+ // src/api/helpers.ts
772
+ var PAGE_LINK_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags";
773
+ var ARTICLE_LINK_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags,fields.articleType,fields.date,fields.author";
774
+ var ARTICLE_TYPE_LINK_FIELDS = "sys,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
775
+ var TAG_LINK_FIELDS = "sys,fields.cmsLabel,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
776
+ var PERSON_LINK_FIELDS = "sys,fields.name,fields.slug,fields.media,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
777
+ function convertAllAssets(response, context) {
778
+ const visuals = /* @__PURE__ */ new Map();
779
+ const assets = response.includes?.Asset;
780
+ if (assets && assets.length > 0) {
781
+ for (const asset of assets) {
782
+ const visual = convertAssetToVisual(context, asset);
783
+ if (visual) {
784
+ visuals.set(visual.id, visual);
785
+ }
786
+ }
787
+ }
788
+ return visuals;
789
+ }
790
+ function convertAllIncludes(response) {
791
+ const includes = /* @__PURE__ */ new Map();
792
+ const entries = [...response.items, ...response.includes?.Entry || []];
793
+ if (entries && entries.length > 0) {
794
+ for (const entry of entries) {
795
+ if (entry?.sys && entry.fields) {
796
+ includes.set(entry.sys.id, {
797
+ id: entry.sys.id,
798
+ type: entry.sys.contentType.sys.id,
799
+ entry
800
+ });
801
+ }
802
+ }
803
+ }
804
+ return includes;
805
+ }
806
+ async function fetchSingleEntity(context, config, fetchConfig, options) {
807
+ const client = getContentfulClient(config, options?.preview);
808
+ const cacheTags = getCacheTags(
809
+ fetchConfig.cacheTagType,
810
+ fetchConfig.cacheTagIdentifier,
811
+ options?.preview
812
+ );
813
+ const requestOptions = {
814
+ ...options,
815
+ next: {
816
+ ...options?.next,
817
+ tags: cacheTags
818
+ }
819
+ };
820
+ const fetchFn = async () => {
821
+ const response = await client.getEntries(
822
+ {
823
+ content_type: fetchConfig.contentType,
824
+ ...fetchConfig.query,
825
+ include: 10,
826
+ locale: options?.locale,
827
+ limit: 1
828
+ },
829
+ requestOptions
830
+ );
831
+ const entry = response.items[0];
832
+ if (!entry || !entry.fields) {
833
+ return { data: null, errors: [] };
834
+ }
835
+ try {
836
+ const assets = convertAllAssets(response, context);
837
+ const includes = convertAllIncludes(response);
838
+ const fullContext = {
839
+ ...context,
840
+ includes,
841
+ assets,
842
+ errors: []
843
+ };
844
+ const converted = fetchConfig.resolver(fullContext, entry);
845
+ if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
846
+ console.error(`CMS conversion errors for ${fetchConfig.contentType}:`, {
847
+ entryId: entry.sys.id,
848
+ ...fetchConfig.errorLogContext,
849
+ errors: fullContext.errors
850
+ });
851
+ }
852
+ return { data: converted, errors: fullContext.errors };
853
+ } catch (error) {
854
+ const entryId = entry.sys.id;
855
+ const entryType = entry.sys.contentType?.sys?.id;
856
+ const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
857
+ const cmsError = {
858
+ entryId,
859
+ entryType,
860
+ message: errorMessage,
861
+ error
862
+ };
863
+ return { data: null, errors: [cmsError] };
864
+ }
865
+ };
866
+ if (options?.retry) {
867
+ return await withRetry(fetchFn, options.retry);
868
+ }
869
+ return await fetchFn();
870
+ }
871
+ async function fetchAllLinks(contentType, client, requestOptions, converter, context, pageSize = 100, select) {
872
+ const allLinks = [];
873
+ const errors = [];
874
+ let skip = 0;
875
+ let hasMore = true;
876
+ const fetchFn = async () => {
877
+ while (hasMore) {
878
+ try {
879
+ const response = await client.getEntries(
880
+ {
881
+ content_type: contentType,
882
+ include: 2,
883
+ // Minimal include for link-only fetching
884
+ locale: requestOptions?.locale,
885
+ limit: pageSize,
886
+ skip,
887
+ ...select && { select }
888
+ },
889
+ requestOptions
890
+ );
891
+ if (response.items.length === 0) {
892
+ hasMore = false;
893
+ break;
894
+ }
895
+ const includes = convertAllIncludes(response);
896
+ const assets = convertAllAssets(response, context);
897
+ const fullContext = {
898
+ ...context,
899
+ includes,
900
+ assets,
901
+ errors: []
902
+ };
903
+ for (const entry of response.items) {
904
+ if (!entry.fields) continue;
905
+ try {
906
+ const converted = converter(
907
+ fullContext,
908
+ entry
909
+ );
910
+ converted.lastModified = entry.sys.updatedAt ? new Date(entry.sys.updatedAt) : void 0;
911
+ allLinks.push(converted);
912
+ } catch (error) {
913
+ const entryId = entry.sys.id;
914
+ const entryType = entry.sys.contentType?.sys?.id;
915
+ const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
916
+ errors.push({
917
+ entryId,
918
+ entryType,
919
+ message: errorMessage,
920
+ error
921
+ });
922
+ }
923
+ }
924
+ skip += pageSize;
925
+ if (skip >= response.total) {
926
+ hasMore = false;
927
+ }
928
+ } catch (error) {
929
+ console.error("Error fetching links", typeof error, error, JSON.stringify(error, null, 2));
930
+ throw error;
931
+ }
932
+ }
933
+ return { data: allLinks, errors };
934
+ };
935
+ return await fetchFn();
936
+ }
937
+
938
+ // src/api/article.ts
939
+ async function contentfulArticleRest(context, config, slug, articleTypeSlug, options) {
940
+ return fetchSingleEntity(
941
+ context,
942
+ config,
943
+ {
944
+ contentType: "article",
945
+ cacheTagType: "article",
946
+ cacheTagIdentifier: slug,
947
+ query: {
948
+ "fields.slug": slug,
949
+ "fields.articleType.sys.contentType.sys.id": "articleType",
950
+ "fields.articleType.fields.slug": articleTypeSlug
951
+ },
952
+ resolver: (ctx, entry) => ctx.articleResolver(ctx, entry),
953
+ errorLogContext: { slug, articleTypeSlug }
954
+ },
955
+ options
956
+ );
957
+ }
958
+
959
+ // src/api/article-type.ts
960
+ async function contentfulArticleTypeRest(context, config, indexPageSlug, options) {
961
+ return fetchSingleEntity(
962
+ context,
963
+ config,
964
+ {
965
+ contentType: "articleType",
966
+ cacheTagType: "articleType",
967
+ cacheTagIdentifier: indexPageSlug,
968
+ query: { "fields.indexPageSlug": indexPageSlug },
969
+ resolver: (ctx, entry) => ctx.articleTypeResolver(ctx, entry),
970
+ errorLogContext: { indexPageSlug }
971
+ },
972
+ options
973
+ );
974
+ }
975
+
708
976
  // src/converters/resolver.ts
709
977
  function resolveHelper(context, fromId, entry, getResolver) {
710
978
  const id = entry.sys.id;
@@ -758,17 +1026,22 @@ function resolveNavigationItem(context, fromId, entry) {
758
1026
  return result;
759
1027
  }
760
1028
  function resolveCollectionContent(context, fromId, entry) {
761
- return resolveHelper(context, fromId, entry, (type) => {
762
- const resolver = context.contentResolver.get(type);
763
- if (resolver) {
764
- return resolver;
765
- }
766
- const linkResolver = context.linkResolver.get(type);
767
- if (linkResolver) {
768
- return linkResolver;
1029
+ return resolveHelper(
1030
+ context,
1031
+ fromId,
1032
+ entry,
1033
+ (type) => {
1034
+ const resolver = context.contentResolver.get(type);
1035
+ if (resolver) {
1036
+ return resolver;
1037
+ }
1038
+ const linkResolver = context.linkResolver.get(type);
1039
+ if (linkResolver) {
1040
+ return linkResolver;
1041
+ }
1042
+ return void 0;
769
1043
  }
770
- return void 0;
771
- });
1044
+ );
772
1045
  }
773
1046
  function resolvePageContent(context, fromId, entry) {
774
1047
  const id = entry.sys.id;
@@ -973,46 +1246,322 @@ function resolveRichTextDocument(context, fromId, richText) {
973
1246
  return { json: resolved };
974
1247
  }
975
1248
 
976
- // src/converters/collection.ts
977
- function baseCollectionConverter(context, entry) {
978
- const { sys, fields } = entry;
979
- const { id } = sys;
1249
+ // src/converters/navigationItem.ts
1250
+ function createLink(context, entry) {
980
1251
  const {
981
- // Fields requiring transformation
982
- backgroundVisual: bgVisual,
983
- mobileBackgroundVisual: mobileBgVisual,
984
- visual: visualField,
985
- mobileVisual: mobileVisualField,
986
- visualCustomSize,
987
- icon: iconField,
988
- links: linksField,
989
- contents: contentsField,
990
- body: bodyField,
991
- additionalCopy: additionalCopyField,
992
- // Field name change
993
- collectionType,
994
- showHeading,
995
- heading,
996
- // Already handled elsewhere
997
- cmsLabel,
998
- ...simpleFields
999
- // anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
1252
+ sys: { id },
1253
+ fields
1254
+ } = entry;
1255
+ const {
1256
+ title,
1257
+ link,
1258
+ text,
1259
+ internal,
1260
+ icon: navIcon,
1261
+ mobileIcon: mobileNavIcon,
1262
+ useTitle,
1263
+ ...otherFields
1000
1264
  } = fields;
1001
- const backgroundVisual = createResponsiveVisual(
1002
- lookupAsset(context, bgVisual),
1003
- lookupAsset(context, mobileBgVisual)
1265
+ const icon = createResponsiveVisual(
1266
+ lookupAsset(context, navIcon),
1267
+ lookupAsset(context, mobileNavIcon)
1004
1268
  );
1005
- const visual = createResponsiveVisual(
1006
- lookupMediaEntry(context, visualField),
1007
- lookupMediaEntry(context, mobileVisualField),
1008
- visualCustomSize
1269
+ const realText = useTitle ? resolveBuildYear(title) : text ? resolveBuildYear(text) : void 0;
1270
+ if (link) {
1271
+ return {
1272
+ type: "External link",
1273
+ id,
1274
+ href: link,
1275
+ icon,
1276
+ name: makeContentfulTitle(title, id),
1277
+ ...otherFields,
1278
+ text: realText
1279
+ };
1280
+ }
1281
+ if (internal) {
1282
+ const resolved = resolveLink(context, id, internal);
1283
+ return { ...resolved, icon, id, text: realText };
1284
+ }
1285
+ const blank = {
1286
+ type: "Blank link",
1287
+ nick: true,
1288
+ id,
1289
+ name: makeContentfulTitle(title, id),
1290
+ ...otherFields,
1291
+ icon,
1292
+ text: realText
1293
+ };
1294
+ return blank;
1295
+ }
1296
+ function baseNavigationItemConverter(context, entry) {
1297
+ const {
1298
+ sys: { id },
1299
+ fields
1300
+ } = entry;
1301
+ const { navigationItems } = fields;
1302
+ const link = createLink(context, entry);
1303
+ const resolvedNavigationItems = navigationItems?.map((item) => resolveNavigationItem(context, id, item)).filter((item) => item !== void 0);
1304
+ const result = {
1305
+ id,
1306
+ link,
1307
+ entries: resolvedNavigationItems
1308
+ };
1309
+ return result;
1310
+ }
1311
+ function resolveNavigation(context, link) {
1312
+ const id = link.sys.id;
1313
+ const possibleEntry = context.includes.get(id);
1314
+ if (!possibleEntry || possibleEntry.type !== "navigation") {
1315
+ return void 0;
1316
+ }
1317
+ const entry = possibleEntry.entry;
1318
+ const { fields } = entry;
1319
+ if (!fields) {
1320
+ return void 0;
1321
+ }
1322
+ const { name, entries: fieldEntries, ...rest } = fields;
1323
+ const entries = fieldEntries?.map((item) => resolveNavigationItem(context, id, item)) ?? [];
1324
+ return {
1325
+ id,
1326
+ name,
1327
+ entries,
1328
+ ...rest
1329
+ };
1330
+ }
1331
+
1332
+ // src/converters/template.ts
1333
+ function resolveTemplate(context, link) {
1334
+ const id = link.sys.id;
1335
+ const possibleEntry = context.includes.get(id);
1336
+ if (!possibleEntry || possibleEntry.type !== "template") {
1337
+ return null;
1338
+ }
1339
+ const entry = possibleEntry.entry;
1340
+ const { fields } = entry;
1341
+ if (!fields) {
1342
+ return null;
1343
+ }
1344
+ const preContent = fields.preContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
1345
+ const postContent = fields.postContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
1346
+ const menu = fields.menu ? resolveNavigation(context, fields.menu) : void 0;
1347
+ const footer = fields.footer ? resolveNavigation(context, fields.footer) : void 0;
1348
+ const stickyNav = fields.flags?.includes("Sticky nav") ?? false;
1349
+ const { backgroundColour, textColour } = fields;
1350
+ return {
1351
+ preContent,
1352
+ postContent,
1353
+ menu,
1354
+ footer,
1355
+ backgroundColour,
1356
+ textColour,
1357
+ stickyNav
1358
+ };
1359
+ }
1360
+
1361
+ // src/converters/article.ts
1362
+ function resolveArticleTemplateHierarchy(context, articleTypeLink, directTemplateLink) {
1363
+ if (directTemplateLink) {
1364
+ return resolveTemplate(context, directTemplateLink);
1365
+ }
1366
+ const articleTypeEntry = context.includes.get(articleTypeLink.sys.id);
1367
+ if (!articleTypeEntry) {
1368
+ console.warn(`ArticleType entry not found for id: ${articleTypeLink.sys.id}`);
1369
+ return null;
1370
+ }
1371
+ const articleTypeFields = articleTypeEntry.entry.fields;
1372
+ if (articleTypeFields?.articleTemplate) {
1373
+ return resolveTemplate(context, articleTypeFields.articleTemplate);
1374
+ }
1375
+ return null;
1376
+ }
1377
+ function baseArticleConverter(context, entry) {
1378
+ const { sys, fields } = entry;
1379
+ const { id } = sys;
1380
+ const {
1381
+ slug,
1382
+ title,
1383
+ description,
1384
+ featuredImage,
1385
+ tags,
1386
+ content,
1387
+ template: templateLink,
1388
+ topContent: topContentLinks,
1389
+ bottomContent: bottomContentLinks,
1390
+ articleType,
1391
+ ...simpleFields
1392
+ } = fields;
1393
+ const articleTypeLink = resolveLink(context, id, articleType);
1394
+ const template = resolveArticleTemplateHierarchy(context, articleType, templateLink);
1395
+ const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1396
+ const articleContent = content?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1397
+ const bottomContent = bottomContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1398
+ const preContent = template?.preContent ?? [];
1399
+ const postContent = template?.postContent ?? [];
1400
+ const contents = addPositionMetadata([
1401
+ ...topContent,
1402
+ ...preContent,
1403
+ ...articleContent,
1404
+ ...postContent,
1405
+ ...bottomContent
1406
+ ]);
1407
+ const article = {
1408
+ type: "Article",
1409
+ id,
1410
+ slug,
1411
+ title: makeContentfulTitle(title, sys.id),
1412
+ description: makeContentfulDescription(description, sys.id),
1413
+ featuredImage: lookupAsset(context, featuredImage),
1414
+ articleType: articleTypeLink,
1415
+ tags: tags?.map((tag) => resolveLink(context, id, tag)),
1416
+ contents,
1417
+ ...simpleFields,
1418
+ // Note: summary field exists in Contentful but is not part of IArticle interface
1419
+ // Keeping it in simpleFields for potential future use
1420
+ menu: template?.menu,
1421
+ footer: template?.footer
1422
+ };
1423
+ return article;
1424
+ }
1425
+ function calculateArticleTypeHref(slug) {
1426
+ return `/${slug}/`;
1427
+ }
1428
+ function calculateArticleHref(articleTypeSlug, slug) {
1429
+ return `${calculateArticleTypeHref(articleTypeSlug)}${slug}/`;
1430
+ }
1431
+ function baseArticleLinkConverter(context, entry) {
1432
+ const { sys, fields } = entry;
1433
+ if (sys.contentType.sys.id !== "article") {
1434
+ throw new Error(`Invalid content type: expected "article", got "${sys.contentType.sys.id}"`);
1435
+ }
1436
+ const articleTypeLink = resolveLink(context, sys.id, fields.articleType);
1437
+ const tags = fields.tags?.map((tag) => resolveLink(context, sys.id, tag));
1438
+ const primaryTag = tags?.[0] ?? void 0;
1439
+ const author = fields.author ? resolveLink(context, sys.id, fields.author) : void 0;
1440
+ return createInternalLink(
1441
+ sys.id,
1442
+ {
1443
+ cmsLabel: fields.cmsLabel,
1444
+ title: fields.title,
1445
+ featuredImage: fields.featuredImage,
1446
+ backgroundColour: fields.backgroundColour,
1447
+ textColour: fields.textColour,
1448
+ indexed: fields.indexed,
1449
+ hidden: fields.hidden,
1450
+ slug: fields.slug
1451
+ },
1452
+ context,
1453
+ calculateArticleHref(articleTypeLink.slug, fields.slug),
1454
+ "Article",
1455
+ {
1456
+ tags,
1457
+ primaryTag,
1458
+ articleType: articleTypeLink,
1459
+ date: fields.date,
1460
+ author
1461
+ }
1462
+ );
1463
+ }
1464
+ function baseArticleTypeLinkConverter(context, entry) {
1465
+ const { sys, fields } = entry;
1466
+ if (sys.contentType.sys.id !== "articleType") {
1467
+ throw new Error(
1468
+ `Invalid content type: expected "articleType", got "${sys.contentType.sys.id}"`
1469
+ );
1470
+ }
1471
+ return createInternalLink(
1472
+ sys.id,
1473
+ {
1474
+ cmsLabel: fields.name,
1475
+ title: fields.name,
1476
+ featuredImage: fields.featuredImage,
1477
+ backgroundColour: fields.backgroundColour,
1478
+ textColour: fields.textColour,
1479
+ indexed: fields.indexed,
1480
+ hidden: fields.hidden,
1481
+ slug: fields.slug
1482
+ },
1483
+ context,
1484
+ calculateArticleTypeHref(fields.slug),
1485
+ "ArticleType",
1486
+ { indexPageSlug: fields.indexPageSlug }
1487
+ );
1488
+ }
1489
+ function baseArticleTypeConverter(context, entry) {
1490
+ const { sys, fields } = entry;
1491
+ const { id } = sys;
1492
+ const {
1493
+ indexPageSlug,
1494
+ indexPageName,
1495
+ indexPageDescription,
1496
+ featuredImage,
1497
+ menu: menuLink,
1498
+ footer: footerLink,
1499
+ indexPageTemplate: templateLink,
1500
+ indexPageTopContent: topContentLinks,
1501
+ structuredData,
1502
+ slug: _slug,
1503
+ ...other
1504
+ } = fields;
1505
+ const template = templateLink ? resolveTemplate(context, templateLink) : null;
1506
+ const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
1507
+ const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
1508
+ const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1509
+ const preContent = template?.preContent ?? [];
1510
+ const postContent = template?.postContent ?? [];
1511
+ const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
1512
+ const articleType = {
1513
+ type: "Article type",
1514
+ id,
1515
+ slug: indexPageSlug,
1516
+ title: makeContentfulTitle(indexPageName, sys.id),
1517
+ description: makeContentfulDescription(indexPageDescription, sys.id),
1518
+ featuredImage: lookupAsset(context, featuredImage),
1519
+ contents,
1520
+ structuredData,
1521
+ menu,
1522
+ footer,
1523
+ ...other
1524
+ };
1525
+ return articleType;
1526
+ }
1527
+
1528
+ // src/converters/collection.ts
1529
+ function baseCollectionConverter(context, entry) {
1530
+ const { sys, fields } = entry;
1531
+ const { id } = sys;
1532
+ const {
1533
+ // Fields requiring transformation
1534
+ backgroundVisual: bgVisual,
1535
+ mobileBackgroundVisual: mobileBgVisual,
1536
+ visual: visualField,
1537
+ mobileVisual: mobileVisualField,
1538
+ visualCustomSize,
1539
+ icon: iconField,
1540
+ links: linksField,
1541
+ contents: contentsField,
1542
+ body: bodyField,
1543
+ additionalCopy: additionalCopyField,
1544
+ showHeading,
1545
+ heading,
1546
+ // Already handled elsewhere
1547
+ cmsLabel,
1548
+ ...simpleFields
1549
+ // anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
1550
+ } = fields;
1551
+ const backgroundVisual = createResponsiveVisual(
1552
+ lookupAsset(context, bgVisual),
1553
+ lookupAsset(context, mobileBgVisual)
1554
+ );
1555
+ const visual = createResponsiveVisual(
1556
+ lookupMediaEntry(context, visualField),
1557
+ lookupMediaEntry(context, mobileVisualField),
1558
+ visualCustomSize
1009
1559
  );
1010
1560
  const collection = {
1011
1561
  type: "Collection",
1012
1562
  id,
1013
1563
  name: cmsLabel,
1014
1564
  cmsLabel,
1015
- collectionType,
1016
1565
  ...DEFAULT_POSITION_FIELDS,
1017
1566
  ...simpleFields,
1018
1567
  heading: showHeading ? heading : void 0,
@@ -1043,7 +1592,6 @@ function baseComponentConverter(context, entry) {
1043
1592
  body: bodyField,
1044
1593
  additionalCopy: additionalCopyField,
1045
1594
  // Field name change
1046
- componentType,
1047
1595
  showHeading,
1048
1596
  heading,
1049
1597
  otherMedia: otherMediaField,
@@ -1067,7 +1615,6 @@ function baseComponentConverter(context, entry) {
1067
1615
  id,
1068
1616
  name: cmsLabel,
1069
1617
  cmsLabel,
1070
- componentType,
1071
1618
  ...DEFAULT_POSITION_FIELDS,
1072
1619
  ...simpleFields,
1073
1620
  heading: showHeading ? heading : void 0,
@@ -1082,6 +1629,49 @@ function baseComponentConverter(context, entry) {
1082
1629
  return component;
1083
1630
  }
1084
1631
 
1632
+ // src/converters/customType.ts
1633
+ function baseCustomTypeConverter(context, entry) {
1634
+ const { sys, fields } = entry;
1635
+ const { id } = sys;
1636
+ const {
1637
+ slug,
1638
+ indexPageSlug,
1639
+ indexPageName,
1640
+ indexPageDescription,
1641
+ featuredImage,
1642
+ menu: menuLink,
1643
+ footer: footerLink,
1644
+ indexPageTemplate: templateLink,
1645
+ indexPageTopContent: topContentLinks,
1646
+ structuredData,
1647
+ ...other
1648
+ } = fields;
1649
+ const template = templateLink ? resolveTemplate(context, templateLink) : null;
1650
+ const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
1651
+ const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
1652
+ const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1653
+ const preContent = template?.preContent ?? [];
1654
+ const postContent = template?.postContent ?? [];
1655
+ const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
1656
+ const customType = {
1657
+ type: "Custom type",
1658
+ id,
1659
+ slug,
1660
+ indexPageSlug,
1661
+ indexPageName: makeContentfulTitle(indexPageName, sys.id),
1662
+ indexPageDescription: makeContentfulDescription(indexPageDescription, sys.id),
1663
+ title: makeContentfulTitle(indexPageName, sys.id),
1664
+ description: makeContentfulDescription(indexPageDescription, sys.id),
1665
+ featuredImage: lookupAsset(context, featuredImage),
1666
+ contents,
1667
+ structuredData,
1668
+ menu,
1669
+ footer,
1670
+ ...other
1671
+ };
1672
+ return customType;
1673
+ }
1674
+
1085
1675
  // src/converters/link.ts
1086
1676
  function baseLinkConverter(context, entry) {
1087
1677
  const { sys, fields } = entry;
@@ -1123,7 +1713,9 @@ function baseLinkConverter(context, entry) {
1123
1713
  slug: internalTarget.slug,
1124
1714
  indexed: internalTarget.indexed,
1125
1715
  hidden: internalTarget.hidden,
1126
- tags: internalTarget.tags
1716
+ tags: internalTarget.tags,
1717
+ title: internalTarget.title,
1718
+ description: internalTarget.description
1127
1719
  };
1128
1720
  }
1129
1721
  if (fields.external) {
@@ -1155,124 +1747,11 @@ function baseLinkConverter(context, entry) {
1155
1747
  href,
1156
1748
  visual: asset
1157
1749
  };
1158
- }
1159
- return {
1160
- ...baseProps,
1161
- type: "Blank link",
1162
- href: null
1163
- };
1164
- }
1165
-
1166
- // src/converters/navigationItem.ts
1167
- function createLink(context, entry) {
1168
- const {
1169
- sys: { id },
1170
- fields
1171
- } = entry;
1172
- const {
1173
- title,
1174
- link,
1175
- text,
1176
- internal,
1177
- icon: navIcon,
1178
- mobileIcon: mobileNavIcon,
1179
- useTitle,
1180
- ...otherFields
1181
- } = fields;
1182
- const icon = createResponsiveVisual(
1183
- lookupAsset(context, navIcon),
1184
- lookupAsset(context, mobileNavIcon)
1185
- );
1186
- const realText = useTitle ? resolveBuildYear(title) : text ? resolveBuildYear(text) : void 0;
1187
- if (link) {
1188
- return {
1189
- type: "External link",
1190
- id,
1191
- href: link,
1192
- icon,
1193
- name: makeContentfulTitle(title, id),
1194
- ...otherFields,
1195
- text: realText
1196
- };
1197
- }
1198
- if (internal) {
1199
- const resolved = resolveLink(context, id, internal);
1200
- return { ...resolved, icon, id, text: realText };
1201
- }
1202
- const blank = {
1203
- type: "Blank link",
1204
- nick: true,
1205
- id,
1206
- name: makeContentfulTitle(title, id),
1207
- ...otherFields,
1208
- icon,
1209
- text: realText
1210
- };
1211
- return blank;
1212
- }
1213
- function baseNavigationItemConverter(context, entry) {
1214
- const {
1215
- sys: { id },
1216
- fields
1217
- } = entry;
1218
- const { navigationItems } = fields;
1219
- const link = createLink(context, entry);
1220
- const resolvedNavigationItems = navigationItems?.map((item) => resolveNavigationItem(context, id, item)).filter((item) => item !== void 0);
1221
- const result = {
1222
- id,
1223
- link,
1224
- entries: resolvedNavigationItems
1225
- };
1226
- return result;
1227
- }
1228
- function resolveNavigation(context, link) {
1229
- const id = link.sys.id;
1230
- const possibleEntry = context.includes.get(id);
1231
- if (!possibleEntry || possibleEntry.type !== "navigation") {
1232
- return void 0;
1233
- }
1234
- const entry = possibleEntry.entry;
1235
- const { fields } = entry;
1236
- if (!fields) {
1237
- return void 0;
1238
- }
1239
- const entries = fields.entries?.map((item) => resolveNavigationItem(context, id, item)) ?? [];
1240
- const { name, textColour, backgroundColour } = fields;
1241
- return {
1242
- id,
1243
- name,
1244
- entries,
1245
- textColour,
1246
- backgroundColour
1247
- };
1248
- }
1249
-
1250
- // src/converters/template.ts
1251
- function resolveTemplate(context, link) {
1252
- const id = link.sys.id;
1253
- const possibleEntry = context.includes.get(id);
1254
- if (!possibleEntry || possibleEntry.type !== "template") {
1255
- return null;
1256
- }
1257
- const entry = possibleEntry.entry;
1258
- const { fields } = entry;
1259
- if (!fields) {
1260
- return null;
1261
- }
1262
- const preContent = fields.preContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
1263
- const postContent = fields.postContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
1264
- const menu = fields.menu ? resolveNavigation(context, fields.menu) : void 0;
1265
- const footer = fields.footer ? resolveNavigation(context, fields.footer) : void 0;
1266
- const stickyNav = fields.flags?.includes("Sticky nav") ?? false;
1267
- const { backgroundColour, textColour } = fields;
1268
- return {
1269
- preContent,
1270
- postContent,
1271
- menu,
1272
- footer,
1273
- backgroundColour,
1274
- textColour,
1275
- stickyNav
1750
+ }
1751
+ return {
1752
+ ...baseProps,
1753
+ type: "Blank link",
1754
+ href: null
1276
1755
  };
1277
1756
  }
1278
1757
 
@@ -1401,16 +1880,7 @@ function basePersonLinkConverter(context, entry) {
1401
1880
  return createInternalLink(
1402
1881
  sys.id,
1403
1882
  {
1404
- cmsLabel: fields.name,
1405
- // Person has no cmsLabel, use name field
1406
- title: fields.name,
1407
- featuredImage: fields.media,
1408
- // Person uses 'media' not 'featuredImage'
1409
- backgroundColour: fields.backgroundColour,
1410
- textColour: fields.textColour,
1411
- indexed: fields.indexed,
1412
- hidden: fields.hidden,
1413
- slug: fields.slug
1883
+ ...fields
1414
1884
  },
1415
1885
  context,
1416
1886
  calculatePersonHref(fields.slug),
@@ -1418,140 +1888,39 @@ function basePersonLinkConverter(context, entry) {
1418
1888
  );
1419
1889
  }
1420
1890
 
1421
- // src/converters/article.ts
1422
- function resolveArticleTemplateHierarchy(context, articleTypeLink, directTemplateLink) {
1423
- if (directTemplateLink) {
1424
- return resolveTemplate(context, directTemplateLink);
1425
- }
1426
- const articleTypeEntry = context.includes.get(articleTypeLink.sys.id);
1427
- if (!articleTypeEntry) {
1428
- console.warn(`ArticleType entry not found for id: ${articleTypeLink.sys.id}`);
1429
- return null;
1430
- }
1431
- const articleTypeFields = articleTypeEntry.entry.fields;
1432
- if (articleTypeFields?.articleTemplate) {
1433
- return resolveTemplate(context, articleTypeFields.articleTemplate);
1434
- }
1435
- return null;
1436
- }
1437
- function baseArticleConverter(context, entry) {
1438
- const { sys, fields } = entry;
1439
- const { id } = sys;
1440
- const {
1441
- slug,
1442
- title,
1443
- description,
1444
- featuredImage,
1445
- tags,
1446
- content,
1447
- template: templateLink,
1448
- topContent: topContentLinks,
1449
- bottomContent: bottomContentLinks,
1450
- articleType,
1451
- ...simpleFields
1452
- } = fields;
1453
- const articleTypeLink = resolveLink(context, id, articleType);
1454
- const template = resolveArticleTemplateHierarchy(context, articleType, templateLink);
1455
- const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1456
- const articleContent = content?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1457
- const bottomContent = bottomContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1458
- const preContent = template?.preContent ?? [];
1459
- const postContent = template?.postContent ?? [];
1460
- const contents = addPositionMetadata([
1461
- ...topContent,
1462
- ...preContent,
1463
- ...articleContent,
1464
- ...postContent,
1465
- ...bottomContent
1466
- ]);
1467
- const article = {
1468
- type: "Article",
1469
- id,
1470
- slug,
1471
- title: makeContentfulTitle(title, sys.id),
1472
- description: makeContentfulDescription(description, sys.id),
1473
- featuredImage: lookupAsset(context, featuredImage),
1474
- articleType: articleTypeLink,
1475
- tags: tags?.map((tag) => resolveLink(context, id, tag)),
1476
- contents,
1477
- ...simpleFields,
1478
- // Note: summary field exists in Contentful but is not part of IArticle interface
1479
- // Keeping it in simpleFields for potential future use
1480
- menu: template?.menu,
1481
- footer: template?.footer
1482
- };
1483
- return article;
1484
- }
1485
- function calculateArticleTypeHref(slug) {
1486
- return `/${slug}/`;
1487
- }
1488
- function calculateArticleHref(articleTypeSlug, slug) {
1489
- return `${calculateArticleTypeHref(articleTypeSlug)}${slug}/`;
1490
- }
1491
- function baseArticleLinkConverter(context, entry) {
1492
- const { sys, fields } = entry;
1493
- if (sys.contentType.sys.id !== "article") {
1494
- throw new Error(`Invalid content type: expected "article", got "${sys.contentType.sys.id}"`);
1495
- }
1496
- const articleTypeLink = resolveLink(context, sys.id, fields.articleType);
1497
- return createInternalLink(
1498
- sys.id,
1499
- {
1500
- cmsLabel: fields.cmsLabel,
1501
- title: fields.title,
1502
- featuredImage: fields.featuredImage,
1503
- backgroundColour: fields.backgroundColour,
1504
- textColour: fields.textColour,
1505
- indexed: fields.indexed,
1506
- hidden: fields.hidden,
1507
- slug: fields.slug
1508
- },
1509
- context,
1510
- calculateArticleHref(articleTypeLink.slug, fields.slug),
1511
- "Article",
1512
- {
1513
- tags: fields.tags?.map((tag) => resolveLink(context, sys.id, tag)),
1514
- articleType: articleTypeLink
1515
- }
1516
- );
1891
+ // src/converters/tag.ts
1892
+ function calculateTagHref(slug) {
1893
+ return `/tag/${slug}/`;
1517
1894
  }
1518
- function baseArticleTypeLinkConverter(context, entry) {
1895
+ function baseTagLinkConverter(context, entry) {
1519
1896
  const { sys, fields } = entry;
1520
- if (sys.contentType.sys.id !== "articleType") {
1521
- throw new Error(
1522
- `Invalid content type: expected "articleType", got "${sys.contentType.sys.id}"`
1523
- );
1897
+ if (sys.contentType.sys.id !== "tag") {
1898
+ throw new Error(`Invalid content type: expected "tag", got "${sys.contentType.sys.id}"`);
1524
1899
  }
1525
1900
  return createInternalLink(
1526
1901
  sys.id,
1527
1902
  {
1528
- cmsLabel: fields.name,
1529
- title: fields.name,
1530
- featuredImage: fields.featuredImage,
1531
- backgroundColour: fields.backgroundColour,
1532
- textColour: fields.textColour,
1533
- indexed: fields.indexed,
1534
- hidden: fields.hidden,
1535
- slug: fields.slug
1903
+ ...fields
1536
1904
  },
1537
1905
  context,
1538
- calculateArticleTypeHref(fields.slug),
1539
- "ArticleType"
1906
+ calculateTagHref(fields.slug),
1907
+ "Tag"
1540
1908
  );
1541
1909
  }
1542
- function baseArticleTypeConverter(context, entry) {
1910
+ function baseTagConverter(context, entry) {
1543
1911
  const { sys, fields } = entry;
1544
1912
  const { id } = sys;
1545
1913
  const {
1914
+ name,
1546
1915
  slug,
1547
- indexPageName,
1548
- indexPageDescription,
1916
+ description,
1549
1917
  featuredImage,
1918
+ tagType,
1550
1919
  menu: menuLink,
1551
1920
  footer: footerLink,
1552
- indexPageTemplate: templateLink,
1553
- indexPageTopContent: topContentLinks,
1554
- ...simpleFields
1921
+ template: templateLink,
1922
+ topContent: topContentLinks,
1923
+ ...rest
1555
1924
  } = fields;
1556
1925
  const template = templateLink ? resolveTemplate(context, templateLink) : null;
1557
1926
  const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
@@ -1559,152 +1928,34 @@ function baseArticleTypeConverter(context, entry) {
1559
1928
  const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
1560
1929
  const preContent = template?.preContent ?? [];
1561
1930
  const postContent = template?.postContent ?? [];
1562
- const indexPageContent = addPositionMetadata([...topContent, ...preContent, ...postContent]);
1563
- const articleType = {
1564
- type: "Article type",
1931
+ const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
1932
+ const tagTypeEntry = tagType ? context.includes.get(tagType.sys.id) : null;
1933
+ const tagTypeName = tagTypeEntry?.entry?.fields?.name;
1934
+ const tag = {
1935
+ type: "Tag",
1565
1936
  id,
1566
1937
  slug,
1567
- title: makeContentfulTitle(indexPageName, sys.id),
1568
- description: makeContentfulDescription(indexPageDescription, sys.id),
1938
+ title: makeContentfulTitle(name, sys.id),
1939
+ description: makeContentfulDescription(description, sys.id),
1569
1940
  featuredImage: lookupAsset(context, featuredImage),
1570
- indexPageContent,
1571
- ...simpleFields,
1941
+ tagType: tagTypeName ?? null,
1942
+ contents,
1943
+ ...rest,
1572
1944
  menu,
1573
- footer
1574
- };
1575
- return articleType;
1576
- }
1577
-
1578
- // src/converters/tag.ts
1579
- function calculateTagHref(slug) {
1580
- return `/tag/${slug}/`;
1581
- }
1582
- function baseTagLinkConverter(context, entry) {
1583
- const { sys, fields } = entry;
1584
- if (sys.contentType.sys.id !== "tag") {
1585
- throw new Error(`Invalid content type: expected "tag", got "${sys.contentType.sys.id}"`);
1586
- }
1587
- return createInternalLink(
1588
- sys.id,
1589
- {
1590
- cmsLabel: fields.cmsLabel,
1591
- title: fields.name,
1592
- featuredImage: fields.featuredImage,
1593
- backgroundColour: fields.backgroundColour,
1594
- textColour: fields.textColour,
1595
- indexed: fields.indexed,
1596
- hidden: fields.hidden,
1597
- slug: fields.slug
1598
- },
1599
- context,
1600
- calculateTagHref(fields.slug),
1601
- "Tag"
1602
- );
1603
- }
1604
-
1605
- // src/api.ts
1606
- init_utils();
1607
- var PAGE_LINK_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags";
1608
- var ARTICLE_LINK_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags,fields.articleType";
1609
- var ARTICLE_RELATED_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags,fields.articleType,fields.date,fields.author";
1610
- var ARTICLE_TYPE_LINK_FIELDS = "sys,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
1611
- var TAG_LINK_FIELDS = "sys,fields.cmsLabel,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
1612
- var PERSON_LINK_FIELDS = "sys,fields.name,fields.slug,fields.media,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
1613
- function convertAllAssets(response, context) {
1614
- const visuals = /* @__PURE__ */ new Map();
1615
- const assets = response.includes?.Asset;
1616
- if (assets && assets.length > 0) {
1617
- for (const asset of assets) {
1618
- const visual = convertAssetToVisual(context, asset);
1619
- if (visual) {
1620
- visuals.set(visual.id, visual);
1621
- }
1622
- }
1623
- }
1624
- return visuals;
1625
- }
1626
- function convertAllIncludes(response) {
1627
- const includes = /* @__PURE__ */ new Map();
1628
- const entries = [...response.items, ...response.includes?.Entry || []];
1629
- if (entries && entries.length > 0) {
1630
- for (const entry of entries) {
1631
- if (entry?.sys && entry.fields) {
1632
- includes.set(entry.sys.id, {
1633
- id: entry.sys.id,
1634
- type: entry.sys.contentType.sys.id,
1635
- entry
1636
- });
1637
- }
1638
- }
1639
- }
1640
- return includes;
1641
- }
1642
- async function contentfulPageRest(context, config, slug, options) {
1643
- const client = getContentfulClient(config, options?.preview);
1644
- const cacheTags = getCacheTags("page", slug, options?.preview);
1645
- const requestOptions = {
1646
- ...options,
1647
- next: {
1648
- ...options?.next,
1649
- tags: cacheTags
1650
- }
1651
- };
1652
- const fetchFn = async () => {
1653
- const response = await client.getEntries(
1654
- {
1655
- content_type: "page",
1656
- "fields.slug": slug,
1657
- include: 10,
1658
- locale: options?.locale,
1659
- limit: 1
1660
- },
1661
- requestOptions
1662
- );
1663
- const pageEntry = response.items[0];
1664
- if (!pageEntry || !pageEntry.fields) {
1665
- return { data: null, errors: [] };
1666
- }
1667
- try {
1668
- const assets = convertAllAssets(response, context);
1669
- const includes = convertAllIncludes(response);
1670
- const fullContext = {
1671
- ...context,
1672
- includes,
1673
- assets,
1674
- errors: []
1675
- };
1676
- const converted = fullContext.pageResolver(fullContext, pageEntry);
1677
- if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
1678
- console.error("CMS conversion errors for page:", {
1679
- pageId: pageEntry.sys.id,
1680
- slug,
1681
- errors: fullContext.errors
1682
- });
1683
- }
1684
- return { data: converted, errors: fullContext.errors };
1685
- } catch (error) {
1686
- const entryId = pageEntry.sys.id;
1687
- const entryType = pageEntry.sys.contentType?.sys?.id;
1688
- const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
1689
- const cmsError = {
1690
- entryId,
1691
- entryType,
1692
- message: errorMessage,
1693
- error
1694
- };
1695
- return { data: null, errors: [cmsError] };
1696
- }
1945
+ footer
1697
1946
  };
1698
- if (options?.retry) {
1699
- return await withRetry(fetchFn, options.retry);
1700
- }
1701
- return await fetchFn();
1947
+ return tag;
1702
1948
  }
1949
+
1950
+ // src/api/context.ts
1703
1951
  function createBaseConverterContext() {
1704
1952
  const linkResolver = /* @__PURE__ */ new Map();
1705
1953
  linkResolver.set("page", basePageLinkConverter);
1706
1954
  linkResolver.set("article", baseArticleLinkConverter);
1707
- linkResolver.set("articleType", baseArticleTypeLinkConverter);
1955
+ linkResolver.set(
1956
+ "articleType",
1957
+ baseArticleTypeLinkConverter
1958
+ );
1708
1959
  linkResolver.set("tag", baseTagLinkConverter);
1709
1960
  linkResolver.set("person", basePersonLinkConverter);
1710
1961
  linkResolver.set("pageVariant", basePageVariantLinkConverter);
@@ -1721,6 +1972,8 @@ function createBaseConverterContext() {
1721
1972
  navigationItemResolver: baseNavigationItemConverter,
1722
1973
  articleResolver: baseArticleConverter,
1723
1974
  articleTypeResolver: baseArticleTypeConverter,
1975
+ tagResolver: baseTagConverter,
1976
+ customTypeResolver: baseCustomTypeConverter,
1724
1977
  componentResolver: baseComponentConverter,
1725
1978
  collectionResolver: baseCollectionConverter,
1726
1979
  linkResolver,
@@ -1728,279 +1981,26 @@ function createBaseConverterContext() {
1728
1981
  videoPrefix: ""
1729
1982
  };
1730
1983
  }
1731
- async function contentfulArticleRest(context, config, slug, articleTypeSlug, options) {
1732
- const client = getContentfulClient(config, options?.preview);
1733
- const cacheTags = getCacheTags("article", slug, options?.preview);
1734
- const requestOptions = {
1735
- ...options,
1736
- next: {
1737
- ...options?.next,
1738
- tags: cacheTags
1739
- }
1740
- };
1741
- const fetchFn = async () => {
1742
- const response = await client.getEntries(
1743
- {
1744
- content_type: "article",
1745
- "fields.slug": slug,
1746
- "fields.articleType.sys.contentType.sys.id": "articleType",
1747
- "fields.articleType.fields.slug": articleTypeSlug,
1748
- include: 10,
1749
- locale: options?.locale,
1750
- limit: 1
1751
- },
1752
- requestOptions
1753
- );
1754
- const articleEntry = response.items[0];
1755
- if (!articleEntry || !articleEntry.fields) {
1756
- return { data: null, errors: [] };
1757
- }
1758
- const assets = convertAllAssets(response, context);
1759
- const includes = convertAllIncludes(response);
1760
- const fullContext = {
1761
- ...context,
1762
- includes,
1763
- assets,
1764
- errors: []
1765
- };
1766
- try {
1767
- const converted = fullContext.articleResolver(fullContext, articleEntry);
1768
- if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
1769
- console.error("CMS conversion errors for article:", {
1770
- articleId: articleEntry.sys.id,
1771
- slug,
1772
- articleTypeSlug,
1773
- errors: fullContext.errors
1774
- });
1775
- }
1776
- return { data: converted, errors: fullContext.errors };
1777
- } catch (error) {
1778
- const entryId = articleEntry.sys.id;
1779
- const entryType = articleEntry.sys.contentType?.sys?.id;
1780
- const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
1781
- const cmsError = {
1782
- entryId,
1783
- entryType,
1784
- message: errorMessage,
1785
- error
1786
- };
1787
- return { data: null, errors: [cmsError] };
1788
- }
1789
- };
1790
- if (options?.retry) {
1791
- return await withRetry(fetchFn, options.retry);
1792
- }
1793
- return await fetchFn();
1794
- }
1795
- async function contentfulArticleTypeRest(context, config, slug, options) {
1796
- const client = getContentfulClient(config, options?.preview);
1797
- const cacheTags = getCacheTags("articleType", slug, options?.preview);
1798
- const requestOptions = {
1799
- ...options,
1800
- next: {
1801
- ...options?.next,
1802
- tags: cacheTags
1803
- }
1804
- };
1805
- const fetchFn = async () => {
1806
- const response = await client.getEntries(
1807
- {
1808
- content_type: "articleType",
1809
- "fields.slug": slug,
1810
- include: 10,
1811
- locale: options?.locale,
1812
- limit: 1
1813
- },
1814
- requestOptions
1815
- );
1816
- const articleTypeEntry = response.items[0];
1817
- if (!articleTypeEntry || !articleTypeEntry.fields) {
1818
- return { data: null, errors: [] };
1819
- }
1820
- const assets = convertAllAssets(response, context);
1821
- const includes = convertAllIncludes(response);
1822
- const fullContext = {
1823
- ...context,
1824
- includes,
1825
- assets,
1826
- errors: []
1827
- };
1828
- try {
1829
- const converted = fullContext.articleTypeResolver(fullContext, articleTypeEntry);
1830
- if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
1831
- console.error("CMS conversion errors for article type:", {
1832
- articleTypeId: articleTypeEntry.sys.id,
1833
- slug,
1834
- errors: fullContext.errors
1835
- });
1836
- }
1837
- return { data: converted, errors: fullContext.errors };
1838
- } catch (error) {
1839
- const entryId = articleTypeEntry.sys.id;
1840
- const entryType = articleTypeEntry.sys.contentType?.sys?.id;
1841
- const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
1842
- const cmsError = {
1843
- entryId,
1844
- entryType,
1845
- message: errorMessage,
1846
- error
1847
- };
1848
- return { data: null, errors: [cmsError] };
1849
- }
1850
- };
1851
- if (options?.retry) {
1852
- return await withRetry(fetchFn, options.retry);
1853
- }
1854
- return await fetchFn();
1855
- }
1856
- function baseArticleLinkConverterWithMetadata(context, entry) {
1857
- const baseLink = baseArticleLinkConverter(context, entry);
1858
- return {
1859
- ...baseLink,
1860
- date: entry.fields.date ? new Date(entry.fields.date) : void 0,
1861
- author: entry.fields.author ? resolveLink(context, baseLink.id, entry.fields.author) : void 0,
1862
- articleType: entry.fields.articleType ? resolveLink(context, baseLink.id, entry.fields.articleType) : void 0
1863
- };
1864
- }
1865
- async function getAllArticlesForRelated(context, config, options) {
1866
- const client = getContentfulClient(config, options?.preview);
1867
- const allArticles = [];
1868
- const errors = [];
1869
- const pageSize = 100;
1870
- let skip = 0;
1871
- let hasMore = true;
1872
- const cacheTags = getCacheTags("article", void 0, options?.preview);
1873
- const requestOptions = {
1874
- ...options,
1875
- next: {
1876
- ...options?.next,
1877
- tags: cacheTags
1878
- }
1879
- };
1880
- const fetchFn = async () => {
1881
- while (hasMore) {
1882
- const response = await client.getEntries(
1883
- {
1884
- content_type: "article",
1885
- "fields.indexed": true,
1886
- "fields.hidden[ne]": true,
1887
- order: "-fields.date",
1888
- include: 2,
1889
- // Shallow include - just enough for tags, articleType, author
1890
- locale: options?.locale,
1891
- limit: pageSize,
1892
- skip,
1893
- select: ARTICLE_RELATED_FIELDS
1894
- },
1895
- requestOptions
1896
- );
1897
- if (response.items.length === 0) {
1898
- hasMore = false;
1899
- break;
1900
- }
1901
- const assets = convertAllAssets(response, context);
1902
- const includes = convertAllIncludes(response);
1903
- const fullContext = {
1904
- ...context,
1905
- includes,
1906
- assets,
1907
- errors: []
1908
- };
1909
- for (const entry of response.items) {
1910
- if (!entry.fields) continue;
1911
- try {
1912
- const converted = baseArticleLinkConverterWithMetadata(fullContext, entry);
1913
- allArticles.push(converted);
1914
- } catch (error) {
1915
- const entryId = entry.sys.id;
1916
- const entryType = entry.sys.contentType?.sys?.id;
1917
- const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
1918
- errors.push({
1919
- entryId,
1920
- entryType,
1921
- message: errorMessage,
1922
- error
1923
- });
1924
- }
1925
- }
1926
- skip += pageSize;
1927
- if (skip >= response.total) {
1928
- hasMore = false;
1929
- }
1930
- }
1931
- return { data: allArticles, errors };
1932
- };
1933
- if (options?.retry) {
1934
- return await withRetry(fetchFn, options.retry);
1935
- }
1936
- return await fetchFn();
1937
- }
1938
- async function fetchAllLinks(contentType, client, requestOptions, converter, context, pageSize = 100, select) {
1939
- const allLinks = [];
1940
- const errors = [];
1941
- let skip = 0;
1942
- let hasMore = true;
1943
- const fetchFn = async () => {
1944
- while (hasMore) {
1945
- try {
1946
- const response = await client.getEntries(
1947
- {
1948
- content_type: contentType,
1949
- include: 2,
1950
- // Minimal include for link-only fetching
1951
- locale: requestOptions?.locale,
1952
- limit: pageSize,
1953
- skip,
1954
- ...select && { select }
1955
- },
1956
- requestOptions
1957
- );
1958
- if (response.items.length === 0) {
1959
- hasMore = false;
1960
- break;
1961
- }
1962
- const includes = convertAllIncludes(response);
1963
- const assets = convertAllAssets(response, context);
1964
- const fullContext = {
1965
- ...context,
1966
- includes,
1967
- assets,
1968
- errors: []
1969
- };
1970
- for (const entry of response.items) {
1971
- if (!entry.fields) continue;
1972
- try {
1973
- const converted = converter(
1974
- fullContext,
1975
- entry
1976
- );
1977
- converted.lastModified = entry.sys.updatedAt ? new Date(entry.sys.updatedAt) : void 0;
1978
- allLinks.push(converted);
1979
- } catch (error) {
1980
- const entryId = entry.sys.id;
1981
- const entryType = entry.sys.contentType?.sys?.id;
1982
- const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
1983
- errors.push({
1984
- entryId,
1985
- entryType,
1986
- message: errorMessage,
1987
- error
1988
- });
1989
- }
1990
- }
1991
- skip += pageSize;
1992
- if (skip >= response.total) {
1993
- hasMore = false;
1994
- }
1995
- } catch (error) {
1996
- console.error("Error fetching links", typeof error, error, JSON.stringify(error, null, 2));
1997
- throw error;
1998
- }
1999
- }
2000
- return { data: allLinks, errors };
2001
- };
2002
- return await fetchFn();
1984
+
1985
+ // src/api/custom-type.ts
1986
+ async function contentfulCustomTypeRest(context, config, indexPageSlug, options) {
1987
+ return fetchSingleEntity(
1988
+ context,
1989
+ config,
1990
+ {
1991
+ contentType: "customType",
1992
+ cacheTagType: "customType",
1993
+ cacheTagIdentifier: indexPageSlug,
1994
+ query: { "fields.indexPageSlug": indexPageSlug },
1995
+ resolver: (ctx, entry) => ctx.customTypeResolver(ctx, entry),
1996
+ errorLogContext: { indexPageSlug }
1997
+ },
1998
+ options
1999
+ );
2003
2000
  }
2001
+
2002
+ // src/api/links.ts
2003
+ init_utils();
2004
2004
  async function contentfulAllPageLinks(context, config, options) {
2005
2005
  const client = getContentfulClient(config, options?.preview);
2006
2006
  const cacheTags = getCacheTags("page", void 0, options?.preview);
@@ -2121,34 +2121,67 @@ async function contentfulAllArticleTypeLinks(context, config, options) {
2121
2121
  }
2122
2122
  return await fetchFn();
2123
2123
  }
2124
+
2125
+ // src/api/page.ts
2126
+ async function contentfulPageRest(context, config, slug, options) {
2127
+ return fetchSingleEntity(
2128
+ context,
2129
+ config,
2130
+ {
2131
+ contentType: "page",
2132
+ cacheTagType: "page",
2133
+ cacheTagIdentifier: slug,
2134
+ query: { "fields.slug": slug },
2135
+ resolver: (ctx, entry) => ctx.pageResolver(ctx, entry),
2136
+ errorLogContext: { slug }
2137
+ },
2138
+ options
2139
+ );
2140
+ }
2141
+
2142
+ // src/api/related-articles.ts
2124
2143
  function filterRelatedArticles(articles, options) {
2125
- const { articleTypeId, tagIds, authorId, excludeIds, before, after, count } = options;
2144
+ const {
2145
+ excludeArticleIds,
2146
+ articleTypeIds: rawArticleTypeIds,
2147
+ tagIds: rawTagIds,
2148
+ authorIds: rawAuthorIds,
2149
+ before,
2150
+ after,
2151
+ count
2152
+ } = options;
2153
+ const excludeIds = excludeArticleIds ? [...new Set(excludeArticleIds)] : [];
2154
+ const articleTypeIds = rawArticleTypeIds ? [...new Set(rawArticleTypeIds)] : [];
2155
+ const tagIds = rawTagIds ? [...new Set(rawTagIds)] : [];
2156
+ const authorIds = rawAuthorIds ? [...new Set(rawAuthorIds)] : [];
2126
2157
  const scoredArticles = articles.map((article) => {
2127
2158
  let score = 0;
2128
- if (excludeIds?.includes(article.id)) {
2129
- return null;
2130
- }
2131
- if (articleTypeId && article.articleType?.id !== articleTypeId) {
2159
+ if (excludeIds.length > 0 && excludeIds.includes(article.id)) {
2132
2160
  return null;
2133
2161
  }
2134
- if (authorId && article.author?.id !== authorId) {
2135
- return null;
2162
+ if (articleTypeIds.length > 0) {
2163
+ if (!article.articleType?.id || !articleTypeIds.includes(article.articleType.id)) {
2164
+ return null;
2165
+ }
2136
2166
  }
2137
2167
  if (article.date) {
2138
- if (before && article.date > before) {
2168
+ const articleDate = new Date(article.date);
2169
+ if (before && articleDate > before) {
2139
2170
  return null;
2140
2171
  }
2141
- if (after && article.date < after) {
2172
+ if (after && articleDate < after) {
2142
2173
  return null;
2143
2174
  }
2144
2175
  }
2145
- if (tagIds && tagIds.length > 0 && article.tags) {
2176
+ if (tagIds.length > 0 && article.tags) {
2146
2177
  const articleTagIds = article.tags.map((tag) => tag.id);
2147
2178
  const matchingTags = tagIds.filter((tagId) => articleTagIds.includes(tagId));
2148
2179
  score += matchingTags.length * 10;
2149
2180
  }
2150
- if (authorId && article.author?.id === authorId) {
2151
- score += 5;
2181
+ if (authorIds.length > 0 && article.author?.id) {
2182
+ if (authorIds.includes(article.author.id)) {
2183
+ score += 5;
2184
+ }
2152
2185
  }
2153
2186
  return { article, score };
2154
2187
  }).filter((item) => item !== null);
@@ -2157,16 +2190,17 @@ function filterRelatedArticles(articles, options) {
2157
2190
  return b.score - a.score;
2158
2191
  }
2159
2192
  if (a.article.date && b.article.date) {
2160
- return b.article.date.getTime() - a.article.date.getTime();
2193
+ const articleDateA = new Date(a.article.date);
2194
+ const articleDateB = new Date(b.article.date);
2195
+ return articleDateB.getTime() - articleDateA.getTime();
2161
2196
  }
2162
2197
  return 0;
2163
2198
  });
2164
- const topArticles = count ? scoredArticles.slice(0, count) : scoredArticles;
2165
- return topArticles.map(({ article }) => {
2166
- const { date: _date, author: _author, articleType: _articleType, ...cleanLink } = article;
2167
- return cleanLink;
2168
- });
2199
+ const topArticles = count !== void 0 ? scoredArticles.slice(0, count) : scoredArticles;
2200
+ return topArticles.map(({ article }) => article);
2169
2201
  }
2202
+
2203
+ // src/api/sitemap.ts
2170
2204
  function linksToSitemapEntries(links, sitemapConfig) {
2171
2205
  return links.filter((link) => link.indexed !== false && link.hidden !== true && link.href).map((link) => ({
2172
2206
  url: link.href,
@@ -2226,6 +2260,60 @@ function createSitemapProvider(fetcher, sitemapConfig) {
2226
2260
  return (context, config, options) => fetcher(context, config, sitemapConfig, options);
2227
2261
  }
2228
2262
 
2263
+ // src/api/tag.ts
2264
+ async function contentfulTagRest(context, config, slug, options) {
2265
+ return fetchSingleEntity(
2266
+ context,
2267
+ config,
2268
+ {
2269
+ contentType: "tag",
2270
+ cacheTagType: "tag",
2271
+ cacheTagIdentifier: slug,
2272
+ query: { "fields.slug": slug },
2273
+ resolver: (ctx, entry) => ctx.tagResolver(ctx, entry),
2274
+ errorLogContext: { slug }
2275
+ },
2276
+ options
2277
+ );
2278
+ }
2279
+
2280
+ // src/api/template.ts
2281
+ function templateConverter(context, entry) {
2282
+ const { fields, sys } = entry;
2283
+ const id = sys.id;
2284
+ const preContent = fields.preContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
2285
+ const postContent = fields.postContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
2286
+ const menu = fields.menu ? resolveNavigation(context, fields.menu) : void 0;
2287
+ const footer = fields.footer ? resolveNavigation(context, fields.footer) : void 0;
2288
+ const stickyNav = fields.flags?.includes("Sticky nav") ?? false;
2289
+ return {
2290
+ id,
2291
+ cmsLabel: fields.cmsLabel,
2292
+ preContent,
2293
+ postContent,
2294
+ menu,
2295
+ footer,
2296
+ backgroundColour: fields.backgroundColour,
2297
+ textColour: fields.textColour,
2298
+ stickyNav
2299
+ };
2300
+ }
2301
+ async function contentfulTemplateRest(context, config, cmsLabel, options) {
2302
+ return fetchSingleEntity(
2303
+ context,
2304
+ config,
2305
+ {
2306
+ contentType: "template",
2307
+ cacheTagType: "template",
2308
+ cacheTagIdentifier: cmsLabel,
2309
+ query: { "fields.cmsLabel": cmsLabel },
2310
+ resolver: (ctx, entry) => templateConverter(ctx, entry),
2311
+ errorLogContext: { cmsLabel }
2312
+ },
2313
+ options
2314
+ );
2315
+ }
2316
+
2229
2317
  // src/revalidation/handlers.ts
2230
2318
  init_tags();
2231
2319
  init_utils();
@@ -2257,6 +2345,11 @@ var pageVariantHandler = {
2257
2345
  makeTags: (extracted) => [extracted ? pageTag(extracted) : void 0],
2258
2346
  getGlobalTags: () => [PageTag]
2259
2347
  };
2348
+ var templateHandler = {
2349
+ extract: (data) => data.fields?.cmsLabel?.[defaultLocale],
2350
+ makeTags: (extracted) => [extracted ? templateTag(extracted) : void 0],
2351
+ getGlobalTags: () => [TemplateTag]
2352
+ };
2260
2353
  var contentTypeHandlers = {
2261
2354
  page: {
2262
2355
  extract: (data) => data.fields?.slug?.[defaultLocale],
@@ -2278,11 +2371,8 @@ var contentTypeHandlers = {
2278
2371
  makeTags: (extracted) => [extracted ? tagTag(extracted) : void 0],
2279
2372
  getGlobalTags: () => [TagTag]
2280
2373
  },
2281
- template: {
2282
- extract: () => void 0,
2283
- makeTags: () => void 0,
2284
- getGlobalTags: () => ["template"]
2285
- },
2374
+ // biome-ignore lint/suspicious/noExplicitAny: Any is ok for handlers with different types
2375
+ template: templateHandler,
2286
2376
  customType: {
2287
2377
  extract: () => void 0,
2288
2378
  makeTags: () => void 0,
@@ -2446,6 +2536,6 @@ function createRevalidationHandler(config = {}) {
2446
2536
  init_tags();
2447
2537
  init_utils();
2448
2538
 
2449
- 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, contentfulPageRest, contentfulPageSitemapEntries, contentfulPersonSitemapEntries, contentfulTagSitemapEntries, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createResponsiveVisual, createRevalidationHandler, createSitemapProvider, customTypeTag, filterRelatedArticles, getAllArticlesForRelated, getAllSitemapEntries, getCacheTags, getCacheTagsForPreview, getCacheTagsForProduction, getContentfulClient, getRetryAfter, isContentfulError, isRateLimitError, isRetryableError, isValidDate, locationTag, lookupAsset, notEmpty, pageTag, personTag, resolveLink, resolveLinks, resolveRichTextDocument, revalidateSingleTag, revalidateTags, safeDate, tagTag, withRetry };
2539
+ 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, contentfulCustomTypeRest, contentfulPageRest, contentfulPageSitemapEntries, contentfulPersonSitemapEntries, contentfulTagRest, contentfulTagSitemapEntries, contentfulTemplateRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createResponsiveVisual, createRevalidationHandler, createSitemapProvider, customTypeTag, filterRelatedArticles, getAllSitemapEntries, getCacheTags, getCacheTagsForPreview, getCacheTagsForProduction, getContentfulClient, getRetryAfter, isContentfulError, isRateLimitError, isRetryableError, isValidDate, locationTag, lookupAsset, notEmpty, pageTag, personTag, resolveLink, resolveLinks, resolveRichTextDocument, revalidateSingleTag, revalidateTags, safeDate, tagTag, templateTag, withRetry };
2450
2540
  //# sourceMappingURL=index.js.map
2451
2541
  //# sourceMappingURL=index.js.map