@se-studio/contentful-rest-api 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,193 +1,144 @@
1
- import { createClient } from 'contentful';
2
-
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __esm = (fn, res) => function __init() {
6
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
1
+ // src/utils/errors.ts
2
+ var ContentfulError = class _ContentfulError extends Error {
3
+ constructor(message, statusCode, details) {
4
+ super(message);
5
+ this.statusCode = statusCode;
6
+ this.details = details;
7
+ this.name = "ContentfulError";
8
+ Object.setPrototypeOf(this, _ContentfulError.prototype);
9
+ }
7
10
  };
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
+ var RateLimitError = class _RateLimitError extends ContentfulError {
12
+ constructor(message, retryAfter, details) {
13
+ super(message, 429, details);
14
+ this.retryAfter = retryAfter;
15
+ this.name = "RateLimitError";
16
+ Object.setPrototypeOf(this, _RateLimitError.prototype);
17
+ }
11
18
  };
12
-
13
- // src/utils/timing.ts
14
- var timing_exports = {};
15
- __export(timing_exports, {
16
- Timer: () => Timer,
17
- createTimer: () => createTimer,
18
- logTimingResult: () => logTimingResult
19
- });
20
- function formatTimingResult(result, indent = "") {
21
- const lines = [];
22
- let output = `${result.label}: ${result.duration}ms`;
23
- if (result.metadata) {
24
- const metadataStr = Object.entries(result.metadata).map(([k, v]) => `${k}: ${v}`).join(", ");
25
- output += ` (${metadataStr})`;
19
+ var EntryNotFoundError = class _EntryNotFoundError extends ContentfulError {
20
+ constructor(entryId, contentType) {
21
+ super(`Entry not found: ${entryId}${contentType ? ` (${contentType})` : ""}`, 404);
22
+ this.entryId = entryId;
23
+ this.contentType = contentType;
24
+ this.name = "EntryNotFoundError";
25
+ Object.setPrototypeOf(this, _EntryNotFoundError.prototype);
26
26
  }
27
- if (result.memoryDelta) {
28
- const mem = result.memoryDelta;
29
- const parts = [];
30
- if (Math.abs(mem.heapUsedMB) > 0.01) {
31
- parts.push(`heap: ${mem.heapUsedMB >= 0 ? "+" : ""}${mem.heapUsedMB}MB`);
32
- }
33
- if (Math.abs(mem.rssMB) > 0.01) {
34
- parts.push(`rss: ${mem.rssMB >= 0 ? "+" : ""}${mem.rssMB}MB`);
35
- }
36
- if (Math.abs(mem.externalMB) > 0.01) {
37
- parts.push(`ext: ${mem.externalMB >= 0 ? "+" : ""}${mem.externalMB}MB`);
38
- }
39
- if (parts.length > 0) {
40
- output += ` [${parts.join(", ")}]`;
41
- }
27
+ };
28
+ var AuthenticationError = class _AuthenticationError extends ContentfulError {
29
+ constructor(message = "Authentication failed") {
30
+ super(message, 401);
31
+ this.name = "AuthenticationError";
32
+ Object.setPrototypeOf(this, _AuthenticationError.prototype);
42
33
  }
43
- lines.push(`${indent}${output}`);
44
- if (result.children && result.children.length > 0) {
45
- for (let i = 0; i < result.children.length; i++) {
46
- const child = result.children[i];
47
- if (!child) continue;
48
- const isLast = i === result.children.length - 1;
49
- const childIndent = indent + (isLast ? " \u2514\u2500 " : " \u251C\u2500 ");
50
- const grandchildIndent = indent + (isLast ? " " : " \u2502 ");
51
- const childLines = formatTimingResult(child, "").split("\n");
52
- lines.push(childIndent + childLines[0]);
53
- for (let j = 1; j < childLines.length; j++) {
54
- lines.push(grandchildIndent + childLines[j]);
55
- }
56
- }
34
+ };
35
+ var ValidationError = class _ValidationError extends ContentfulError {
36
+ constructor(message, validationErrors) {
37
+ super(message, 400, validationErrors);
38
+ this.validationErrors = validationErrors;
39
+ this.name = "ValidationError";
40
+ Object.setPrototypeOf(this, _ValidationError.prototype);
41
+ }
42
+ };
43
+ function isContentfulError(error) {
44
+ return error instanceof ContentfulError;
45
+ }
46
+ function isRateLimitError(error) {
47
+ return error instanceof RateLimitError;
48
+ }
49
+ function isRetryableError(error) {
50
+ if (isRateLimitError(error)) {
51
+ return true;
57
52
  }
58
- return lines.join("\n");
53
+ if (isContentfulError(error)) {
54
+ return error.statusCode !== void 0 && (error.statusCode >= 500 || error.statusCode === 429);
55
+ }
56
+ return false;
59
57
  }
60
- function logTimingResult(result) {
61
- if (!shouldLog) return;
62
- console.log(`
63
- [Timing] ${formatTimingResult(result)}`);
58
+ function getRetryAfter(error) {
59
+ if (isRateLimitError(error)) {
60
+ return error.retryAfter;
61
+ }
62
+ return void 0;
64
63
  }
65
- function createTimer(label) {
66
- return new Timer(label);
64
+
65
+ // src/client.ts
66
+ function buildQueryString(query) {
67
+ const params = new URLSearchParams();
68
+ Object.entries(query).forEach(([key, value]) => {
69
+ if (value !== void 0 && value !== null) {
70
+ params.append(key, String(value));
71
+ }
72
+ });
73
+ return params.toString();
67
74
  }
68
- var isDevelopment, isDebugTimingEnabled, shouldLog, Timer;
69
- var init_timing = __esm({
70
- "src/utils/timing.ts"() {
71
- isDevelopment = process.env.NODE_ENV === "development";
72
- isDebugTimingEnabled = process.env.DEBUG_TIMING === "true";
73
- shouldLog = isDevelopment || isDebugTimingEnabled;
74
- Timer = class _Timer {
75
- startTime;
76
- memoryStart;
77
- label;
78
- children = [];
79
- metadata = {};
80
- trackMemory;
81
- constructor(label, trackMemory = true) {
82
- this.label = label;
83
- this.startTime = performance.now();
84
- this.trackMemory = trackMemory && shouldLog;
85
- if (this.trackMemory && typeof process !== "undefined" && process.memoryUsage) {
86
- this.memoryStart = process.memoryUsage();
87
- }
88
- }
89
- /**
90
- * Add metadata to the timing result
91
- */
92
- addMetadata(key, value) {
93
- this.metadata[key] = value;
94
- }
95
- /**
96
- * Create and return a child timer
97
- */
98
- child(label) {
99
- return new _Timer(`${this.label} > ${label}`);
100
- }
101
- /**
102
- * End the timer and return the result
103
- */
104
- end() {
105
- const duration = performance.now() - this.startTime;
106
- const result = {
107
- label: this.label,
108
- duration: Math.round(duration * 100) / 100,
109
- // Round to 2 decimal places
110
- children: this.children.length > 0 ? this.children : void 0,
111
- metadata: Object.keys(this.metadata).length > 0 ? this.metadata : void 0
112
- };
113
- if (this.memoryStart && typeof process !== "undefined" && process.memoryUsage) {
114
- const memoryEnd = process.memoryUsage();
115
- result.memoryDelta = {
116
- heapUsedMB: Number(
117
- ((memoryEnd.heapUsed - this.memoryStart.heapUsed) / 1024 / 1024).toFixed(2)
118
- ),
119
- heapTotalMB: Number(
120
- ((memoryEnd.heapTotal - this.memoryStart.heapTotal) / 1024 / 1024).toFixed(2)
121
- ),
122
- rssMB: Number(((memoryEnd.rss - this.memoryStart.rss) / 1024 / 1024).toFixed(2)),
123
- externalMB: Number(
124
- ((memoryEnd.external - this.memoryStart.external) / 1024 / 1024).toFixed(2)
125
- )
126
- };
127
- }
128
- return result;
129
- }
130
- /**
131
- * End timer and log the result
132
- */
133
- endAndLog() {
134
- const result = this.end();
135
- if (shouldLog) {
136
- logTimingResult(result);
137
- }
138
- return result;
139
- }
140
- /**
141
- * Execute a function and time it
142
- */
143
- static async time(label, fn, metadata) {
144
- const timer = new _Timer(label);
145
- if (metadata) {
146
- for (const [key, value] of Object.entries(metadata)) {
147
- timer.addMetadata(key, value);
148
- }
149
- }
150
- const result = await fn();
151
- const timing = timer.end();
152
- return { result, timing };
153
- }
154
- /**
155
- * Execute a synchronous function and time it
156
- */
157
- static timeSync(label, fn, metadata) {
158
- const timer = new _Timer(label);
159
- if (metadata) {
160
- for (const [key, value] of Object.entries(metadata)) {
161
- timer.addMetadata(key, value);
162
- }
163
- }
164
- const result = fn();
165
- const timing = timer.end();
166
- return { result, timing };
75
+ async function parseErrorResponse(response) {
76
+ const statusCode = response.status;
77
+ let errorData;
78
+ try {
79
+ errorData = await response.json();
80
+ } catch {
81
+ errorData = { message: response.statusText };
82
+ }
83
+ const message = errorData?.message || `Contentful API error: ${statusCode}`;
84
+ switch (statusCode) {
85
+ case 401:
86
+ return new AuthenticationError(message);
87
+ case 404:
88
+ return new EntryNotFoundError(
89
+ errorData?.sys?.id || "unknown",
90
+ errorData?.sys?.contentType?.sys?.id
91
+ );
92
+ case 429: {
93
+ const retryAfterHeader = response.headers.get("X-Contentful-RateLimit-Reset") || response.headers.get("Retry-After");
94
+ const retryAfter = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : void 0;
95
+ return new RateLimitError(message, retryAfter, errorData);
96
+ }
97
+ case 400:
98
+ return new ValidationError(message, errorData);
99
+ default:
100
+ return new ContentfulError(message, statusCode, errorData);
101
+ }
102
+ }
103
+ var ContentfulFetchClient = class {
104
+ baseUrl;
105
+ accessToken;
106
+ constructor(config, preview = false) {
107
+ const host = config.host || (preview ? "preview.contentful.com" : "cdn.contentful.com");
108
+ const environment = config.environment || "master";
109
+ this.baseUrl = `https://${host}/spaces/${config.spaceId}/environments/${environment}`;
110
+ this.accessToken = config.accessToken;
111
+ }
112
+ /**
113
+ * Fetches entries from Contentful
114
+ */
115
+ async getEntries(query, options) {
116
+ const queryString = buildQueryString(query);
117
+ const url = `${this.baseUrl}/entries?${queryString}`;
118
+ const fetchOptions = {
119
+ headers: {
120
+ Authorization: `Bearer ${this.accessToken}`,
121
+ "Content-Type": "application/json"
167
122
  }
168
123
  };
124
+ if (options?.next) {
125
+ fetchOptions.next = options.next;
126
+ }
127
+ const response = await fetch(url, fetchOptions);
128
+ if (!response.ok) {
129
+ throw await parseErrorResponse(response);
130
+ }
131
+ return response.json();
169
132
  }
170
- });
133
+ };
171
134
  function createContentfulClient(config) {
172
- return createClient({
173
- space: config.spaceId,
174
- accessToken: config.accessToken,
175
- environment: config.environment || "master",
176
- host: config.host,
177
- ...config.options
178
- });
135
+ return new ContentfulFetchClient(config, false);
179
136
  }
180
137
  function createContentfulPreviewClient(config) {
181
- return createClient({
182
- space: config.spaceId,
183
- accessToken: config.accessToken,
184
- environment: config.environment || "master",
185
- host: "preview.contentful.com",
186
- ...config.options
187
- });
138
+ return new ContentfulFetchClient(config, true);
188
139
  }
189
140
  function getContentfulClient(config, preview = false) {
190
- return (preview ? createContentfulPreviewClient(config) : createContentfulClient(config)).withoutLinkResolution;
141
+ return preview ? createContentfulPreviewClient(config) : createContentfulClient(config);
191
142
  }
192
143
 
193
144
  // src/converters/helpers.ts
@@ -212,7 +163,7 @@ function createInternalLink(id, fields, context, href, additionalProps) {
212
163
  return {
213
164
  type: "Internal link",
214
165
  id,
215
- name: cmsLabel,
166
+ name: cmsLabel ?? "",
216
167
  useName: true,
217
168
  text: makeContentfulTitle(title, id),
218
169
  visual: lookupAsset(context, featuredImage),
@@ -242,7 +193,7 @@ function addPositionMetadata(items) {
242
193
  }
243
194
 
244
195
  // src/converters/asset.ts
245
- function convertAssetToVisual(asset, options) {
196
+ function convertAssetToVisual(context, asset, options) {
246
197
  if (!asset) return void 0;
247
198
  const { fields, sys } = asset;
248
199
  if (!fields) return void 0;
@@ -259,7 +210,13 @@ function convertAssetToVisual(asset, options) {
259
210
  };
260
211
  }
261
212
  if (contentType?.startsWith("video/")) {
262
- const video = convertAssetToVideo(file, fields, sys, options);
213
+ const video = convertAssetToVideo(
214
+ file,
215
+ fields,
216
+ sys,
217
+ context,
218
+ options
219
+ );
263
220
  return {
264
221
  id,
265
222
  type: "Visual",
@@ -299,7 +256,7 @@ function convertAssetToVideoDetails(file, sys) {
299
256
  fileName
300
257
  };
301
258
  }
302
- function convertAssetToVideo(file, fields, sys, options) {
259
+ function convertAssetToVideo(file, fields, sys, context, options) {
303
260
  const { id } = sys;
304
261
  const { title, description } = fields;
305
262
  const { details } = file;
@@ -311,6 +268,7 @@ function convertAssetToVideo(file, fields, sys, options) {
311
268
  id,
312
269
  type: "Local video",
313
270
  preview: videoDetails,
271
+ videoPrefix: context.videoPrefix,
314
272
  width: width || 0,
315
273
  height: height || 0,
316
274
  name: makeContentfulTitle(title, id),
@@ -416,32 +374,6 @@ function lookupMediaEntry(context, link) {
416
374
  return void 0;
417
375
  }
418
376
 
419
- // src/converters/externalComponent.ts
420
- function baseExternalComponentConverter(_context, entry) {
421
- const { sys, fields } = entry;
422
- const {
423
- externalComponentType,
424
- cmsLabel,
425
- data,
426
- heading: _heading,
427
- // Exclude: not in target interface
428
- ...simpleFields
429
- // backgroundColour, textColour
430
- } = fields;
431
- return {
432
- type: "External component",
433
- id: sys.id,
434
- name: cmsLabel ?? `External component ${sys.id}`,
435
- cmsLabel: cmsLabel ?? null,
436
- externalType: externalComponentType,
437
- data: data ?? null,
438
- ...DEFAULT_POSITION_FIELDS,
439
- ...simpleFields,
440
- backgroundOverlayOpacity: null,
441
- backgroundVisual: void 0
442
- };
443
- }
444
-
445
377
  // src/converters/resolver.ts
446
378
  function resolveHelper(context, entry, getResolver) {
447
379
  const id = entry.sys.id;
@@ -456,6 +388,9 @@ function resolveHelper(context, entry, getResolver) {
456
388
  `No resolver found for link type ${possibleEntry.type} (${JSON.stringify(possibleEntry)}) [${JSON.stringify(entry)}]`
457
389
  );
458
390
  }
391
+ if (typeof resolver !== "function") {
392
+ console.log("Resolver type", possibleEntry.type, typeof resolver, resolver);
393
+ }
459
394
  const resolved = resolver(
460
395
  context,
461
396
  possibleEntry.entry
@@ -472,6 +407,15 @@ function resolveLink(context, entry) {
472
407
  (type) => context.linkResolver.get(type)
473
408
  );
474
409
  }
410
+ function resolveLinks(context, entries) {
411
+ return entries?.map((entry) => resolveLink(context, entry)) || [];
412
+ }
413
+ function resolveContent(context, entry) {
414
+ return resolveHelper(context, entry, (type) => {
415
+ const resolver = context.contentResolver.get(type);
416
+ return resolver;
417
+ });
418
+ }
475
419
  function resolveNavigationItem(context, entry) {
476
420
  return resolveHelper(
477
421
  context,
@@ -480,15 +424,14 @@ function resolveNavigationItem(context, entry) {
480
424
  );
481
425
  }
482
426
  function resolveCollectionContent(context, entry) {
483
- return resolveHelper(context, entry, (type) => {
484
- if (type === "component") {
485
- return context.componentResolver;
486
- }
487
- if (type === "collection") {
488
- return context.collectionResolver;
427
+ return resolveHelper(
428
+ context,
429
+ entry,
430
+ (type) => {
431
+ const resolver = context.contentResolver.get(type);
432
+ return resolver;
489
433
  }
490
- return void 0;
491
- });
434
+ );
492
435
  }
493
436
  function resolvePageContent(context, entry) {
494
437
  const id = entry.sys.id;
@@ -497,9 +440,6 @@ function resolvePageContent(context, entry) {
497
440
  throw new Error(`Cannot find included entry for content with id ${id}`);
498
441
  }
499
442
  const { type } = possibleEntry;
500
- if (type === "component" || type === "collection") {
501
- return resolveCollectionContent(context, entry);
502
- }
503
443
  if (type === "media") {
504
444
  const visual = convertMediaEntryToVisual(
505
445
  context,
@@ -520,8 +460,8 @@ function resolvePageContent(context, entry) {
520
460
  }
521
461
  return visual;
522
462
  }
523
- if (type === "externalComponent") {
524
- return resolveHelper(context, entry, () => baseExternalComponentConverter);
463
+ if (context.contentResolver.has(type)) {
464
+ return resolveContent(context, entry);
525
465
  }
526
466
  if (context.linkResolver.has(type)) {
527
467
  return resolveLink(context, entry);
@@ -631,9 +571,8 @@ function baseCollectionConverter(context, entry) {
631
571
  additionalCopy: additionalCopyField,
632
572
  // Field name change
633
573
  collectionType,
634
- // CMS-only fields (must exclude)
635
- textSize: _textSize,
636
- showHeading: _showHeading,
574
+ showHeading,
575
+ heading,
637
576
  // Already handled elsewhere
638
577
  cmsLabel,
639
578
  ...simpleFields
@@ -648,7 +587,7 @@ function baseCollectionConverter(context, entry) {
648
587
  lookupMediaEntry(context, mobileVisualField),
649
588
  visualCustomSize
650
589
  );
651
- return {
590
+ const collection = {
652
591
  type: "Collection",
653
592
  id: sys.id,
654
593
  name: cmsLabel,
@@ -656,6 +595,7 @@ function baseCollectionConverter(context, entry) {
656
595
  collectionType,
657
596
  ...DEFAULT_POSITION_FIELDS,
658
597
  ...simpleFields,
598
+ heading: showHeading ? heading : void 0,
659
599
  body: resolveRichTextDocument(context, bodyField),
660
600
  additionalCopy: resolveRichTextDocument(context, additionalCopyField),
661
601
  icon: lookupAsset(context, iconField),
@@ -664,6 +604,7 @@ function baseCollectionConverter(context, entry) {
664
604
  links: linksField?.map((link) => resolveLink(context, link)),
665
605
  contents: contentsField?.map((content) => resolveCollectionContent(context, content))
666
606
  };
607
+ return collection;
667
608
  }
668
609
 
669
610
  // src/converters/component.ts
@@ -682,9 +623,8 @@ function baseComponentConverter(context, entry) {
682
623
  additionalCopy: additionalCopyField,
683
624
  // Field name change
684
625
  componentType,
685
- // CMS-only fields (must exclude)
686
- textSize: _textSize,
687
- showHeading: _showHeading,
626
+ showHeading,
627
+ heading,
688
628
  otherMedia: _otherMedia,
689
629
  otherVisuals: _otherVisuals,
690
630
  // Already handled elsewhere
@@ -701,7 +641,7 @@ function baseComponentConverter(context, entry) {
701
641
  lookupMediaEntry(context, mobileVisualField),
702
642
  visualCustomSize
703
643
  );
704
- return {
644
+ const component = {
705
645
  type: "Component",
706
646
  id: sys.id,
707
647
  name: cmsLabel,
@@ -709,13 +649,15 @@ function baseComponentConverter(context, entry) {
709
649
  componentType,
710
650
  ...DEFAULT_POSITION_FIELDS,
711
651
  ...simpleFields,
652
+ heading: showHeading ? heading : void 0,
712
653
  body: resolveRichTextDocument(context, bodyField),
713
654
  additionalCopy: resolveRichTextDocument(context, additionalCopyField),
714
655
  icon: lookupAsset(context, iconField),
715
656
  backgroundVisual,
716
657
  visual,
717
- links: linksField?.map((link) => resolveLink(context, link))
658
+ links: resolveLinks(context, linksField)
718
659
  };
660
+ return component;
719
661
  }
720
662
 
721
663
  // src/converters/link.ts
@@ -871,7 +813,7 @@ function basePageConverter(context, entry) {
871
813
  ...postContent,
872
814
  ...bottomContent
873
815
  ]);
874
- return {
816
+ const page = {
875
817
  type: "Page",
876
818
  id: sys.id,
877
819
  isHomePage: slug === "index",
@@ -885,6 +827,7 @@ function basePageConverter(context, entry) {
885
827
  menu: template?.menu,
886
828
  footer: template?.footer
887
829
  };
830
+ return page;
888
831
  }
889
832
  function calculatePageHref(slug) {
890
833
  if (slug === "index") {
@@ -1000,7 +943,7 @@ function baseArticleConverter(context, entry) {
1000
943
  ...postContent,
1001
944
  ...bottomContent
1002
945
  ]);
1003
- return {
946
+ const article = {
1004
947
  type: "Article",
1005
948
  id: sys.id,
1006
949
  slug,
@@ -1016,6 +959,7 @@ function baseArticleConverter(context, entry) {
1016
959
  menu: template?.menu,
1017
960
  footer: template?.footer
1018
961
  };
962
+ return article;
1019
963
  }
1020
964
  function calculateArticleTypeHref(slug) {
1021
965
  return `/${slug}/`;
@@ -1096,12 +1040,11 @@ function createLink(context, entry) {
1096
1040
  }
1097
1041
  function baseNavigationItemConverter(context, entry) {
1098
1042
  const { sys, fields } = entry;
1099
- const { longText, navigationItems } = fields;
1043
+ const { navigationItems } = fields;
1100
1044
  const link = createLink(context, entry);
1101
1045
  const resolvedNavigationItems = navigationItems?.map((item) => resolveNavigationItem(context, item)).filter((item) => item !== void 0);
1102
1046
  return {
1103
1047
  id: sys.id,
1104
- longText,
1105
1048
  link,
1106
1049
  entries: resolvedNavigationItems
1107
1050
  };
@@ -1133,70 +1076,6 @@ function baseTagLinkConverter(context, entry) {
1133
1076
  );
1134
1077
  }
1135
1078
 
1136
- // src/utils/errors.ts
1137
- var ContentfulError = class _ContentfulError extends Error {
1138
- constructor(message, statusCode, details) {
1139
- super(message);
1140
- this.statusCode = statusCode;
1141
- this.details = details;
1142
- this.name = "ContentfulError";
1143
- Object.setPrototypeOf(this, _ContentfulError.prototype);
1144
- }
1145
- };
1146
- var RateLimitError = class _RateLimitError extends ContentfulError {
1147
- constructor(message, retryAfter, details) {
1148
- super(message, 429, details);
1149
- this.retryAfter = retryAfter;
1150
- this.name = "RateLimitError";
1151
- Object.setPrototypeOf(this, _RateLimitError.prototype);
1152
- }
1153
- };
1154
- var EntryNotFoundError = class _EntryNotFoundError extends ContentfulError {
1155
- constructor(entryId, contentType) {
1156
- super(`Entry not found: ${entryId}${contentType ? ` (${contentType})` : ""}`, 404);
1157
- this.entryId = entryId;
1158
- this.contentType = contentType;
1159
- this.name = "EntryNotFoundError";
1160
- Object.setPrototypeOf(this, _EntryNotFoundError.prototype);
1161
- }
1162
- };
1163
- var AuthenticationError = class _AuthenticationError extends ContentfulError {
1164
- constructor(message = "Authentication failed") {
1165
- super(message, 401);
1166
- this.name = "AuthenticationError";
1167
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
1168
- }
1169
- };
1170
- var ValidationError = class _ValidationError extends ContentfulError {
1171
- constructor(message, validationErrors) {
1172
- super(message, 400, validationErrors);
1173
- this.validationErrors = validationErrors;
1174
- this.name = "ValidationError";
1175
- Object.setPrototypeOf(this, _ValidationError.prototype);
1176
- }
1177
- };
1178
- function isContentfulError(error) {
1179
- return error instanceof ContentfulError;
1180
- }
1181
- function isRateLimitError(error) {
1182
- return error instanceof RateLimitError;
1183
- }
1184
- function isRetryableError(error) {
1185
- if (isRateLimitError(error)) {
1186
- return true;
1187
- }
1188
- if (isContentfulError(error)) {
1189
- return error.statusCode !== void 0 && (error.statusCode >= 500 || error.statusCode === 429);
1190
- }
1191
- return false;
1192
- }
1193
- function getRetryAfter(error) {
1194
- if (isRateLimitError(error)) {
1195
- return error.retryAfter;
1196
- }
1197
- return void 0;
1198
- }
1199
-
1200
1079
  // src/utils/retry.ts
1201
1080
  var DEFAULT_RETRY_CONFIG = {
1202
1081
  maxRetries: 3,
@@ -1296,16 +1175,13 @@ var RateLimiter = class {
1296
1175
  }
1297
1176
  };
1298
1177
 
1299
- // src/utils/index.ts
1300
- init_timing();
1301
-
1302
1178
  // src/api.ts
1303
- function convertAllAssets(response) {
1179
+ function convertAllAssets(response, context) {
1304
1180
  const visuals = /* @__PURE__ */ new Map();
1305
1181
  const assets = response.includes?.Asset;
1306
1182
  if (assets && assets.length > 0) {
1307
1183
  for (const asset of assets) {
1308
- const visual = convertAssetToVisual(asset);
1184
+ const visual = convertAssetToVisual(context, asset);
1309
1185
  if (visual) {
1310
1186
  visuals.set(visual.id, visual);
1311
1187
  }
@@ -1330,43 +1206,30 @@ function convertAllIncludes(response) {
1330
1206
  return includes;
1331
1207
  }
1332
1208
  async function contentfulPageRest(context, config, slug, options) {
1333
- const totalTimer = new Timer(`contentfulPageRest(${slug})`);
1334
1209
  const client = getContentfulClient(config, options?.preview);
1335
1210
  const fetchFn = async () => {
1336
- const apiFetchTimer = new Timer("API fetch");
1337
- const response = await client.getEntries({
1338
- content_type: "page",
1339
- "fields.slug": slug,
1340
- include: 10,
1341
- locale: options?.locale,
1342
- limit: 1
1343
- });
1344
- const apiFetchTiming = apiFetchTimer.end();
1211
+ const response = await client.getEntries(
1212
+ {
1213
+ content_type: "page",
1214
+ "fields.slug": slug,
1215
+ include: 10,
1216
+ locale: options?.locale,
1217
+ limit: 1
1218
+ },
1219
+ options
1220
+ );
1345
1221
  const pageEntry = response.items[0];
1346
1222
  if (!pageEntry || !pageEntry.fields) {
1347
- totalTimer.endAndLog();
1348
1223
  return null;
1349
1224
  }
1350
- const assetTimer = new Timer("Asset conversion");
1351
- const assets = convertAllAssets(response);
1352
- const assetTiming = assetTimer.end();
1353
- assetTiming.metadata = { count: assets.size };
1354
- const includesTimer = new Timer("Includes indexing");
1225
+ const assets = convertAllAssets(response, context);
1355
1226
  const includes = convertAllIncludes(response);
1356
- const includesTiming = includesTimer.end();
1357
- includesTiming.metadata = { count: includes.size };
1358
1227
  const fullContext = {
1359
1228
  ...context,
1360
1229
  includes,
1361
1230
  assets
1362
1231
  };
1363
- const conversionTimer = new Timer("Page conversion");
1364
1232
  const converted = fullContext.pageResolver(fullContext, pageEntry);
1365
- const conversionTiming = conversionTimer.end();
1366
- const totalTiming = totalTimer.end();
1367
- totalTiming.children = [apiFetchTiming, assetTiming, includesTiming, conversionTiming];
1368
- const { logTimingResult: logTimingResult2 } = await Promise.resolve().then(() => (init_timing(), timing_exports));
1369
- logTimingResult2(totalTiming);
1370
1233
  return converted;
1371
1234
  };
1372
1235
  if (options?.retry) {
@@ -1378,43 +1241,49 @@ function createBaseConverterContext() {
1378
1241
  const linkResolver = /* @__PURE__ */ new Map();
1379
1242
  linkResolver.set("page", basePageLinkConverter);
1380
1243
  linkResolver.set("article", baseArticleLinkConverter);
1381
- linkResolver.set(
1382
- "articleType",
1383
- baseArticleTypeLinkConverter
1384
- );
1244
+ linkResolver.set("articleType", baseArticleTypeLinkConverter);
1385
1245
  linkResolver.set("tag", baseTagLinkConverter);
1386
1246
  linkResolver.set("person", basePersonLinkConverter);
1387
- linkResolver.set(
1388
- "pageVariant",
1389
- basePageVariantLinkConverter
1390
- );
1247
+ linkResolver.set("pageVariant", basePageVariantLinkConverter);
1391
1248
  linkResolver.set("link", baseLinkConverter);
1249
+ const contentResolver = /* @__PURE__ */ new Map();
1250
+ contentResolver.set("collection", baseCollectionConverter);
1251
+ contentResolver.set("component", baseComponentConverter);
1252
+ contentResolver.set(
1253
+ "externalComponent",
1254
+ baseComponentConverter
1255
+ );
1392
1256
  return {
1393
1257
  pageResolver: basePageConverter,
1394
1258
  navigationItemResolver: baseNavigationItemConverter,
1395
1259
  articleResolver: baseArticleConverter,
1396
1260
  componentResolver: baseComponentConverter,
1397
1261
  collectionResolver: baseCollectionConverter,
1398
- linkResolver
1262
+ linkResolver,
1263
+ contentResolver,
1264
+ videoPrefix: ""
1399
1265
  };
1400
1266
  }
1401
1267
  async function contentfulArticleRest(context, config, slug, articleTypeSlug, options) {
1402
1268
  const client = getContentfulClient(config, options?.preview);
1403
1269
  const fetchFn = async () => {
1404
- const response = await client.getEntries({
1405
- content_type: "article",
1406
- "fields.slug": slug,
1407
- "fields.articleType.sys.contentType.sys.id": "articleType",
1408
- "fields.articleType.fields.slug": articleTypeSlug,
1409
- include: 10,
1410
- locale: options?.locale,
1411
- limit: 1
1412
- });
1270
+ const response = await client.getEntries(
1271
+ {
1272
+ content_type: "article",
1273
+ "fields.slug": slug,
1274
+ "fields.articleType.sys.contentType.sys.id": "articleType",
1275
+ "fields.articleType.fields.slug": articleTypeSlug,
1276
+ include: 10,
1277
+ locale: options?.locale,
1278
+ limit: 1
1279
+ },
1280
+ options
1281
+ );
1413
1282
  const articleEntry = response.items[0];
1414
1283
  if (!articleEntry || !articleEntry.fields) {
1415
1284
  return null;
1416
1285
  }
1417
- const assets = convertAllAssets(response);
1286
+ const assets = convertAllAssets(response, context);
1418
1287
  const includes = convertAllIncludes(response);
1419
1288
  const fullContext = {
1420
1289
  ...context,
@@ -1430,6 +1299,6 @@ async function contentfulArticleRest(context, config, slug, articleTypeSlug, opt
1430
1299
  return await fetchFn();
1431
1300
  }
1432
1301
 
1433
- export { AuthenticationError, ContentfulError, EntryNotFoundError, RateLimitError, RateLimiter, Timer, ValidationError, basePageConverter, calculateBackoffDelay, contentfulArticleRest, contentfulPageRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createTimer, getContentfulClient, getRetryAfter, isContentfulError, isRateLimitError, isRetryableError, logTimingResult, withRetry };
1302
+ export { AuthenticationError, ContentfulError, EntryNotFoundError, RateLimitError, RateLimiter, ValidationError, basePageConverter, calculateBackoffDelay, contentfulArticleRest, contentfulPageRest, createBaseConverterContext, createContentfulClient, createContentfulPreviewClient, createResponsiveVisual, getContentfulClient, getRetryAfter, isContentfulError, isRateLimitError, isRetryableError, lookupAsset, resolveLink, resolveLinks, resolveRichTextDocument, withRetry };
1434
1303
  //# sourceMappingURL=index.js.map
1435
1304
  //# sourceMappingURL=index.js.map