@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.d.ts +95 -58
- package/dist/index.js +822 -732
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
|
265
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
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
|
-
|
|
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/
|
|
977
|
-
function
|
|
978
|
-
const { sys, fields } = entry;
|
|
979
|
-
const { id } = sys;
|
|
1249
|
+
// src/converters/navigationItem.ts
|
|
1250
|
+
function createLink(context, entry) {
|
|
980
1251
|
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
|
|
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
|
|
1002
|
-
lookupAsset(context,
|
|
1003
|
-
lookupAsset(context,
|
|
1265
|
+
const icon = createResponsiveVisual(
|
|
1266
|
+
lookupAsset(context, navIcon),
|
|
1267
|
+
lookupAsset(context, mobileNavIcon)
|
|
1004
1268
|
);
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
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
|
-
|
|
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/
|
|
1422
|
-
function
|
|
1423
|
-
|
|
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
|
|
1895
|
+
function baseTagLinkConverter(context, entry) {
|
|
1519
1896
|
const { sys, fields } = entry;
|
|
1520
|
-
if (sys.contentType.sys.id !== "
|
|
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
|
-
|
|
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
|
-
|
|
1539
|
-
"
|
|
1906
|
+
calculateTagHref(fields.slug),
|
|
1907
|
+
"Tag"
|
|
1540
1908
|
);
|
|
1541
1909
|
}
|
|
1542
|
-
function
|
|
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
|
-
|
|
1548
|
-
indexPageDescription,
|
|
1916
|
+
description,
|
|
1549
1917
|
featuredImage,
|
|
1918
|
+
tagType,
|
|
1550
1919
|
menu: menuLink,
|
|
1551
1920
|
footer: footerLink,
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
...
|
|
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
|
|
1563
|
-
const
|
|
1564
|
-
|
|
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(
|
|
1568
|
-
description: makeContentfulDescription(
|
|
1938
|
+
title: makeContentfulTitle(name, sys.id),
|
|
1939
|
+
description: makeContentfulDescription(description, sys.id),
|
|
1569
1940
|
featuredImage: lookupAsset(context, featuredImage),
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
{
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
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 {
|
|
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
|
|
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 (
|
|
2135
|
-
|
|
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
|
-
|
|
2168
|
+
const articleDate = new Date(article.date);
|
|
2169
|
+
if (before && articleDate > before) {
|
|
2139
2170
|
return null;
|
|
2140
2171
|
}
|
|
2141
|
-
if (after &&
|
|
2172
|
+
if (after && articleDate < after) {
|
|
2142
2173
|
return null;
|
|
2143
2174
|
}
|
|
2144
2175
|
}
|
|
2145
|
-
if (tagIds
|
|
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 (
|
|
2151
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2282
|
-
|
|
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,
|
|
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
|