@se-studio/contentful-rest-api 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +101 -42
- package/dist/index.js +997 -836
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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
|
}
|
|
@@ -306,14 +309,25 @@ var DEFAULT_POSITION_FIELDS = {
|
|
|
306
309
|
indexOfType: 0
|
|
307
310
|
};
|
|
308
311
|
function createInternalLink(id, fields, context, href, internalType, additionalProps) {
|
|
309
|
-
const {
|
|
312
|
+
const {
|
|
313
|
+
cmsLabel,
|
|
314
|
+
title,
|
|
315
|
+
featuredImage,
|
|
316
|
+
backgroundColour,
|
|
317
|
+
textColour,
|
|
318
|
+
indexed,
|
|
319
|
+
hidden,
|
|
320
|
+
slug,
|
|
321
|
+
description
|
|
322
|
+
} = fields;
|
|
323
|
+
const text = makeContentfulTitle(title, id);
|
|
310
324
|
return {
|
|
311
325
|
type: "Internal link",
|
|
312
326
|
internalType,
|
|
313
327
|
id,
|
|
314
328
|
name: cmsLabel ?? "",
|
|
315
329
|
useName: true,
|
|
316
|
-
text
|
|
330
|
+
text,
|
|
317
331
|
visual: lookupAsset(context, featuredImage),
|
|
318
332
|
backgroundColour,
|
|
319
333
|
textColour,
|
|
@@ -321,6 +335,8 @@ function createInternalLink(id, fields, context, href, internalType, additionalP
|
|
|
321
335
|
hidden,
|
|
322
336
|
slug,
|
|
323
337
|
href,
|
|
338
|
+
title,
|
|
339
|
+
description,
|
|
324
340
|
...additionalProps
|
|
325
341
|
};
|
|
326
342
|
}
|
|
@@ -573,6 +589,9 @@ function lookupMediaEntry(context, link) {
|
|
|
573
589
|
return void 0;
|
|
574
590
|
}
|
|
575
591
|
|
|
592
|
+
// src/api/helpers.ts
|
|
593
|
+
init_utils();
|
|
594
|
+
|
|
576
595
|
// src/utils/arrayUtils.ts
|
|
577
596
|
function notEmpty(value) {
|
|
578
597
|
if (value === null || value === void 0) return false;
|
|
@@ -620,11 +639,19 @@ function sleep(ms) {
|
|
|
620
639
|
}
|
|
621
640
|
function calculateBackoffDelay(attempt, config, retryAfter) {
|
|
622
641
|
if (retryAfter !== void 0) {
|
|
623
|
-
|
|
642
|
+
const result2 = Math.min(retryAfter * 1e3, config.maxDelay);
|
|
643
|
+
console.log(
|
|
644
|
+
`Calculated backoff delay: ${result2}ms (attempt ${attempt + 1}), retryAfter: ${retryAfter}`
|
|
645
|
+
);
|
|
646
|
+
return result2;
|
|
624
647
|
}
|
|
625
648
|
const exponentialDelay = config.initialDelay * config.backoffMultiplier ** attempt;
|
|
626
649
|
const jitter = Math.random() * exponentialDelay;
|
|
627
|
-
|
|
650
|
+
const result = Math.min(exponentialDelay + jitter, config.maxDelay);
|
|
651
|
+
console.log(
|
|
652
|
+
`Calculated backoff delay: ${result}ms (attempt ${attempt + 1}), exponentialDelay: ${exponentialDelay}, jitter: ${jitter}`
|
|
653
|
+
);
|
|
654
|
+
return result;
|
|
628
655
|
}
|
|
629
656
|
async function withRetry(fn, config) {
|
|
630
657
|
const retryConfig = {
|
|
@@ -705,6 +732,211 @@ var RateLimiter = class {
|
|
|
705
732
|
}
|
|
706
733
|
};
|
|
707
734
|
|
|
735
|
+
// src/api/helpers.ts
|
|
736
|
+
var PAGE_LINK_FIELDS = "sys,fields.cmsLabel,fields.title,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden,fields.tags";
|
|
737
|
+
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";
|
|
738
|
+
var ARTICLE_TYPE_LINK_FIELDS = "sys,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
|
|
739
|
+
var TAG_LINK_FIELDS = "sys,fields.cmsLabel,fields.name,fields.slug,fields.featuredImage,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
|
|
740
|
+
var PERSON_LINK_FIELDS = "sys,fields.name,fields.slug,fields.media,fields.backgroundColour,fields.textColour,fields.indexed,fields.hidden";
|
|
741
|
+
function convertAllAssets(response, context) {
|
|
742
|
+
const visuals = /* @__PURE__ */ new Map();
|
|
743
|
+
const assets = response.includes?.Asset;
|
|
744
|
+
if (assets && assets.length > 0) {
|
|
745
|
+
for (const asset of assets) {
|
|
746
|
+
const visual = convertAssetToVisual(context, asset);
|
|
747
|
+
if (visual) {
|
|
748
|
+
visuals.set(visual.id, visual);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return visuals;
|
|
753
|
+
}
|
|
754
|
+
function convertAllIncludes(response) {
|
|
755
|
+
const includes = /* @__PURE__ */ new Map();
|
|
756
|
+
const entries = [...response.items, ...response.includes?.Entry || []];
|
|
757
|
+
if (entries && entries.length > 0) {
|
|
758
|
+
for (const entry of entries) {
|
|
759
|
+
if (entry?.sys && entry.fields) {
|
|
760
|
+
includes.set(entry.sys.id, {
|
|
761
|
+
id: entry.sys.id,
|
|
762
|
+
type: entry.sys.contentType.sys.id,
|
|
763
|
+
entry
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return includes;
|
|
769
|
+
}
|
|
770
|
+
async function fetchSingleEntity(context, config, fetchConfig, options) {
|
|
771
|
+
const client = getContentfulClient(config, options?.preview);
|
|
772
|
+
const cacheTags = getCacheTags(
|
|
773
|
+
fetchConfig.cacheTagType,
|
|
774
|
+
fetchConfig.cacheTagIdentifier,
|
|
775
|
+
options?.preview
|
|
776
|
+
);
|
|
777
|
+
const requestOptions = {
|
|
778
|
+
...options,
|
|
779
|
+
next: {
|
|
780
|
+
...options?.next,
|
|
781
|
+
tags: cacheTags
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
const fetchFn = async () => {
|
|
785
|
+
const response = await client.getEntries(
|
|
786
|
+
{
|
|
787
|
+
content_type: fetchConfig.contentType,
|
|
788
|
+
...fetchConfig.query,
|
|
789
|
+
include: 10,
|
|
790
|
+
locale: options?.locale,
|
|
791
|
+
limit: 1
|
|
792
|
+
},
|
|
793
|
+
requestOptions
|
|
794
|
+
);
|
|
795
|
+
const entry = response.items[0];
|
|
796
|
+
if (!entry || !entry.fields) {
|
|
797
|
+
return { data: null, errors: [] };
|
|
798
|
+
}
|
|
799
|
+
try {
|
|
800
|
+
const assets = convertAllAssets(response, context);
|
|
801
|
+
const includes = convertAllIncludes(response);
|
|
802
|
+
const fullContext = {
|
|
803
|
+
...context,
|
|
804
|
+
includes,
|
|
805
|
+
assets,
|
|
806
|
+
errors: []
|
|
807
|
+
};
|
|
808
|
+
const converted = fetchConfig.resolver(fullContext, entry);
|
|
809
|
+
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
810
|
+
console.error(`CMS conversion errors for ${fetchConfig.contentType}:`, {
|
|
811
|
+
entryId: entry.sys.id,
|
|
812
|
+
...fetchConfig.errorLogContext,
|
|
813
|
+
errors: fullContext.errors
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
return { data: converted, errors: fullContext.errors };
|
|
817
|
+
} catch (error) {
|
|
818
|
+
const entryId = entry.sys.id;
|
|
819
|
+
const entryType = entry.sys.contentType?.sys?.id;
|
|
820
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
821
|
+
const cmsError = {
|
|
822
|
+
entryId,
|
|
823
|
+
entryType,
|
|
824
|
+
message: errorMessage,
|
|
825
|
+
error
|
|
826
|
+
};
|
|
827
|
+
return { data: null, errors: [cmsError] };
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
if (options?.retry) {
|
|
831
|
+
return await withRetry(fetchFn, options.retry);
|
|
832
|
+
}
|
|
833
|
+
return await fetchFn();
|
|
834
|
+
}
|
|
835
|
+
async function fetchAllLinks(contentType, client, requestOptions, converter, context, pageSize = 100, select) {
|
|
836
|
+
const allLinks = [];
|
|
837
|
+
const errors = [];
|
|
838
|
+
let skip = 0;
|
|
839
|
+
let hasMore = true;
|
|
840
|
+
const fetchFn = async () => {
|
|
841
|
+
while (hasMore) {
|
|
842
|
+
try {
|
|
843
|
+
const response = await client.getEntries(
|
|
844
|
+
{
|
|
845
|
+
content_type: contentType,
|
|
846
|
+
include: 2,
|
|
847
|
+
// Minimal include for link-only fetching
|
|
848
|
+
locale: requestOptions?.locale,
|
|
849
|
+
limit: pageSize,
|
|
850
|
+
skip,
|
|
851
|
+
...select && { select }
|
|
852
|
+
},
|
|
853
|
+
requestOptions
|
|
854
|
+
);
|
|
855
|
+
if (response.items.length === 0) {
|
|
856
|
+
hasMore = false;
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
const includes = convertAllIncludes(response);
|
|
860
|
+
const assets = convertAllAssets(response, context);
|
|
861
|
+
const fullContext = {
|
|
862
|
+
...context,
|
|
863
|
+
includes,
|
|
864
|
+
assets,
|
|
865
|
+
errors: []
|
|
866
|
+
};
|
|
867
|
+
for (const entry of response.items) {
|
|
868
|
+
if (!entry.fields) continue;
|
|
869
|
+
try {
|
|
870
|
+
const converted = converter(
|
|
871
|
+
fullContext,
|
|
872
|
+
entry
|
|
873
|
+
);
|
|
874
|
+
converted.lastModified = entry.sys.updatedAt ? new Date(entry.sys.updatedAt) : void 0;
|
|
875
|
+
allLinks.push(converted);
|
|
876
|
+
} catch (error) {
|
|
877
|
+
const entryId = entry.sys.id;
|
|
878
|
+
const entryType = entry.sys.contentType?.sys?.id;
|
|
879
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
880
|
+
errors.push({
|
|
881
|
+
entryId,
|
|
882
|
+
entryType,
|
|
883
|
+
message: errorMessage,
|
|
884
|
+
error
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
skip += pageSize;
|
|
889
|
+
if (skip >= response.total) {
|
|
890
|
+
hasMore = false;
|
|
891
|
+
}
|
|
892
|
+
} catch (error) {
|
|
893
|
+
console.error("Error fetching links", typeof error, error, JSON.stringify(error, null, 2));
|
|
894
|
+
throw error;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return { data: allLinks, errors };
|
|
898
|
+
};
|
|
899
|
+
return await fetchFn();
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/api/article.ts
|
|
903
|
+
async function contentfulArticleRest(context, config, slug, articleTypeSlug, options) {
|
|
904
|
+
return fetchSingleEntity(
|
|
905
|
+
context,
|
|
906
|
+
config,
|
|
907
|
+
{
|
|
908
|
+
contentType: "article",
|
|
909
|
+
cacheTagType: "article",
|
|
910
|
+
cacheTagIdentifier: slug,
|
|
911
|
+
query: {
|
|
912
|
+
"fields.slug": slug,
|
|
913
|
+
"fields.articleType.sys.contentType.sys.id": "articleType",
|
|
914
|
+
"fields.articleType.fields.slug": articleTypeSlug
|
|
915
|
+
},
|
|
916
|
+
resolver: (ctx, entry) => ctx.articleResolver(ctx, entry),
|
|
917
|
+
errorLogContext: { slug, articleTypeSlug }
|
|
918
|
+
},
|
|
919
|
+
options
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// src/api/article-type.ts
|
|
924
|
+
async function contentfulArticleTypeRest(context, config, indexPageSlug, options) {
|
|
925
|
+
return fetchSingleEntity(
|
|
926
|
+
context,
|
|
927
|
+
config,
|
|
928
|
+
{
|
|
929
|
+
contentType: "articleType",
|
|
930
|
+
cacheTagType: "articleType",
|
|
931
|
+
cacheTagIdentifier: indexPageSlug,
|
|
932
|
+
query: { "fields.indexPageSlug": indexPageSlug },
|
|
933
|
+
resolver: (ctx, entry) => ctx.articleTypeResolver(ctx, entry),
|
|
934
|
+
errorLogContext: { indexPageSlug }
|
|
935
|
+
},
|
|
936
|
+
options
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
|
|
708
940
|
// src/converters/resolver.ts
|
|
709
941
|
function resolveHelper(context, fromId, entry, getResolver) {
|
|
710
942
|
const id = entry.sys.id;
|
|
@@ -758,17 +990,22 @@ function resolveNavigationItem(context, fromId, entry) {
|
|
|
758
990
|
return result;
|
|
759
991
|
}
|
|
760
992
|
function resolveCollectionContent(context, fromId, entry) {
|
|
761
|
-
return resolveHelper(
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
993
|
+
return resolveHelper(
|
|
994
|
+
context,
|
|
995
|
+
fromId,
|
|
996
|
+
entry,
|
|
997
|
+
(type) => {
|
|
998
|
+
const resolver = context.contentResolver.get(type);
|
|
999
|
+
if (resolver) {
|
|
1000
|
+
return resolver;
|
|
1001
|
+
}
|
|
1002
|
+
const linkResolver = context.linkResolver.get(type);
|
|
1003
|
+
if (linkResolver) {
|
|
1004
|
+
return linkResolver;
|
|
1005
|
+
}
|
|
1006
|
+
return void 0;
|
|
769
1007
|
}
|
|
770
|
-
|
|
771
|
-
});
|
|
1008
|
+
);
|
|
772
1009
|
}
|
|
773
1010
|
function resolvePageContent(context, fromId, entry) {
|
|
774
1011
|
const id = entry.sys.id;
|
|
@@ -973,215 +1210,25 @@ function resolveRichTextDocument(context, fromId, richText) {
|
|
|
973
1210
|
return { json: resolved };
|
|
974
1211
|
}
|
|
975
1212
|
|
|
976
|
-
// src/converters/
|
|
977
|
-
function
|
|
978
|
-
const { sys, fields } = entry;
|
|
979
|
-
const { id } = sys;
|
|
1213
|
+
// src/converters/navigationItem.ts
|
|
1214
|
+
function createLink(context, entry) {
|
|
980
1215
|
const {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
collectionType,
|
|
994
|
-
showHeading,
|
|
995
|
-
heading,
|
|
996
|
-
// Already handled elsewhere
|
|
997
|
-
cmsLabel,
|
|
998
|
-
...simpleFields
|
|
999
|
-
// anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
|
|
1216
|
+
sys: { id },
|
|
1217
|
+
fields
|
|
1218
|
+
} = entry;
|
|
1219
|
+
const {
|
|
1220
|
+
title,
|
|
1221
|
+
link,
|
|
1222
|
+
text,
|
|
1223
|
+
internal,
|
|
1224
|
+
icon: navIcon,
|
|
1225
|
+
mobileIcon: mobileNavIcon,
|
|
1226
|
+
useTitle,
|
|
1227
|
+
...otherFields
|
|
1000
1228
|
} = fields;
|
|
1001
|
-
const
|
|
1002
|
-
lookupAsset(context,
|
|
1003
|
-
lookupAsset(context,
|
|
1004
|
-
);
|
|
1005
|
-
const visual = createResponsiveVisual(
|
|
1006
|
-
lookupMediaEntry(context, visualField),
|
|
1007
|
-
lookupMediaEntry(context, mobileVisualField),
|
|
1008
|
-
visualCustomSize
|
|
1009
|
-
);
|
|
1010
|
-
const collection = {
|
|
1011
|
-
type: "Collection",
|
|
1012
|
-
id,
|
|
1013
|
-
name: cmsLabel,
|
|
1014
|
-
cmsLabel,
|
|
1015
|
-
collectionType,
|
|
1016
|
-
...DEFAULT_POSITION_FIELDS,
|
|
1017
|
-
...simpleFields,
|
|
1018
|
-
heading: showHeading ? heading : void 0,
|
|
1019
|
-
body: resolveRichTextDocument(context, id, bodyField),
|
|
1020
|
-
additionalCopy: resolveRichTextDocument(context, id, additionalCopyField),
|
|
1021
|
-
icon: lookupAsset(context, iconField),
|
|
1022
|
-
backgroundVisual,
|
|
1023
|
-
visual,
|
|
1024
|
-
links: linksField?.map((link) => resolveLink(context, id, link)),
|
|
1025
|
-
contents: contentsField?.map((content) => resolveCollectionContent(context, id, content))
|
|
1026
|
-
};
|
|
1027
|
-
return collection;
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// src/converters/component.ts
|
|
1031
|
-
function baseComponentConverter(context, entry) {
|
|
1032
|
-
const { sys, fields } = entry;
|
|
1033
|
-
const { id } = sys;
|
|
1034
|
-
const {
|
|
1035
|
-
// Fields requiring transformation
|
|
1036
|
-
backgroundVisual: bgVisual,
|
|
1037
|
-
mobileBackgroundVisual: mobileBgVisual,
|
|
1038
|
-
visual: visualField,
|
|
1039
|
-
mobileVisual: mobileVisualField,
|
|
1040
|
-
visualCustomSize,
|
|
1041
|
-
icon: iconField,
|
|
1042
|
-
links: linksField,
|
|
1043
|
-
body: bodyField,
|
|
1044
|
-
additionalCopy: additionalCopyField,
|
|
1045
|
-
// Field name change
|
|
1046
|
-
componentType,
|
|
1047
|
-
showHeading,
|
|
1048
|
-
heading,
|
|
1049
|
-
otherMedia: otherMediaField,
|
|
1050
|
-
// Already handled elsewhere
|
|
1051
|
-
cmsLabel,
|
|
1052
|
-
...simpleFields
|
|
1053
|
-
// anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
|
|
1054
|
-
} = fields;
|
|
1055
|
-
const backgroundVisual = createResponsiveVisual(
|
|
1056
|
-
lookupAsset(context, bgVisual),
|
|
1057
|
-
lookupAsset(context, mobileBgVisual)
|
|
1058
|
-
);
|
|
1059
|
-
const visual = createResponsiveVisual(
|
|
1060
|
-
lookupMediaEntry(context, visualField),
|
|
1061
|
-
lookupMediaEntry(context, mobileVisualField),
|
|
1062
|
-
visualCustomSize
|
|
1063
|
-
);
|
|
1064
|
-
const otherMedia = otherMediaField?.map((media) => lookupAsset(context, media));
|
|
1065
|
-
const component = {
|
|
1066
|
-
type: "Component",
|
|
1067
|
-
id,
|
|
1068
|
-
name: cmsLabel,
|
|
1069
|
-
cmsLabel,
|
|
1070
|
-
componentType,
|
|
1071
|
-
...DEFAULT_POSITION_FIELDS,
|
|
1072
|
-
...simpleFields,
|
|
1073
|
-
heading: showHeading ? heading : void 0,
|
|
1074
|
-
body: resolveRichTextDocument(context, id, bodyField),
|
|
1075
|
-
additionalCopy: resolveRichTextDocument(context, id, additionalCopyField),
|
|
1076
|
-
icon: lookupAsset(context, iconField),
|
|
1077
|
-
backgroundVisual,
|
|
1078
|
-
visual,
|
|
1079
|
-
links: resolveLinks(context, id, linksField),
|
|
1080
|
-
otherMedia: arrayOrUndefined(otherMedia?.filter(notEmpty))
|
|
1081
|
-
};
|
|
1082
|
-
return component;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
// src/converters/link.ts
|
|
1086
|
-
function baseLinkConverter(context, entry) {
|
|
1087
|
-
const { sys, fields } = entry;
|
|
1088
|
-
if (sys.contentType.sys.id !== "link") {
|
|
1089
|
-
throw new Error(`Invalid content type: expected "link", got "${sys.contentType.sys.id}"`);
|
|
1090
|
-
}
|
|
1091
|
-
const id = sys.id;
|
|
1092
|
-
const name = fields.name;
|
|
1093
|
-
const useName = fields.useName;
|
|
1094
|
-
const text = resolveBuildYear(
|
|
1095
|
-
useName ? name : fields.linkText ?? makeContentfulTitle(fields.linkText, id, "Link text for ")
|
|
1096
|
-
);
|
|
1097
|
-
const icon = createResponsiveVisual(
|
|
1098
|
-
lookupAsset(context, fields.icon),
|
|
1099
|
-
lookupAsset(context, fields.mobileIcon)
|
|
1100
|
-
);
|
|
1101
|
-
const backgroundColour = fields.backgroundColour ?? null;
|
|
1102
|
-
const textColour = fields.textColour ?? null;
|
|
1103
|
-
const variant = fields.variant;
|
|
1104
|
-
const size = fields.size;
|
|
1105
|
-
const baseProps = {
|
|
1106
|
-
id,
|
|
1107
|
-
useName,
|
|
1108
|
-
name,
|
|
1109
|
-
text,
|
|
1110
|
-
icon,
|
|
1111
|
-
backgroundColour,
|
|
1112
|
-
textColour,
|
|
1113
|
-
variant,
|
|
1114
|
-
size
|
|
1115
|
-
};
|
|
1116
|
-
if (fields.internal) {
|
|
1117
|
-
const internalTarget = resolveLink(context, id, fields.internal);
|
|
1118
|
-
return {
|
|
1119
|
-
...baseProps,
|
|
1120
|
-
type: "Internal link",
|
|
1121
|
-
internalType: internalTarget.internalType,
|
|
1122
|
-
href: internalTarget.href,
|
|
1123
|
-
slug: internalTarget.slug,
|
|
1124
|
-
indexed: internalTarget.indexed,
|
|
1125
|
-
hidden: internalTarget.hidden,
|
|
1126
|
-
tags: internalTarget.tags
|
|
1127
|
-
};
|
|
1128
|
-
}
|
|
1129
|
-
if (fields.external) {
|
|
1130
|
-
return {
|
|
1131
|
-
...baseProps,
|
|
1132
|
-
type: "External link",
|
|
1133
|
-
href: fields.external
|
|
1134
|
-
};
|
|
1135
|
-
}
|
|
1136
|
-
if (fields.downloadAsset) {
|
|
1137
|
-
const asset = lookupAsset(context, fields.downloadAsset);
|
|
1138
|
-
let href = null;
|
|
1139
|
-
if (asset?.image?.type === "Picture") {
|
|
1140
|
-
href = asset.image.src;
|
|
1141
|
-
} else if (asset?.image?.type === "Svg image") {
|
|
1142
|
-
href = asset.image.svgSrc;
|
|
1143
|
-
} else if (asset?.video) {
|
|
1144
|
-
if (asset.video.type === "Local video") {
|
|
1145
|
-
href = asset.video.preview.videoUrl;
|
|
1146
|
-
} else if (asset.video.type === "Full video") {
|
|
1147
|
-
href = asset.video.full.videoUrl;
|
|
1148
|
-
} else if (asset.video.type === "External video") {
|
|
1149
|
-
href = asset.video.external;
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
return {
|
|
1153
|
-
...baseProps,
|
|
1154
|
-
type: "Download link",
|
|
1155
|
-
href,
|
|
1156
|
-
visual: asset
|
|
1157
|
-
};
|
|
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)
|
|
1229
|
+
const icon = createResponsiveVisual(
|
|
1230
|
+
lookupAsset(context, navIcon),
|
|
1231
|
+
lookupAsset(context, mobileNavIcon)
|
|
1185
1232
|
);
|
|
1186
1233
|
const realText = useTitle ? resolveBuildYear(title) : text ? resolveBuildYear(text) : void 0;
|
|
1187
1234
|
if (link) {
|
|
@@ -1236,14 +1283,13 @@ function resolveNavigation(context, link) {
|
|
|
1236
1283
|
if (!fields) {
|
|
1237
1284
|
return void 0;
|
|
1238
1285
|
}
|
|
1239
|
-
const
|
|
1240
|
-
const
|
|
1286
|
+
const { name, entries: fieldEntries, ...rest } = fields;
|
|
1287
|
+
const entries = fieldEntries?.map((item) => resolveNavigationItem(context, id, item)) ?? [];
|
|
1241
1288
|
return {
|
|
1242
1289
|
id,
|
|
1243
1290
|
name,
|
|
1244
1291
|
entries,
|
|
1245
|
-
|
|
1246
|
-
backgroundColour
|
|
1292
|
+
...rest
|
|
1247
1293
|
};
|
|
1248
1294
|
}
|
|
1249
1295
|
|
|
@@ -1276,12 +1322,25 @@ function resolveTemplate(context, link) {
|
|
|
1276
1322
|
};
|
|
1277
1323
|
}
|
|
1278
1324
|
|
|
1279
|
-
// src/converters/
|
|
1280
|
-
function
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1325
|
+
// src/converters/article.ts
|
|
1326
|
+
function resolveArticleTemplateHierarchy(context, articleTypeLink, directTemplateLink) {
|
|
1327
|
+
if (directTemplateLink) {
|
|
1328
|
+
return resolveTemplate(context, directTemplateLink);
|
|
1329
|
+
}
|
|
1330
|
+
const articleTypeEntry = context.includes.get(articleTypeLink.sys.id);
|
|
1331
|
+
if (!articleTypeEntry) {
|
|
1332
|
+
console.warn(`ArticleType entry not found for id: ${articleTypeLink.sys.id}`);
|
|
1333
|
+
return null;
|
|
1334
|
+
}
|
|
1335
|
+
const articleTypeFields = articleTypeEntry.entry.fields;
|
|
1336
|
+
if (articleTypeFields?.articleTemplate) {
|
|
1337
|
+
return resolveTemplate(context, articleTypeFields.articleTemplate);
|
|
1338
|
+
}
|
|
1339
|
+
return null;
|
|
1340
|
+
}
|
|
1341
|
+
function baseArticleConverter(context, entry) {
|
|
1342
|
+
const { sys, fields } = entry;
|
|
1343
|
+
const { id } = sys;
|
|
1285
1344
|
const {
|
|
1286
1345
|
slug,
|
|
1287
1346
|
title,
|
|
@@ -1289,60 +1348,61 @@ function basePageConverter(context, entry) {
|
|
|
1289
1348
|
featuredImage,
|
|
1290
1349
|
tags,
|
|
1291
1350
|
content,
|
|
1292
|
-
menu: pageMenu,
|
|
1293
|
-
footer: pageFooter,
|
|
1294
1351
|
template: templateLink,
|
|
1295
1352
|
topContent: topContentLinks,
|
|
1296
1353
|
bottomContent: bottomContentLinks,
|
|
1354
|
+
articleType,
|
|
1297
1355
|
...simpleFields
|
|
1298
1356
|
} = fields;
|
|
1299
|
-
const
|
|
1300
|
-
const
|
|
1301
|
-
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
1357
|
+
const articleTypeLink = resolveLink(context, id, articleType);
|
|
1358
|
+
const template = resolveArticleTemplateHierarchy(context, articleType, templateLink);
|
|
1302
1359
|
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1303
|
-
const
|
|
1360
|
+
const articleContent = content?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1304
1361
|
const bottomContent = bottomContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1305
1362
|
const preContent = template?.preContent ?? [];
|
|
1306
1363
|
const postContent = template?.postContent ?? [];
|
|
1307
1364
|
const contents = addPositionMetadata([
|
|
1308
1365
|
...topContent,
|
|
1309
1366
|
...preContent,
|
|
1310
|
-
...
|
|
1367
|
+
...articleContent,
|
|
1311
1368
|
...postContent,
|
|
1312
1369
|
...bottomContent
|
|
1313
1370
|
]);
|
|
1314
|
-
const
|
|
1315
|
-
type: "
|
|
1371
|
+
const article = {
|
|
1372
|
+
type: "Article",
|
|
1316
1373
|
id,
|
|
1317
|
-
isHomePage: slug === "index",
|
|
1318
1374
|
slug,
|
|
1319
|
-
title: makeContentfulTitle(title, id),
|
|
1320
|
-
description: makeContentfulDescription(description, id),
|
|
1375
|
+
title: makeContentfulTitle(title, sys.id),
|
|
1376
|
+
description: makeContentfulDescription(description, sys.id),
|
|
1321
1377
|
featuredImage: lookupAsset(context, featuredImage),
|
|
1378
|
+
articleType: articleTypeLink,
|
|
1322
1379
|
tags: tags?.map((tag) => resolveLink(context, id, tag)),
|
|
1323
1380
|
contents,
|
|
1324
1381
|
...simpleFields,
|
|
1325
|
-
|
|
1326
|
-
|
|
1382
|
+
// Note: summary field exists in Contentful but is not part of IArticle interface
|
|
1383
|
+
// Keeping it in simpleFields for potential future use
|
|
1384
|
+
menu: template?.menu,
|
|
1385
|
+
footer: template?.footer
|
|
1327
1386
|
};
|
|
1328
|
-
return
|
|
1387
|
+
return article;
|
|
1329
1388
|
}
|
|
1330
|
-
function
|
|
1331
|
-
if (slug === "index") {
|
|
1332
|
-
return "/";
|
|
1333
|
-
}
|
|
1389
|
+
function calculateArticleTypeHref(slug) {
|
|
1334
1390
|
return `/${slug}/`;
|
|
1335
1391
|
}
|
|
1336
|
-
function
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
} = entry;
|
|
1341
|
-
if (contentType.sys.id !== "
|
|
1342
|
-
throw new Error(`Invalid content type: expected "
|
|
1392
|
+
function calculateArticleHref(articleTypeSlug, slug) {
|
|
1393
|
+
return `${calculateArticleTypeHref(articleTypeSlug)}${slug}/`;
|
|
1394
|
+
}
|
|
1395
|
+
function baseArticleLinkConverter(context, entry) {
|
|
1396
|
+
const { sys, fields } = entry;
|
|
1397
|
+
if (sys.contentType.sys.id !== "article") {
|
|
1398
|
+
throw new Error(`Invalid content type: expected "article", got "${sys.contentType.sys.id}"`);
|
|
1343
1399
|
}
|
|
1400
|
+
const articleTypeLink = resolveLink(context, sys.id, fields.articleType);
|
|
1401
|
+
const tags = fields.tags?.map((tag) => resolveLink(context, sys.id, tag));
|
|
1402
|
+
const primaryTag = tags?.[0] ?? void 0;
|
|
1403
|
+
const author = fields.author ? resolveLink(context, sys.id, fields.author) : void 0;
|
|
1344
1404
|
return createInternalLink(
|
|
1345
|
-
id,
|
|
1405
|
+
sys.id,
|
|
1346
1406
|
{
|
|
1347
1407
|
cmsLabel: fields.cmsLabel,
|
|
1348
1408
|
title: fields.title,
|
|
@@ -1354,58 +1414,30 @@ function basePageLinkConverter(context, entry) {
|
|
|
1354
1414
|
slug: fields.slug
|
|
1355
1415
|
},
|
|
1356
1416
|
context,
|
|
1357
|
-
|
|
1358
|
-
"
|
|
1359
|
-
{
|
|
1417
|
+
calculateArticleHref(articleTypeLink.slug, fields.slug),
|
|
1418
|
+
"Article",
|
|
1419
|
+
{
|
|
1420
|
+
tags,
|
|
1421
|
+
primaryTag,
|
|
1422
|
+
articleType: articleTypeLink,
|
|
1423
|
+
date: fields.date,
|
|
1424
|
+
author
|
|
1425
|
+
}
|
|
1360
1426
|
);
|
|
1361
1427
|
}
|
|
1362
|
-
function
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
fields
|
|
1369
|
-
} = entry;
|
|
1370
|
-
if (contentType.sys.id !== "pageVariant") {
|
|
1371
|
-
throw new Error(`Invalid content type: expected "pageVariant", got "${contentType.sys.id}"`);
|
|
1428
|
+
function baseArticleTypeLinkConverter(context, entry) {
|
|
1429
|
+
const { sys, fields } = entry;
|
|
1430
|
+
if (sys.contentType.sys.id !== "articleType") {
|
|
1431
|
+
throw new Error(
|
|
1432
|
+
`Invalid content type: expected "articleType", got "${sys.contentType.sys.id}"`
|
|
1433
|
+
);
|
|
1372
1434
|
}
|
|
1373
1435
|
return createInternalLink(
|
|
1374
|
-
id,
|
|
1375
|
-
{
|
|
1376
|
-
cmsLabel: fields.cmsLabel,
|
|
1377
|
-
title: fields.title,
|
|
1378
|
-
featuredImage: fields.featuredImage,
|
|
1379
|
-
backgroundColour: fields.backgroundColour,
|
|
1380
|
-
textColour: fields.textColour,
|
|
1381
|
-
indexed: fields.indexed,
|
|
1382
|
-
hidden: fields.hidden,
|
|
1383
|
-
slug: fields.slug
|
|
1384
|
-
},
|
|
1385
|
-
context,
|
|
1386
|
-
calculatePageVariantHref(fields.slug),
|
|
1387
|
-
"Page",
|
|
1388
|
-
{ tags: fields.tags?.map((tag) => resolveLink(context, id, tag)) }
|
|
1389
|
-
);
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
// src/converters/person.ts
|
|
1393
|
-
function calculatePersonHref(slug) {
|
|
1394
|
-
return `/people/${slug}/`;
|
|
1395
|
-
}
|
|
1396
|
-
function basePersonLinkConverter(context, entry) {
|
|
1397
|
-
const { sys, fields } = entry;
|
|
1398
|
-
if (sys.contentType.sys.id !== "person") {
|
|
1399
|
-
throw new Error(`Invalid content type: expected "person", got "${sys.contentType.sys.id}"`);
|
|
1400
|
-
}
|
|
1401
|
-
return createInternalLink(
|
|
1402
|
-
sys.id,
|
|
1436
|
+
sys.id,
|
|
1403
1437
|
{
|
|
1404
1438
|
cmsLabel: fields.name,
|
|
1405
|
-
// Person has no cmsLabel, use name field
|
|
1406
1439
|
title: fields.name,
|
|
1407
|
-
featuredImage: fields.
|
|
1408
|
-
// Person uses 'media' not 'featuredImage'
|
|
1440
|
+
featuredImage: fields.featuredImage,
|
|
1409
1441
|
backgroundColour: fields.backgroundColour,
|
|
1410
1442
|
textColour: fields.textColour,
|
|
1411
1443
|
indexed: fields.indexed,
|
|
@@ -1413,137 +1445,161 @@ function basePersonLinkConverter(context, entry) {
|
|
|
1413
1445
|
slug: fields.slug
|
|
1414
1446
|
},
|
|
1415
1447
|
context,
|
|
1416
|
-
|
|
1417
|
-
"
|
|
1448
|
+
calculateArticleTypeHref(fields.slug),
|
|
1449
|
+
"ArticleType",
|
|
1450
|
+
{ indexPageSlug: fields.indexPageSlug }
|
|
1418
1451
|
);
|
|
1419
1452
|
}
|
|
1420
|
-
|
|
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) {
|
|
1453
|
+
function baseArticleTypeConverter(context, entry) {
|
|
1438
1454
|
const { sys, fields } = entry;
|
|
1439
1455
|
const { id } = sys;
|
|
1440
1456
|
const {
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1457
|
+
indexPageSlug,
|
|
1458
|
+
indexPageName,
|
|
1459
|
+
indexPageDescription,
|
|
1444
1460
|
featuredImage,
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
...
|
|
1461
|
+
menu: menuLink,
|
|
1462
|
+
footer: footerLink,
|
|
1463
|
+
indexPageTemplate: templateLink,
|
|
1464
|
+
indexPageTopContent: topContentLinks,
|
|
1465
|
+
structuredData,
|
|
1466
|
+
slug: _slug,
|
|
1467
|
+
...other
|
|
1452
1468
|
} = fields;
|
|
1453
|
-
const
|
|
1454
|
-
const
|
|
1469
|
+
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
1470
|
+
const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
|
|
1471
|
+
const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
|
|
1455
1472
|
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
1473
|
const preContent = template?.preContent ?? [];
|
|
1459
1474
|
const postContent = template?.postContent ?? [];
|
|
1460
|
-
const contents = addPositionMetadata([
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
...articleContent,
|
|
1464
|
-
...postContent,
|
|
1465
|
-
...bottomContent
|
|
1466
|
-
]);
|
|
1467
|
-
const article = {
|
|
1468
|
-
type: "Article",
|
|
1475
|
+
const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
|
|
1476
|
+
const articleType = {
|
|
1477
|
+
type: "Article type",
|
|
1469
1478
|
id,
|
|
1470
|
-
slug,
|
|
1471
|
-
title: makeContentfulTitle(
|
|
1472
|
-
description: makeContentfulDescription(
|
|
1479
|
+
slug: indexPageSlug,
|
|
1480
|
+
title: makeContentfulTitle(indexPageName, sys.id),
|
|
1481
|
+
description: makeContentfulDescription(indexPageDescription, sys.id),
|
|
1473
1482
|
featuredImage: lookupAsset(context, featuredImage),
|
|
1474
|
-
articleType: articleTypeLink,
|
|
1475
|
-
tags: tags?.map((tag) => resolveLink(context, id, tag)),
|
|
1476
1483
|
contents,
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
footer: template?.footer
|
|
1484
|
+
structuredData,
|
|
1485
|
+
menu,
|
|
1486
|
+
footer,
|
|
1487
|
+
...other
|
|
1482
1488
|
};
|
|
1483
|
-
return
|
|
1484
|
-
}
|
|
1485
|
-
function calculateArticleTypeHref(slug) {
|
|
1486
|
-
return `/${slug}/`;
|
|
1487
|
-
}
|
|
1488
|
-
function calculateArticleHref(articleTypeSlug, slug) {
|
|
1489
|
-
return `${calculateArticleTypeHref(articleTypeSlug)}${slug}/`;
|
|
1489
|
+
return articleType;
|
|
1490
1490
|
}
|
|
1491
|
-
|
|
1491
|
+
|
|
1492
|
+
// src/converters/collection.ts
|
|
1493
|
+
function baseCollectionConverter(context, entry) {
|
|
1492
1494
|
const { sys, fields } = entry;
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1495
|
+
const { id } = sys;
|
|
1496
|
+
const {
|
|
1497
|
+
// Fields requiring transformation
|
|
1498
|
+
backgroundVisual: bgVisual,
|
|
1499
|
+
mobileBackgroundVisual: mobileBgVisual,
|
|
1500
|
+
visual: visualField,
|
|
1501
|
+
mobileVisual: mobileVisualField,
|
|
1502
|
+
visualCustomSize,
|
|
1503
|
+
icon: iconField,
|
|
1504
|
+
links: linksField,
|
|
1505
|
+
contents: contentsField,
|
|
1506
|
+
body: bodyField,
|
|
1507
|
+
additionalCopy: additionalCopyField,
|
|
1508
|
+
showHeading,
|
|
1509
|
+
heading,
|
|
1510
|
+
// Already handled elsewhere
|
|
1511
|
+
cmsLabel,
|
|
1512
|
+
...simpleFields
|
|
1513
|
+
// anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
|
|
1514
|
+
} = fields;
|
|
1515
|
+
const backgroundVisual = createResponsiveVisual(
|
|
1516
|
+
lookupAsset(context, bgVisual),
|
|
1517
|
+
lookupAsset(context, mobileBgVisual)
|
|
1518
|
+
);
|
|
1519
|
+
const visual = createResponsiveVisual(
|
|
1520
|
+
lookupMediaEntry(context, visualField),
|
|
1521
|
+
lookupMediaEntry(context, mobileVisualField),
|
|
1522
|
+
visualCustomSize
|
|
1516
1523
|
);
|
|
1524
|
+
const collection = {
|
|
1525
|
+
type: "Collection",
|
|
1526
|
+
id,
|
|
1527
|
+
name: cmsLabel,
|
|
1528
|
+
cmsLabel,
|
|
1529
|
+
...DEFAULT_POSITION_FIELDS,
|
|
1530
|
+
...simpleFields,
|
|
1531
|
+
heading: showHeading ? heading : void 0,
|
|
1532
|
+
body: resolveRichTextDocument(context, id, bodyField),
|
|
1533
|
+
additionalCopy: resolveRichTextDocument(context, id, additionalCopyField),
|
|
1534
|
+
icon: lookupAsset(context, iconField),
|
|
1535
|
+
backgroundVisual,
|
|
1536
|
+
visual,
|
|
1537
|
+
links: linksField?.map((link) => resolveLink(context, id, link)),
|
|
1538
|
+
contents: contentsField?.map((content) => resolveCollectionContent(context, id, content))
|
|
1539
|
+
};
|
|
1540
|
+
return collection;
|
|
1517
1541
|
}
|
|
1518
|
-
|
|
1542
|
+
|
|
1543
|
+
// src/converters/component.ts
|
|
1544
|
+
function baseComponentConverter(context, entry) {
|
|
1519
1545
|
const { sys, fields } = entry;
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1546
|
+
const { id } = sys;
|
|
1547
|
+
const {
|
|
1548
|
+
// Fields requiring transformation
|
|
1549
|
+
backgroundVisual: bgVisual,
|
|
1550
|
+
mobileBackgroundVisual: mobileBgVisual,
|
|
1551
|
+
visual: visualField,
|
|
1552
|
+
mobileVisual: mobileVisualField,
|
|
1553
|
+
visualCustomSize,
|
|
1554
|
+
icon: iconField,
|
|
1555
|
+
links: linksField,
|
|
1556
|
+
body: bodyField,
|
|
1557
|
+
additionalCopy: additionalCopyField,
|
|
1558
|
+
// Field name change
|
|
1559
|
+
showHeading,
|
|
1560
|
+
heading,
|
|
1561
|
+
otherMedia: otherMediaField,
|
|
1562
|
+
// Already handled elsewhere
|
|
1563
|
+
cmsLabel,
|
|
1564
|
+
...simpleFields
|
|
1565
|
+
// anchor, backgroundColour, textColour, preHeading, heading, postHeading, backgroundOverlayOpacity
|
|
1566
|
+
} = fields;
|
|
1567
|
+
const backgroundVisual = createResponsiveVisual(
|
|
1568
|
+
lookupAsset(context, bgVisual),
|
|
1569
|
+
lookupAsset(context, mobileBgVisual)
|
|
1570
|
+
);
|
|
1571
|
+
const visual = createResponsiveVisual(
|
|
1572
|
+
lookupMediaEntry(context, visualField),
|
|
1573
|
+
lookupMediaEntry(context, mobileVisualField),
|
|
1574
|
+
visualCustomSize
|
|
1540
1575
|
);
|
|
1576
|
+
const otherMedia = otherMediaField?.map((media) => lookupAsset(context, media));
|
|
1577
|
+
const component = {
|
|
1578
|
+
type: "Component",
|
|
1579
|
+
id,
|
|
1580
|
+
name: cmsLabel,
|
|
1581
|
+
cmsLabel,
|
|
1582
|
+
...DEFAULT_POSITION_FIELDS,
|
|
1583
|
+
...simpleFields,
|
|
1584
|
+
heading: showHeading ? heading : void 0,
|
|
1585
|
+
body: resolveRichTextDocument(context, id, bodyField),
|
|
1586
|
+
additionalCopy: resolveRichTextDocument(context, id, additionalCopyField),
|
|
1587
|
+
icon: lookupAsset(context, iconField),
|
|
1588
|
+
backgroundVisual,
|
|
1589
|
+
visual,
|
|
1590
|
+
links: resolveLinks(context, id, linksField),
|
|
1591
|
+
otherMedia: arrayOrUndefined(otherMedia?.filter(notEmpty))
|
|
1592
|
+
};
|
|
1593
|
+
return component;
|
|
1541
1594
|
}
|
|
1542
|
-
|
|
1595
|
+
|
|
1596
|
+
// src/converters/customType.ts
|
|
1597
|
+
function baseCustomTypeConverter(context, entry) {
|
|
1543
1598
|
const { sys, fields } = entry;
|
|
1544
1599
|
const { id } = sys;
|
|
1545
1600
|
const {
|
|
1546
1601
|
slug,
|
|
1602
|
+
indexPageSlug,
|
|
1547
1603
|
indexPageName,
|
|
1548
1604
|
indexPageDescription,
|
|
1549
1605
|
featuredImage,
|
|
@@ -1551,7 +1607,8 @@ function baseArticleTypeConverter(context, entry) {
|
|
|
1551
1607
|
footer: footerLink,
|
|
1552
1608
|
indexPageTemplate: templateLink,
|
|
1553
1609
|
indexPageTopContent: topContentLinks,
|
|
1554
|
-
|
|
1610
|
+
structuredData,
|
|
1611
|
+
...other
|
|
1555
1612
|
} = fields;
|
|
1556
1613
|
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
1557
1614
|
const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
|
|
@@ -1559,36 +1616,179 @@ function baseArticleTypeConverter(context, entry) {
|
|
|
1559
1616
|
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1560
1617
|
const preContent = template?.preContent ?? [];
|
|
1561
1618
|
const postContent = template?.postContent ?? [];
|
|
1562
|
-
const
|
|
1563
|
-
const
|
|
1564
|
-
type: "
|
|
1619
|
+
const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
|
|
1620
|
+
const customType = {
|
|
1621
|
+
type: "Custom type",
|
|
1565
1622
|
id,
|
|
1566
1623
|
slug,
|
|
1624
|
+
indexPageSlug,
|
|
1625
|
+
indexPageName: makeContentfulTitle(indexPageName, sys.id),
|
|
1626
|
+
indexPageDescription: makeContentfulDescription(indexPageDescription, sys.id),
|
|
1567
1627
|
title: makeContentfulTitle(indexPageName, sys.id),
|
|
1568
1628
|
description: makeContentfulDescription(indexPageDescription, sys.id),
|
|
1569
1629
|
featuredImage: lookupAsset(context, featuredImage),
|
|
1570
|
-
|
|
1571
|
-
|
|
1630
|
+
contents,
|
|
1631
|
+
structuredData,
|
|
1572
1632
|
menu,
|
|
1573
|
-
footer
|
|
1633
|
+
footer,
|
|
1634
|
+
...other
|
|
1574
1635
|
};
|
|
1575
|
-
return
|
|
1636
|
+
return customType;
|
|
1576
1637
|
}
|
|
1577
1638
|
|
|
1578
|
-
// src/converters/
|
|
1579
|
-
function
|
|
1580
|
-
return `/tag/${slug}/`;
|
|
1581
|
-
}
|
|
1582
|
-
function baseTagLinkConverter(context, entry) {
|
|
1639
|
+
// src/converters/link.ts
|
|
1640
|
+
function baseLinkConverter(context, entry) {
|
|
1583
1641
|
const { sys, fields } = entry;
|
|
1584
|
-
if (sys.contentType.sys.id !== "
|
|
1585
|
-
throw new Error(`Invalid content type: expected "
|
|
1642
|
+
if (sys.contentType.sys.id !== "link") {
|
|
1643
|
+
throw new Error(`Invalid content type: expected "link", got "${sys.contentType.sys.id}"`);
|
|
1644
|
+
}
|
|
1645
|
+
const id = sys.id;
|
|
1646
|
+
const name = fields.name;
|
|
1647
|
+
const useName = fields.useName;
|
|
1648
|
+
const text = resolveBuildYear(
|
|
1649
|
+
useName ? name : fields.linkText ?? makeContentfulTitle(fields.linkText, id, "Link text for ")
|
|
1650
|
+
);
|
|
1651
|
+
const icon = createResponsiveVisual(
|
|
1652
|
+
lookupAsset(context, fields.icon),
|
|
1653
|
+
lookupAsset(context, fields.mobileIcon)
|
|
1654
|
+
);
|
|
1655
|
+
const backgroundColour = fields.backgroundColour ?? null;
|
|
1656
|
+
const textColour = fields.textColour ?? null;
|
|
1657
|
+
const variant = fields.variant;
|
|
1658
|
+
const size = fields.size;
|
|
1659
|
+
const baseProps = {
|
|
1660
|
+
id,
|
|
1661
|
+
useName,
|
|
1662
|
+
name,
|
|
1663
|
+
text,
|
|
1664
|
+
icon,
|
|
1665
|
+
backgroundColour,
|
|
1666
|
+
textColour,
|
|
1667
|
+
variant,
|
|
1668
|
+
size
|
|
1669
|
+
};
|
|
1670
|
+
if (fields.internal) {
|
|
1671
|
+
const internalTarget = resolveLink(context, id, fields.internal);
|
|
1672
|
+
return {
|
|
1673
|
+
...baseProps,
|
|
1674
|
+
type: "Internal link",
|
|
1675
|
+
internalType: internalTarget.internalType,
|
|
1676
|
+
href: internalTarget.href,
|
|
1677
|
+
slug: internalTarget.slug,
|
|
1678
|
+
indexed: internalTarget.indexed,
|
|
1679
|
+
hidden: internalTarget.hidden,
|
|
1680
|
+
tags: internalTarget.tags,
|
|
1681
|
+
title: internalTarget.title,
|
|
1682
|
+
description: internalTarget.description
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
if (fields.external) {
|
|
1686
|
+
return {
|
|
1687
|
+
...baseProps,
|
|
1688
|
+
type: "External link",
|
|
1689
|
+
href: fields.external
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
if (fields.downloadAsset) {
|
|
1693
|
+
const asset = lookupAsset(context, fields.downloadAsset);
|
|
1694
|
+
let href = null;
|
|
1695
|
+
if (asset?.image?.type === "Picture") {
|
|
1696
|
+
href = asset.image.src;
|
|
1697
|
+
} else if (asset?.image?.type === "Svg image") {
|
|
1698
|
+
href = asset.image.svgSrc;
|
|
1699
|
+
} else if (asset?.video) {
|
|
1700
|
+
if (asset.video.type === "Local video") {
|
|
1701
|
+
href = asset.video.preview.videoUrl;
|
|
1702
|
+
} else if (asset.video.type === "Full video") {
|
|
1703
|
+
href = asset.video.full.videoUrl;
|
|
1704
|
+
} else if (asset.video.type === "External video") {
|
|
1705
|
+
href = asset.video.external;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
return {
|
|
1709
|
+
...baseProps,
|
|
1710
|
+
type: "Download link",
|
|
1711
|
+
href,
|
|
1712
|
+
visual: asset
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
return {
|
|
1716
|
+
...baseProps,
|
|
1717
|
+
type: "Blank link",
|
|
1718
|
+
href: null
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// src/converters/page.ts
|
|
1723
|
+
function basePageConverter(context, entry) {
|
|
1724
|
+
const {
|
|
1725
|
+
sys: { id },
|
|
1726
|
+
fields
|
|
1727
|
+
} = entry;
|
|
1728
|
+
const {
|
|
1729
|
+
slug,
|
|
1730
|
+
title,
|
|
1731
|
+
description,
|
|
1732
|
+
featuredImage,
|
|
1733
|
+
tags,
|
|
1734
|
+
content,
|
|
1735
|
+
menu: pageMenu,
|
|
1736
|
+
footer: pageFooter,
|
|
1737
|
+
template: templateLink,
|
|
1738
|
+
topContent: topContentLinks,
|
|
1739
|
+
bottomContent: bottomContentLinks,
|
|
1740
|
+
...simpleFields
|
|
1741
|
+
} = fields;
|
|
1742
|
+
const pageMenuNav = pageMenu ? resolveNavigation(context, pageMenu) : void 0;
|
|
1743
|
+
const pageFooterNav = pageFooter ? resolveNavigation(context, pageFooter) : void 0;
|
|
1744
|
+
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
1745
|
+
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1746
|
+
const pageContent = content?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1747
|
+
const bottomContent = bottomContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1748
|
+
const preContent = template?.preContent ?? [];
|
|
1749
|
+
const postContent = template?.postContent ?? [];
|
|
1750
|
+
const contents = addPositionMetadata([
|
|
1751
|
+
...topContent,
|
|
1752
|
+
...preContent,
|
|
1753
|
+
...pageContent,
|
|
1754
|
+
...postContent,
|
|
1755
|
+
...bottomContent
|
|
1756
|
+
]);
|
|
1757
|
+
const page = {
|
|
1758
|
+
type: "Page",
|
|
1759
|
+
id,
|
|
1760
|
+
isHomePage: slug === "index",
|
|
1761
|
+
slug,
|
|
1762
|
+
title: makeContentfulTitle(title, id),
|
|
1763
|
+
description: makeContentfulDescription(description, id),
|
|
1764
|
+
featuredImage: lookupAsset(context, featuredImage),
|
|
1765
|
+
tags: tags?.map((tag) => resolveLink(context, id, tag)),
|
|
1766
|
+
contents,
|
|
1767
|
+
...simpleFields,
|
|
1768
|
+
menu: pageMenuNav ?? template?.menu,
|
|
1769
|
+
footer: pageFooterNav ?? template?.footer
|
|
1770
|
+
};
|
|
1771
|
+
return page;
|
|
1772
|
+
}
|
|
1773
|
+
function calculatePageHref(slug) {
|
|
1774
|
+
if (slug === "index") {
|
|
1775
|
+
return "/";
|
|
1776
|
+
}
|
|
1777
|
+
return `/${slug}/`;
|
|
1778
|
+
}
|
|
1779
|
+
function basePageLinkConverter(context, entry) {
|
|
1780
|
+
const {
|
|
1781
|
+
sys: { id, contentType },
|
|
1782
|
+
fields
|
|
1783
|
+
} = entry;
|
|
1784
|
+
if (contentType.sys.id !== "page") {
|
|
1785
|
+
throw new Error(`Invalid content type: expected "page", got "${contentType.sys.id}"`);
|
|
1586
1786
|
}
|
|
1587
1787
|
return createInternalLink(
|
|
1588
|
-
|
|
1788
|
+
id,
|
|
1589
1789
|
{
|
|
1590
1790
|
cmsLabel: fields.cmsLabel,
|
|
1591
|
-
title: fields.
|
|
1791
|
+
title: fields.title,
|
|
1592
1792
|
featuredImage: fields.featuredImage,
|
|
1593
1793
|
backgroundColour: fields.backgroundColour,
|
|
1594
1794
|
textColour: fields.textColour,
|
|
@@ -1597,401 +1797,174 @@ function baseTagLinkConverter(context, entry) {
|
|
|
1597
1797
|
slug: fields.slug
|
|
1598
1798
|
},
|
|
1599
1799
|
context,
|
|
1600
|
-
|
|
1601
|
-
"
|
|
1800
|
+
calculatePageHref(fields.slug),
|
|
1801
|
+
"Page",
|
|
1802
|
+
{ tags: fields.tags?.map((tag) => resolveLink(context, id, tag)) }
|
|
1602
1803
|
);
|
|
1603
1804
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
init_utils();
|
|
1607
|
-
function convertAllAssets(response, context) {
|
|
1608
|
-
const visuals = /* @__PURE__ */ new Map();
|
|
1609
|
-
const assets = response.includes?.Asset;
|
|
1610
|
-
if (assets && assets.length > 0) {
|
|
1611
|
-
for (const asset of assets) {
|
|
1612
|
-
const visual = convertAssetToVisual(context, asset);
|
|
1613
|
-
if (visual) {
|
|
1614
|
-
visuals.set(visual.id, visual);
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
return visuals;
|
|
1619
|
-
}
|
|
1620
|
-
function convertAllIncludes(response) {
|
|
1621
|
-
const includes = /* @__PURE__ */ new Map();
|
|
1622
|
-
const entries = [...response.items, ...response.includes?.Entry || []];
|
|
1623
|
-
if (entries && entries.length > 0) {
|
|
1624
|
-
for (const entry of entries) {
|
|
1625
|
-
if (entry?.sys && entry.fields) {
|
|
1626
|
-
includes.set(entry.sys.id, {
|
|
1627
|
-
id: entry.sys.id,
|
|
1628
|
-
type: entry.sys.contentType.sys.id,
|
|
1629
|
-
entry
|
|
1630
|
-
});
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
return includes;
|
|
1805
|
+
function calculatePageVariantHref(slug) {
|
|
1806
|
+
return `/${slug}/`;
|
|
1635
1807
|
}
|
|
1636
|
-
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
tags: cacheTags
|
|
1644
|
-
}
|
|
1645
|
-
};
|
|
1646
|
-
const fetchFn = async () => {
|
|
1647
|
-
const response = await client.getEntries(
|
|
1648
|
-
{
|
|
1649
|
-
content_type: "page",
|
|
1650
|
-
"fields.slug": slug,
|
|
1651
|
-
include: 10,
|
|
1652
|
-
locale: options?.locale,
|
|
1653
|
-
limit: 1
|
|
1654
|
-
},
|
|
1655
|
-
requestOptions
|
|
1656
|
-
);
|
|
1657
|
-
const pageEntry = response.items[0];
|
|
1658
|
-
if (!pageEntry || !pageEntry.fields) {
|
|
1659
|
-
return { data: null, errors: [] };
|
|
1660
|
-
}
|
|
1661
|
-
try {
|
|
1662
|
-
const assets = convertAllAssets(response, context);
|
|
1663
|
-
const includes = convertAllIncludes(response);
|
|
1664
|
-
const fullContext = {
|
|
1665
|
-
...context,
|
|
1666
|
-
includes,
|
|
1667
|
-
assets,
|
|
1668
|
-
errors: []
|
|
1669
|
-
};
|
|
1670
|
-
const converted = fullContext.pageResolver(fullContext, pageEntry);
|
|
1671
|
-
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
1672
|
-
console.error("CMS conversion errors for page:", {
|
|
1673
|
-
pageId: pageEntry.sys.id,
|
|
1674
|
-
slug,
|
|
1675
|
-
errors: fullContext.errors
|
|
1676
|
-
});
|
|
1677
|
-
}
|
|
1678
|
-
return { data: converted, errors: fullContext.errors };
|
|
1679
|
-
} catch (error) {
|
|
1680
|
-
const entryId = pageEntry.sys.id;
|
|
1681
|
-
const entryType = pageEntry.sys.contentType?.sys?.id;
|
|
1682
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1683
|
-
const cmsError = {
|
|
1684
|
-
entryId,
|
|
1685
|
-
entryType,
|
|
1686
|
-
message: errorMessage,
|
|
1687
|
-
error
|
|
1688
|
-
};
|
|
1689
|
-
return { data: null, errors: [cmsError] };
|
|
1690
|
-
}
|
|
1691
|
-
};
|
|
1692
|
-
if (options?.retry) {
|
|
1693
|
-
return await withRetry(fetchFn, options.retry);
|
|
1808
|
+
function basePageVariantLinkConverter(context, entry) {
|
|
1809
|
+
const {
|
|
1810
|
+
sys: { id, contentType },
|
|
1811
|
+
fields
|
|
1812
|
+
} = entry;
|
|
1813
|
+
if (contentType.sys.id !== "pageVariant") {
|
|
1814
|
+
throw new Error(`Invalid content type: expected "pageVariant", got "${contentType.sys.id}"`);
|
|
1694
1815
|
}
|
|
1695
|
-
return
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
baseComponentConverter
|
|
1816
|
+
return createInternalLink(
|
|
1817
|
+
id,
|
|
1818
|
+
{
|
|
1819
|
+
cmsLabel: fields.cmsLabel,
|
|
1820
|
+
title: fields.title,
|
|
1821
|
+
featuredImage: fields.featuredImage,
|
|
1822
|
+
backgroundColour: fields.backgroundColour,
|
|
1823
|
+
textColour: fields.textColour,
|
|
1824
|
+
indexed: fields.indexed,
|
|
1825
|
+
hidden: fields.hidden,
|
|
1826
|
+
slug: fields.slug
|
|
1827
|
+
},
|
|
1828
|
+
context,
|
|
1829
|
+
calculatePageVariantHref(fields.slug),
|
|
1830
|
+
"Page",
|
|
1831
|
+
{ tags: fields.tags?.map((tag) => resolveLink(context, id, tag)) }
|
|
1712
1832
|
);
|
|
1713
|
-
return {
|
|
1714
|
-
pageResolver: basePageConverter,
|
|
1715
|
-
navigationItemResolver: baseNavigationItemConverter,
|
|
1716
|
-
articleResolver: baseArticleConverter,
|
|
1717
|
-
articleTypeResolver: baseArticleTypeConverter,
|
|
1718
|
-
componentResolver: baseComponentConverter,
|
|
1719
|
-
collectionResolver: baseCollectionConverter,
|
|
1720
|
-
linkResolver,
|
|
1721
|
-
contentResolver,
|
|
1722
|
-
videoPrefix: ""
|
|
1723
|
-
};
|
|
1724
1833
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
...options,
|
|
1730
|
-
next: {
|
|
1731
|
-
...options?.next,
|
|
1732
|
-
tags: cacheTags
|
|
1733
|
-
}
|
|
1734
|
-
};
|
|
1735
|
-
const fetchFn = async () => {
|
|
1736
|
-
const response = await client.getEntries(
|
|
1737
|
-
{
|
|
1738
|
-
content_type: "article",
|
|
1739
|
-
"fields.slug": slug,
|
|
1740
|
-
"fields.articleType.sys.contentType.sys.id": "articleType",
|
|
1741
|
-
"fields.articleType.fields.slug": articleTypeSlug,
|
|
1742
|
-
include: 10,
|
|
1743
|
-
locale: options?.locale,
|
|
1744
|
-
limit: 1
|
|
1745
|
-
},
|
|
1746
|
-
requestOptions
|
|
1747
|
-
);
|
|
1748
|
-
const articleEntry = response.items[0];
|
|
1749
|
-
if (!articleEntry || !articleEntry.fields) {
|
|
1750
|
-
return { data: null, errors: [] };
|
|
1751
|
-
}
|
|
1752
|
-
const assets = convertAllAssets(response, context);
|
|
1753
|
-
const includes = convertAllIncludes(response);
|
|
1754
|
-
const fullContext = {
|
|
1755
|
-
...context,
|
|
1756
|
-
includes,
|
|
1757
|
-
assets,
|
|
1758
|
-
errors: []
|
|
1759
|
-
};
|
|
1760
|
-
try {
|
|
1761
|
-
const converted = fullContext.articleResolver(fullContext, articleEntry);
|
|
1762
|
-
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
1763
|
-
console.error("CMS conversion errors for article:", {
|
|
1764
|
-
articleId: articleEntry.sys.id,
|
|
1765
|
-
slug,
|
|
1766
|
-
articleTypeSlug,
|
|
1767
|
-
errors: fullContext.errors
|
|
1768
|
-
});
|
|
1769
|
-
}
|
|
1770
|
-
return { data: converted, errors: fullContext.errors };
|
|
1771
|
-
} catch (error) {
|
|
1772
|
-
const entryId = articleEntry.sys.id;
|
|
1773
|
-
const entryType = articleEntry.sys.contentType?.sys?.id;
|
|
1774
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1775
|
-
const cmsError = {
|
|
1776
|
-
entryId,
|
|
1777
|
-
entryType,
|
|
1778
|
-
message: errorMessage,
|
|
1779
|
-
error
|
|
1780
|
-
};
|
|
1781
|
-
return { data: null, errors: [cmsError] };
|
|
1782
|
-
}
|
|
1783
|
-
};
|
|
1784
|
-
if (options?.retry) {
|
|
1785
|
-
return await withRetry(fetchFn, options.retry);
|
|
1786
|
-
}
|
|
1787
|
-
return await fetchFn();
|
|
1834
|
+
|
|
1835
|
+
// src/converters/person.ts
|
|
1836
|
+
function calculatePersonHref(slug) {
|
|
1837
|
+
return `/people/${slug}/`;
|
|
1788
1838
|
}
|
|
1789
|
-
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
}
|
|
1814
|
-
const assets = convertAllAssets(response, context);
|
|
1815
|
-
const includes = convertAllIncludes(response);
|
|
1816
|
-
const fullContext = {
|
|
1817
|
-
...context,
|
|
1818
|
-
includes,
|
|
1819
|
-
assets,
|
|
1820
|
-
errors: []
|
|
1821
|
-
};
|
|
1822
|
-
try {
|
|
1823
|
-
const converted = fullContext.articleTypeResolver(fullContext, articleTypeEntry);
|
|
1824
|
-
if (fullContext.errors.length > 0 && typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
1825
|
-
console.error("CMS conversion errors for article type:", {
|
|
1826
|
-
articleTypeId: articleTypeEntry.sys.id,
|
|
1827
|
-
slug,
|
|
1828
|
-
errors: fullContext.errors
|
|
1829
|
-
});
|
|
1830
|
-
}
|
|
1831
|
-
return { data: converted, errors: fullContext.errors };
|
|
1832
|
-
} catch (error) {
|
|
1833
|
-
const entryId = articleTypeEntry.sys.id;
|
|
1834
|
-
const entryType = articleTypeEntry.sys.contentType?.sys?.id;
|
|
1835
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1836
|
-
const cmsError = {
|
|
1837
|
-
entryId,
|
|
1838
|
-
entryType,
|
|
1839
|
-
message: errorMessage,
|
|
1840
|
-
error
|
|
1841
|
-
};
|
|
1842
|
-
return { data: null, errors: [cmsError] };
|
|
1843
|
-
}
|
|
1844
|
-
};
|
|
1845
|
-
if (options?.retry) {
|
|
1846
|
-
return await withRetry(fetchFn, options.retry);
|
|
1839
|
+
function basePersonLinkConverter(context, entry) {
|
|
1840
|
+
const { sys, fields } = entry;
|
|
1841
|
+
if (sys.contentType.sys.id !== "person") {
|
|
1842
|
+
throw new Error(`Invalid content type: expected "person", got "${sys.contentType.sys.id}"`);
|
|
1843
|
+
}
|
|
1844
|
+
return createInternalLink(
|
|
1845
|
+
sys.id,
|
|
1846
|
+
{
|
|
1847
|
+
...fields
|
|
1848
|
+
},
|
|
1849
|
+
context,
|
|
1850
|
+
calculatePersonHref(fields.slug),
|
|
1851
|
+
"Person"
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
// src/converters/tag.ts
|
|
1856
|
+
function calculateTagHref(slug) {
|
|
1857
|
+
return `/tag/${slug}/`;
|
|
1858
|
+
}
|
|
1859
|
+
function baseTagLinkConverter(context, entry) {
|
|
1860
|
+
const { sys, fields } = entry;
|
|
1861
|
+
if (sys.contentType.sys.id !== "tag") {
|
|
1862
|
+
throw new Error(`Invalid content type: expected "tag", got "${sys.contentType.sys.id}"`);
|
|
1847
1863
|
}
|
|
1848
|
-
return
|
|
1864
|
+
return createInternalLink(
|
|
1865
|
+
sys.id,
|
|
1866
|
+
{
|
|
1867
|
+
...fields
|
|
1868
|
+
},
|
|
1869
|
+
context,
|
|
1870
|
+
calculateTagHref(fields.slug),
|
|
1871
|
+
"Tag"
|
|
1872
|
+
);
|
|
1849
1873
|
}
|
|
1850
|
-
function
|
|
1851
|
-
const
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1874
|
+
function baseTagConverter(context, entry) {
|
|
1875
|
+
const { sys, fields } = entry;
|
|
1876
|
+
const { id } = sys;
|
|
1877
|
+
const {
|
|
1878
|
+
name,
|
|
1879
|
+
slug,
|
|
1880
|
+
description,
|
|
1881
|
+
featuredImage,
|
|
1882
|
+
tagType,
|
|
1883
|
+
menu: menuLink,
|
|
1884
|
+
footer: footerLink,
|
|
1885
|
+
template: templateLink,
|
|
1886
|
+
topContent: topContentLinks,
|
|
1887
|
+
...rest
|
|
1888
|
+
} = fields;
|
|
1889
|
+
const template = templateLink ? resolveTemplate(context, templateLink) : null;
|
|
1890
|
+
const menu = menuLink ? resolveNavigation(context, menuLink) : template?.menu;
|
|
1891
|
+
const footer = footerLink ? resolveNavigation(context, footerLink) : template?.footer;
|
|
1892
|
+
const topContent = topContentLinks?.map((c) => resolvePageContent(context, id, c)).filter((item) => item !== null) ?? [];
|
|
1893
|
+
const preContent = template?.preContent ?? [];
|
|
1894
|
+
const postContent = template?.postContent ?? [];
|
|
1895
|
+
const contents = addPositionMetadata([...topContent, ...preContent, ...postContent]);
|
|
1896
|
+
const tagTypeEntry = tagType ? context.includes.get(tagType.sys.id) : null;
|
|
1897
|
+
const tagTypeName = tagTypeEntry?.entry?.fields?.name;
|
|
1898
|
+
const tag = {
|
|
1899
|
+
type: "Tag",
|
|
1900
|
+
id,
|
|
1901
|
+
slug,
|
|
1902
|
+
title: makeContentfulTitle(name, sys.id),
|
|
1903
|
+
description: makeContentfulDescription(description, sys.id),
|
|
1904
|
+
featuredImage: lookupAsset(context, featuredImage),
|
|
1905
|
+
tagType: tagTypeName ?? null,
|
|
1906
|
+
contents,
|
|
1907
|
+
...rest,
|
|
1908
|
+
menu,
|
|
1909
|
+
footer
|
|
1857
1910
|
};
|
|
1911
|
+
return tag;
|
|
1858
1912
|
}
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
const
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
break;
|
|
1893
|
-
}
|
|
1894
|
-
const assets = convertAllAssets(response, context);
|
|
1895
|
-
const includes = convertAllIncludes(response);
|
|
1896
|
-
const fullContext = {
|
|
1897
|
-
...context,
|
|
1898
|
-
includes,
|
|
1899
|
-
assets,
|
|
1900
|
-
errors: []
|
|
1901
|
-
};
|
|
1902
|
-
for (const entry of response.items) {
|
|
1903
|
-
if (!entry.fields) continue;
|
|
1904
|
-
try {
|
|
1905
|
-
const converted = baseArticleLinkConverterWithMetadata(fullContext, entry);
|
|
1906
|
-
allArticles.push(converted);
|
|
1907
|
-
} catch (error) {
|
|
1908
|
-
const entryId = entry.sys.id;
|
|
1909
|
-
const entryType = entry.sys.contentType?.sys?.id;
|
|
1910
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1911
|
-
errors.push({
|
|
1912
|
-
entryId,
|
|
1913
|
-
entryType,
|
|
1914
|
-
message: errorMessage,
|
|
1915
|
-
error
|
|
1916
|
-
});
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
skip += pageSize;
|
|
1920
|
-
if (skip >= response.total) {
|
|
1921
|
-
hasMore = false;
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
return { data: allArticles, errors };
|
|
1913
|
+
|
|
1914
|
+
// src/api/context.ts
|
|
1915
|
+
function createBaseConverterContext() {
|
|
1916
|
+
const linkResolver = /* @__PURE__ */ new Map();
|
|
1917
|
+
linkResolver.set("page", basePageLinkConverter);
|
|
1918
|
+
linkResolver.set("article", baseArticleLinkConverter);
|
|
1919
|
+
linkResolver.set(
|
|
1920
|
+
"articleType",
|
|
1921
|
+
baseArticleTypeLinkConverter
|
|
1922
|
+
);
|
|
1923
|
+
linkResolver.set("tag", baseTagLinkConverter);
|
|
1924
|
+
linkResolver.set("person", basePersonLinkConverter);
|
|
1925
|
+
linkResolver.set("pageVariant", basePageVariantLinkConverter);
|
|
1926
|
+
linkResolver.set("link", baseLinkConverter);
|
|
1927
|
+
const contentResolver = /* @__PURE__ */ new Map();
|
|
1928
|
+
contentResolver.set("collection", baseCollectionConverter);
|
|
1929
|
+
contentResolver.set("component", baseComponentConverter);
|
|
1930
|
+
contentResolver.set(
|
|
1931
|
+
"externalComponent",
|
|
1932
|
+
baseComponentConverter
|
|
1933
|
+
);
|
|
1934
|
+
return {
|
|
1935
|
+
pageResolver: basePageConverter,
|
|
1936
|
+
navigationItemResolver: baseNavigationItemConverter,
|
|
1937
|
+
articleResolver: baseArticleConverter,
|
|
1938
|
+
articleTypeResolver: baseArticleTypeConverter,
|
|
1939
|
+
tagResolver: baseTagConverter,
|
|
1940
|
+
customTypeResolver: baseCustomTypeConverter,
|
|
1941
|
+
componentResolver: baseComponentConverter,
|
|
1942
|
+
collectionResolver: baseCollectionConverter,
|
|
1943
|
+
linkResolver,
|
|
1944
|
+
contentResolver,
|
|
1945
|
+
videoPrefix: ""
|
|
1925
1946
|
};
|
|
1926
|
-
if (options?.retry) {
|
|
1927
|
-
return await withRetry(fetchFn, options.retry);
|
|
1928
|
-
}
|
|
1929
|
-
return await fetchFn();
|
|
1930
1947
|
}
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
},
|
|
1948
|
-
requestOptions
|
|
1949
|
-
);
|
|
1950
|
-
if (response.items.length === 0) {
|
|
1951
|
-
hasMore = false;
|
|
1952
|
-
break;
|
|
1953
|
-
}
|
|
1954
|
-
const includes = convertAllIncludes(response);
|
|
1955
|
-
const assets = convertAllAssets(response, context);
|
|
1956
|
-
const fullContext = {
|
|
1957
|
-
...context,
|
|
1958
|
-
includes,
|
|
1959
|
-
assets,
|
|
1960
|
-
errors: []
|
|
1961
|
-
};
|
|
1962
|
-
for (const entry of response.items) {
|
|
1963
|
-
if (!entry.fields) continue;
|
|
1964
|
-
try {
|
|
1965
|
-
const converted = converter(
|
|
1966
|
-
fullContext,
|
|
1967
|
-
entry
|
|
1968
|
-
);
|
|
1969
|
-
allLinks.push(converted);
|
|
1970
|
-
} catch (error) {
|
|
1971
|
-
const entryId = entry.sys.id;
|
|
1972
|
-
const entryType = entry.sys.contentType?.sys?.id;
|
|
1973
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown conversion error";
|
|
1974
|
-
errors.push({
|
|
1975
|
-
entryId,
|
|
1976
|
-
entryType,
|
|
1977
|
-
message: errorMessage,
|
|
1978
|
-
error
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
}
|
|
1982
|
-
skip += pageSize;
|
|
1983
|
-
if (skip >= response.total) {
|
|
1984
|
-
hasMore = false;
|
|
1985
|
-
}
|
|
1986
|
-
} catch (error) {
|
|
1987
|
-
console.error("Error fetching links", typeof error, error, JSON.stringify(error, null, 2));
|
|
1988
|
-
throw error;
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
return { data: allLinks, errors };
|
|
1992
|
-
};
|
|
1993
|
-
return await fetchFn();
|
|
1948
|
+
|
|
1949
|
+
// src/api/custom-type.ts
|
|
1950
|
+
async function contentfulCustomTypeRest(context, config, indexPageSlug, options) {
|
|
1951
|
+
return fetchSingleEntity(
|
|
1952
|
+
context,
|
|
1953
|
+
config,
|
|
1954
|
+
{
|
|
1955
|
+
contentType: "customType",
|
|
1956
|
+
cacheTagType: "customType",
|
|
1957
|
+
cacheTagIdentifier: indexPageSlug,
|
|
1958
|
+
query: { "fields.indexPageSlug": indexPageSlug },
|
|
1959
|
+
resolver: (ctx, entry) => ctx.customTypeResolver(ctx, entry),
|
|
1960
|
+
errorLogContext: { indexPageSlug }
|
|
1961
|
+
},
|
|
1962
|
+
options
|
|
1963
|
+
);
|
|
1994
1964
|
}
|
|
1965
|
+
|
|
1966
|
+
// src/api/links.ts
|
|
1967
|
+
init_utils();
|
|
1995
1968
|
async function contentfulAllPageLinks(context, config, options) {
|
|
1996
1969
|
const client = getContentfulClient(config, options?.preview);
|
|
1997
1970
|
const cacheTags = getCacheTags("page", void 0, options?.preview);
|
|
@@ -2002,7 +1975,15 @@ async function contentfulAllPageLinks(context, config, options) {
|
|
|
2002
1975
|
tags: cacheTags
|
|
2003
1976
|
}
|
|
2004
1977
|
};
|
|
2005
|
-
const fetchFn = () => fetchAllLinks(
|
|
1978
|
+
const fetchFn = () => fetchAllLinks(
|
|
1979
|
+
"page",
|
|
1980
|
+
client,
|
|
1981
|
+
requestOptions,
|
|
1982
|
+
basePageLinkConverter,
|
|
1983
|
+
context,
|
|
1984
|
+
100,
|
|
1985
|
+
PAGE_LINK_FIELDS
|
|
1986
|
+
);
|
|
2006
1987
|
if (options?.retry) {
|
|
2007
1988
|
return await withRetry(fetchFn, options.retry);
|
|
2008
1989
|
}
|
|
@@ -2018,7 +1999,15 @@ async function contentfulAllArticleLinks(context, config, options) {
|
|
|
2018
1999
|
tags: cacheTags
|
|
2019
2000
|
}
|
|
2020
2001
|
};
|
|
2021
|
-
const fetchFn = () => fetchAllLinks(
|
|
2002
|
+
const fetchFn = () => fetchAllLinks(
|
|
2003
|
+
"article",
|
|
2004
|
+
client,
|
|
2005
|
+
requestOptions,
|
|
2006
|
+
baseArticleLinkConverter,
|
|
2007
|
+
context,
|
|
2008
|
+
100,
|
|
2009
|
+
ARTICLE_LINK_FIELDS
|
|
2010
|
+
);
|
|
2022
2011
|
if (options?.retry) {
|
|
2023
2012
|
return await withRetry(fetchFn, options.retry);
|
|
2024
2013
|
}
|
|
@@ -2034,7 +2023,15 @@ async function contentfulAllTagLinks(context, config, options) {
|
|
|
2034
2023
|
tags: cacheTags
|
|
2035
2024
|
}
|
|
2036
2025
|
};
|
|
2037
|
-
const fetchFn = () => fetchAllLinks(
|
|
2026
|
+
const fetchFn = () => fetchAllLinks(
|
|
2027
|
+
"tag",
|
|
2028
|
+
client,
|
|
2029
|
+
requestOptions,
|
|
2030
|
+
baseTagLinkConverter,
|
|
2031
|
+
context,
|
|
2032
|
+
100,
|
|
2033
|
+
TAG_LINK_FIELDS
|
|
2034
|
+
);
|
|
2038
2035
|
if (options?.retry) {
|
|
2039
2036
|
return await withRetry(fetchFn, options.retry);
|
|
2040
2037
|
}
|
|
@@ -2050,7 +2047,15 @@ async function contentfulAllPersonLinks(context, config, options) {
|
|
|
2050
2047
|
tags: cacheTags
|
|
2051
2048
|
}
|
|
2052
2049
|
};
|
|
2053
|
-
const fetchFn = () => fetchAllLinks(
|
|
2050
|
+
const fetchFn = () => fetchAllLinks(
|
|
2051
|
+
"person",
|
|
2052
|
+
client,
|
|
2053
|
+
requestOptions,
|
|
2054
|
+
basePersonLinkConverter,
|
|
2055
|
+
context,
|
|
2056
|
+
100,
|
|
2057
|
+
PERSON_LINK_FIELDS
|
|
2058
|
+
);
|
|
2054
2059
|
if (options?.retry) {
|
|
2055
2060
|
return await withRetry(fetchFn, options.retry);
|
|
2056
2061
|
}
|
|
@@ -2066,40 +2071,81 @@ async function contentfulAllArticleTypeLinks(context, config, options) {
|
|
|
2066
2071
|
tags: cacheTags
|
|
2067
2072
|
}
|
|
2068
2073
|
};
|
|
2069
|
-
const fetchFn = () => fetchAllLinks(
|
|
2074
|
+
const fetchFn = () => fetchAllLinks(
|
|
2075
|
+
"articleType",
|
|
2076
|
+
client,
|
|
2077
|
+
requestOptions,
|
|
2078
|
+
baseArticleTypeLinkConverter,
|
|
2079
|
+
context,
|
|
2080
|
+
100,
|
|
2081
|
+
ARTICLE_TYPE_LINK_FIELDS
|
|
2082
|
+
);
|
|
2070
2083
|
if (options?.retry) {
|
|
2071
2084
|
return await withRetry(fetchFn, options.retry);
|
|
2072
2085
|
}
|
|
2073
2086
|
return await fetchFn();
|
|
2074
2087
|
}
|
|
2088
|
+
|
|
2089
|
+
// src/api/page.ts
|
|
2090
|
+
async function contentfulPageRest(context, config, slug, options) {
|
|
2091
|
+
return fetchSingleEntity(
|
|
2092
|
+
context,
|
|
2093
|
+
config,
|
|
2094
|
+
{
|
|
2095
|
+
contentType: "page",
|
|
2096
|
+
cacheTagType: "page",
|
|
2097
|
+
cacheTagIdentifier: slug,
|
|
2098
|
+
query: { "fields.slug": slug },
|
|
2099
|
+
resolver: (ctx, entry) => ctx.pageResolver(ctx, entry),
|
|
2100
|
+
errorLogContext: { slug }
|
|
2101
|
+
},
|
|
2102
|
+
options
|
|
2103
|
+
);
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
// src/api/related-articles.ts
|
|
2075
2107
|
function filterRelatedArticles(articles, options) {
|
|
2076
|
-
const {
|
|
2108
|
+
const {
|
|
2109
|
+
excludeArticleIds,
|
|
2110
|
+
articleTypeIds: rawArticleTypeIds,
|
|
2111
|
+
tagIds: rawTagIds,
|
|
2112
|
+
authorIds: rawAuthorIds,
|
|
2113
|
+
before,
|
|
2114
|
+
after,
|
|
2115
|
+
count
|
|
2116
|
+
} = options;
|
|
2117
|
+
const excludeIds = excludeArticleIds ? [...new Set(excludeArticleIds)] : [];
|
|
2118
|
+
const articleTypeIds = rawArticleTypeIds ? [...new Set(rawArticleTypeIds)] : [];
|
|
2119
|
+
const tagIds = rawTagIds ? [...new Set(rawTagIds)] : [];
|
|
2120
|
+
const authorIds = rawAuthorIds ? [...new Set(rawAuthorIds)] : [];
|
|
2077
2121
|
const scoredArticles = articles.map((article) => {
|
|
2078
2122
|
let score = 0;
|
|
2079
|
-
if (excludeIds
|
|
2123
|
+
if (excludeIds.length > 0 && excludeIds.includes(article.id)) {
|
|
2080
2124
|
return null;
|
|
2081
2125
|
}
|
|
2082
|
-
if (
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
return null;
|
|
2126
|
+
if (articleTypeIds.length > 0) {
|
|
2127
|
+
if (!article.articleType?.id || !articleTypeIds.includes(article.articleType.id)) {
|
|
2128
|
+
return null;
|
|
2129
|
+
}
|
|
2087
2130
|
}
|
|
2088
2131
|
if (article.date) {
|
|
2089
|
-
|
|
2132
|
+
const articleDate = new Date(article.date);
|
|
2133
|
+
if (before && articleDate > before) {
|
|
2090
2134
|
return null;
|
|
2091
2135
|
}
|
|
2092
|
-
if (after &&
|
|
2136
|
+
if (after && articleDate < after) {
|
|
2093
2137
|
return null;
|
|
2094
2138
|
}
|
|
2095
2139
|
}
|
|
2096
|
-
if (tagIds
|
|
2140
|
+
if (tagIds.length > 0 && article.tags) {
|
|
2097
2141
|
const articleTagIds = article.tags.map((tag) => tag.id);
|
|
2098
2142
|
const matchingTags = tagIds.filter((tagId) => articleTagIds.includes(tagId));
|
|
2099
2143
|
score += matchingTags.length * 10;
|
|
2100
2144
|
}
|
|
2101
|
-
if (
|
|
2102
|
-
|
|
2145
|
+
if (authorIds.length > 0 && article.author?.id) {
|
|
2146
|
+
if (authorIds.includes(article.author.id)) {
|
|
2147
|
+
score += 5;
|
|
2148
|
+
}
|
|
2103
2149
|
}
|
|
2104
2150
|
return { article, score };
|
|
2105
2151
|
}).filter((item) => item !== null);
|
|
@@ -2108,15 +2154,128 @@ function filterRelatedArticles(articles, options) {
|
|
|
2108
2154
|
return b.score - a.score;
|
|
2109
2155
|
}
|
|
2110
2156
|
if (a.article.date && b.article.date) {
|
|
2111
|
-
|
|
2157
|
+
const articleDateA = new Date(a.article.date);
|
|
2158
|
+
const articleDateB = new Date(b.article.date);
|
|
2159
|
+
return articleDateB.getTime() - articleDateA.getTime();
|
|
2112
2160
|
}
|
|
2113
2161
|
return 0;
|
|
2114
2162
|
});
|
|
2115
|
-
const topArticles = count ? scoredArticles.slice(0, count) : scoredArticles;
|
|
2116
|
-
return topArticles.map(({ article }) =>
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2163
|
+
const topArticles = count !== void 0 ? scoredArticles.slice(0, count) : scoredArticles;
|
|
2164
|
+
return topArticles.map(({ article }) => article);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
// src/api/sitemap.ts
|
|
2168
|
+
function linksToSitemapEntries(links, sitemapConfig) {
|
|
2169
|
+
return links.filter((link) => link.indexed !== false && link.hidden !== true && link.href).map((link) => ({
|
|
2170
|
+
url: link.href,
|
|
2171
|
+
lastModified: link.lastModified,
|
|
2172
|
+
changeFrequency: sitemapConfig?.changeFrequency,
|
|
2173
|
+
priority: sitemapConfig?.priority
|
|
2174
|
+
}));
|
|
2175
|
+
}
|
|
2176
|
+
async function contentfulPageSitemapEntries(context, config, sitemapConfig, options) {
|
|
2177
|
+
const response = await contentfulAllPageLinks(context, config, options);
|
|
2178
|
+
return {
|
|
2179
|
+
data: linksToSitemapEntries(response.data, sitemapConfig),
|
|
2180
|
+
errors: response.errors
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
async function contentfulArticleSitemapEntries(context, config, sitemapConfig, options) {
|
|
2184
|
+
const response = await contentfulAllArticleLinks(context, config, options);
|
|
2185
|
+
return {
|
|
2186
|
+
data: linksToSitemapEntries(response.data, sitemapConfig),
|
|
2187
|
+
errors: response.errors
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
async function contentfulArticleTypeSitemapEntries(context, config, sitemapConfig, options) {
|
|
2191
|
+
const response = await contentfulAllArticleTypeLinks(context, config, options);
|
|
2192
|
+
return {
|
|
2193
|
+
data: linksToSitemapEntries(response.data, sitemapConfig),
|
|
2194
|
+
errors: response.errors
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
async function contentfulTagSitemapEntries(context, config, sitemapConfig, options) {
|
|
2198
|
+
const response = await contentfulAllTagLinks(context, config, options);
|
|
2199
|
+
return {
|
|
2200
|
+
data: linksToSitemapEntries(response.data, sitemapConfig),
|
|
2201
|
+
errors: response.errors
|
|
2202
|
+
};
|
|
2203
|
+
}
|
|
2204
|
+
async function contentfulPersonSitemapEntries(context, config, sitemapConfig, options) {
|
|
2205
|
+
const response = await contentfulAllPersonLinks(context, config, options);
|
|
2206
|
+
return {
|
|
2207
|
+
data: linksToSitemapEntries(response.data, sitemapConfig),
|
|
2208
|
+
errors: response.errors
|
|
2209
|
+
};
|
|
2210
|
+
}
|
|
2211
|
+
async function getAllSitemapEntries(context, config, sitemapConfig, options) {
|
|
2212
|
+
const allEntries = [];
|
|
2213
|
+
const allErrors = [];
|
|
2214
|
+
const results = await Promise.all(
|
|
2215
|
+
sitemapConfig.providers.map((provider) => provider(context, config, options))
|
|
2216
|
+
);
|
|
2217
|
+
for (const result of results) {
|
|
2218
|
+
allEntries.push(...result.data);
|
|
2219
|
+
allErrors.push(...result.errors);
|
|
2220
|
+
}
|
|
2221
|
+
return { data: allEntries, errors: allErrors };
|
|
2222
|
+
}
|
|
2223
|
+
function createSitemapProvider(fetcher, sitemapConfig) {
|
|
2224
|
+
return (context, config, options) => fetcher(context, config, sitemapConfig, options);
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
// src/api/tag.ts
|
|
2228
|
+
async function contentfulTagRest(context, config, slug, options) {
|
|
2229
|
+
return fetchSingleEntity(
|
|
2230
|
+
context,
|
|
2231
|
+
config,
|
|
2232
|
+
{
|
|
2233
|
+
contentType: "tag",
|
|
2234
|
+
cacheTagType: "tag",
|
|
2235
|
+
cacheTagIdentifier: slug,
|
|
2236
|
+
query: { "fields.slug": slug },
|
|
2237
|
+
resolver: (ctx, entry) => ctx.tagResolver(ctx, entry),
|
|
2238
|
+
errorLogContext: { slug }
|
|
2239
|
+
},
|
|
2240
|
+
options
|
|
2241
|
+
);
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// src/api/template.ts
|
|
2245
|
+
function templateConverter(context, entry) {
|
|
2246
|
+
const { fields, sys } = entry;
|
|
2247
|
+
const id = sys.id;
|
|
2248
|
+
const preContent = fields.preContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
|
|
2249
|
+
const postContent = fields.postContent?.map((content) => resolvePageContent(context, id, content)).filter((item) => item !== null) ?? [];
|
|
2250
|
+
const menu = fields.menu ? resolveNavigation(context, fields.menu) : void 0;
|
|
2251
|
+
const footer = fields.footer ? resolveNavigation(context, fields.footer) : void 0;
|
|
2252
|
+
const stickyNav = fields.flags?.includes("Sticky nav") ?? false;
|
|
2253
|
+
return {
|
|
2254
|
+
id,
|
|
2255
|
+
cmsLabel: fields.cmsLabel,
|
|
2256
|
+
preContent,
|
|
2257
|
+
postContent,
|
|
2258
|
+
menu,
|
|
2259
|
+
footer,
|
|
2260
|
+
backgroundColour: fields.backgroundColour,
|
|
2261
|
+
textColour: fields.textColour,
|
|
2262
|
+
stickyNav
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
async function contentfulTemplateRest(context, config, cmsLabel, options) {
|
|
2266
|
+
return fetchSingleEntity(
|
|
2267
|
+
context,
|
|
2268
|
+
config,
|
|
2269
|
+
{
|
|
2270
|
+
contentType: "template",
|
|
2271
|
+
cacheTagType: "template",
|
|
2272
|
+
cacheTagIdentifier: cmsLabel,
|
|
2273
|
+
query: { "fields.cmsLabel": cmsLabel },
|
|
2274
|
+
resolver: (ctx, entry) => templateConverter(ctx, entry),
|
|
2275
|
+
errorLogContext: { cmsLabel }
|
|
2276
|
+
},
|
|
2277
|
+
options
|
|
2278
|
+
);
|
|
2120
2279
|
}
|
|
2121
2280
|
|
|
2122
2281
|
// src/revalidation/handlers.ts
|
|
@@ -2150,6 +2309,11 @@ var pageVariantHandler = {
|
|
|
2150
2309
|
makeTags: (extracted) => [extracted ? pageTag(extracted) : void 0],
|
|
2151
2310
|
getGlobalTags: () => [PageTag]
|
|
2152
2311
|
};
|
|
2312
|
+
var templateHandler = {
|
|
2313
|
+
extract: (data) => data.fields?.cmsLabel?.[defaultLocale],
|
|
2314
|
+
makeTags: (extracted) => [extracted ? templateTag(extracted) : void 0],
|
|
2315
|
+
getGlobalTags: () => [TemplateTag]
|
|
2316
|
+
};
|
|
2153
2317
|
var contentTypeHandlers = {
|
|
2154
2318
|
page: {
|
|
2155
2319
|
extract: (data) => data.fields?.slug?.[defaultLocale],
|
|
@@ -2171,11 +2335,8 @@ var contentTypeHandlers = {
|
|
|
2171
2335
|
makeTags: (extracted) => [extracted ? tagTag(extracted) : void 0],
|
|
2172
2336
|
getGlobalTags: () => [TagTag]
|
|
2173
2337
|
},
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
makeTags: () => void 0,
|
|
2177
|
-
getGlobalTags: () => ["template"]
|
|
2178
|
-
},
|
|
2338
|
+
// biome-ignore lint/suspicious/noExplicitAny: Any is ok for handlers with different types
|
|
2339
|
+
template: templateHandler,
|
|
2179
2340
|
customType: {
|
|
2180
2341
|
extract: () => void 0,
|
|
2181
2342
|
makeTags: () => void 0,
|
|
@@ -2339,6 +2500,6 @@ function createRevalidationHandler(config = {}) {
|
|
|
2339
2500
|
init_tags();
|
|
2340
2501
|
init_utils();
|
|
2341
2502
|
|
|
2342
|
-
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, contentfulArticleTypeRest, contentfulPageRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createResponsiveVisual, createRevalidationHandler, customTypeTag, filterRelatedArticles,
|
|
2503
|
+
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 };
|
|
2343
2504
|
//# sourceMappingURL=index.js.map
|
|
2344
2505
|
//# sourceMappingURL=index.js.map
|