@fourtwelvelabs/fetch-contentful 0.4.1 → 1.1.0
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/CHANGELOG.md +165 -0
- package/README.md +228 -57
- package/dist/cli/index.mjs +21 -72
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +452 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +307 -26
- package/dist/index.d.ts +307 -26
- package/dist/index.mjs +448 -151
- package/dist/index.mjs.map +1 -1
- package/docs/tada.md +31 -29
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,113 @@
|
|
|
1
|
-
import { Kind, parse, print, visit } from 'graphql';
|
|
1
|
+
import { TokenKind, Lexer, Source, Kind, parse, print, visit } from 'graphql';
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
|
|
5
|
+
// src/annotate.ts
|
|
6
|
+
var ESC = String.fromCharCode(27);
|
|
7
|
+
var ANSI = {
|
|
8
|
+
reset: `${ESC}[0m`,
|
|
9
|
+
bold: `${ESC}[1m`,
|
|
10
|
+
dim: `${ESC}[2m`,
|
|
11
|
+
red: `${ESC}[31m`
|
|
12
|
+
};
|
|
13
|
+
var DEFAULT_CONTEXT_LINES = 3;
|
|
14
|
+
function supportsColor() {
|
|
15
|
+
if (typeof process === "undefined" || !process.env) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const forced = process.env.FORCE_COLOR;
|
|
19
|
+
const disabled = process.env.NO_COLOR;
|
|
20
|
+
if (forced) {
|
|
21
|
+
return forced !== "0" && forced !== "false";
|
|
22
|
+
}
|
|
23
|
+
if (disabled) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return Boolean(process.stderr?.isTTY);
|
|
27
|
+
}
|
|
28
|
+
function makePalette(enabled) {
|
|
29
|
+
const paint = (code) => (text) => enabled ? `${code}${text}${ANSI.reset}` : text;
|
|
30
|
+
return {
|
|
31
|
+
dim: paint(ANSI.dim),
|
|
32
|
+
red: paint(ANSI.red),
|
|
33
|
+
bold: paint(ANSI.bold)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function collectMarks(errors, lineCount) {
|
|
37
|
+
const marks = [];
|
|
38
|
+
const seen = /* @__PURE__ */ new Set();
|
|
39
|
+
for (const error of errors) {
|
|
40
|
+
for (const location of error.locations ?? []) {
|
|
41
|
+
const line = Math.trunc(location.line);
|
|
42
|
+
if (!(line >= 1 && line <= lineCount)) continue;
|
|
43
|
+
const reported = Math.trunc(location.column);
|
|
44
|
+
const column = reported >= 1 ? reported : 1;
|
|
45
|
+
const key = `${line}:${column}:${error.message}`;
|
|
46
|
+
if (seen.has(key)) continue;
|
|
47
|
+
seen.add(key);
|
|
48
|
+
marks.push({ line, column, message: error.message });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return marks.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
52
|
+
}
|
|
53
|
+
function excerptsFor(marks, lineCount, contextLines) {
|
|
54
|
+
const excerpts = [];
|
|
55
|
+
for (const mark of marks) {
|
|
56
|
+
const start = Math.max(1, mark.line - contextLines);
|
|
57
|
+
const end = Math.min(lineCount, mark.line + contextLines);
|
|
58
|
+
const previous = excerpts[excerpts.length - 1];
|
|
59
|
+
if (previous && start <= previous.end + 1) {
|
|
60
|
+
previous.end = Math.max(previous.end, end);
|
|
61
|
+
} else {
|
|
62
|
+
excerpts.push({ start, end });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return excerpts;
|
|
66
|
+
}
|
|
67
|
+
function annotateQuery(query, errors, options = {}) {
|
|
68
|
+
const lines = query.split("\n");
|
|
69
|
+
const marks = collectMarks(errors, lines.length);
|
|
70
|
+
if (marks.length === 0) return "";
|
|
71
|
+
const color = makePalette(options.color ?? supportsColor());
|
|
72
|
+
const excerpts = excerptsFor(marks, lines.length, options.contextLines ?? DEFAULT_CONTEXT_LINES);
|
|
73
|
+
const gutter = String(
|
|
74
|
+
excerpts.reduce((widest, excerpt) => Math.max(widest, excerpt.end), 0)
|
|
75
|
+
).length;
|
|
76
|
+
const blank = " ".repeat(gutter);
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const [index, excerpt] of excerpts.entries()) {
|
|
79
|
+
if (index > 0) out.push(color.dim(` ${blank} ...`));
|
|
80
|
+
const window = lines.slice(excerpt.start - 1, excerpt.end);
|
|
81
|
+
for (const [offset, source] of window.entries()) {
|
|
82
|
+
const line = excerpt.start + offset;
|
|
83
|
+
const number = String(line).padStart(gutter, " ");
|
|
84
|
+
const here = marks.filter((mark) => mark.line === line);
|
|
85
|
+
if (here.length === 0) {
|
|
86
|
+
out.push(`${color.dim(` ${number} |`)} ${source}`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
out.push(`${color.red(`> ${number} |`)} ${color.bold(source)}`);
|
|
90
|
+
for (const mark of here) {
|
|
91
|
+
const lead = " ".repeat(mark.column - 1);
|
|
92
|
+
out.push(`${color.dim(` ${blank} |`)} ${lead}${color.red(`^ ${mark.message}`)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return out.join("\n");
|
|
97
|
+
}
|
|
98
|
+
|
|
5
99
|
// src/errors.ts
|
|
6
100
|
var FetchContentfulError = class extends Error {
|
|
7
101
|
code;
|
|
8
102
|
status;
|
|
9
103
|
errors;
|
|
104
|
+
/**
|
|
105
|
+
* The GraphQL query exactly as it was sent to Contentful — fragments
|
|
106
|
+
* inlined, arguments injected, and (for a subquery) generated. This is
|
|
107
|
+
* the text the `line`/`column` in {@link FetchContentfulError.errors}
|
|
108
|
+
* point into, so it is the text to annotate; see `annotateQuery`.
|
|
109
|
+
*/
|
|
110
|
+
query;
|
|
10
111
|
/** Internal: whether a retry may succeed. */
|
|
11
112
|
retryable;
|
|
12
113
|
/** Internal: server-requested retry delay (from Retry-After), in ms. */
|
|
@@ -17,6 +118,7 @@ var FetchContentfulError = class extends Error {
|
|
|
17
118
|
this.code = options.code;
|
|
18
119
|
this.status = options.status;
|
|
19
120
|
this.errors = options.errors;
|
|
121
|
+
this.query = options.query;
|
|
20
122
|
this.retryable = options.retryable ?? false;
|
|
21
123
|
this.retryAfterMs = options.retryAfterMs;
|
|
22
124
|
}
|
|
@@ -24,6 +126,48 @@ var FetchContentfulError = class extends Error {
|
|
|
24
126
|
function isFetchContentfulError(value) {
|
|
25
127
|
return value instanceof FetchContentfulError;
|
|
26
128
|
}
|
|
129
|
+
var WORD_LIKE = /* @__PURE__ */ new Set([TokenKind.NAME, TokenKind.INT, TokenKind.FLOAT]);
|
|
130
|
+
function minifyQuery(query) {
|
|
131
|
+
const lexer = new Lexer(new Source(query));
|
|
132
|
+
let previousKind;
|
|
133
|
+
let out = "";
|
|
134
|
+
for (let token = lexer.advance(); token.kind !== TokenKind.EOF; token = lexer.advance()) {
|
|
135
|
+
if (previousKind && WORD_LIKE.has(previousKind) && WORD_LIKE.has(token.kind)) {
|
|
136
|
+
out += " ";
|
|
137
|
+
}
|
|
138
|
+
out += query.slice(token.start, token.end);
|
|
139
|
+
previousKind = token.kind;
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/persisted-query.ts
|
|
145
|
+
var PERSISTED_QUERY_VERSION = 1;
|
|
146
|
+
function toHex(bytes) {
|
|
147
|
+
let hex = "";
|
|
148
|
+
for (const byte of bytes) {
|
|
149
|
+
hex += byte.toString(16).padStart(2, "0");
|
|
150
|
+
}
|
|
151
|
+
return hex;
|
|
152
|
+
}
|
|
153
|
+
async function sha256Hex(query) {
|
|
154
|
+
const data = new TextEncoder().encode(query);
|
|
155
|
+
const subtle = globalThis.crypto?.subtle;
|
|
156
|
+
if (subtle) {
|
|
157
|
+
const digest = await subtle.digest("SHA-256", data);
|
|
158
|
+
return toHex(new Uint8Array(digest));
|
|
159
|
+
}
|
|
160
|
+
const { createHash } = await import('crypto');
|
|
161
|
+
return createHash("sha256").update(data).digest("hex");
|
|
162
|
+
}
|
|
163
|
+
function persistedQueryExtensions(sha256Hash) {
|
|
164
|
+
return { persistedQuery: { version: PERSISTED_QUERY_VERSION, sha256Hash } };
|
|
165
|
+
}
|
|
166
|
+
function isPersistedQueryNotFoundError(error) {
|
|
167
|
+
if (error.message === "PersistedQueryNotFound") return true;
|
|
168
|
+
const extensions = error.extensions;
|
|
169
|
+
return extensions?.code === "PERSISTED_QUERY_NOT_FOUND";
|
|
170
|
+
}
|
|
27
171
|
|
|
28
172
|
// src/retry.ts
|
|
29
173
|
function defaultSleep(ms) {
|
|
@@ -90,6 +234,9 @@ function withDirective(field, name) {
|
|
|
90
234
|
function responseKeyOf(field) {
|
|
91
235
|
return field.alias?.value ?? field.name.value;
|
|
92
236
|
}
|
|
237
|
+
function hasResponseKey(selection, key) {
|
|
238
|
+
return selection.kind === Kind.FIELD && responseKeyOf(selection) === key;
|
|
239
|
+
}
|
|
93
240
|
function isCollectionField(field) {
|
|
94
241
|
if (!field.name.value.endsWith(COLLECTION_SUFFIX) || field.name.value === COLLECTION_SUFFIX || !field.selectionSet) {
|
|
95
242
|
return false;
|
|
@@ -132,16 +279,14 @@ function getOperation(document) {
|
|
|
132
279
|
);
|
|
133
280
|
const operation = operations[0];
|
|
134
281
|
if (!operation || operations.length > 1) {
|
|
135
|
-
throw new FetchContentfulError(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
);
|
|
282
|
+
throw new FetchContentfulError("fetch-contentful expects exactly one operation per document.", {
|
|
283
|
+
code: "CONFIG"
|
|
284
|
+
});
|
|
139
285
|
}
|
|
140
286
|
if (operation.operation !== "query") {
|
|
141
|
-
throw new FetchContentfulError(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
);
|
|
287
|
+
throw new FetchContentfulError("fetch-contentful only supports query operations.", {
|
|
288
|
+
code: "CONFIG"
|
|
289
|
+
});
|
|
145
290
|
}
|
|
146
291
|
return operation;
|
|
147
292
|
}
|
|
@@ -153,41 +298,34 @@ function inlineFragments(document) {
|
|
|
153
298
|
}
|
|
154
299
|
}
|
|
155
300
|
function inlineSelectionSet(selectionSet, stack) {
|
|
156
|
-
const selections = selectionSet.selections.map(
|
|
157
|
-
(selection)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{ code: "CONFIG" }
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
if (stack.includes(name)) {
|
|
168
|
-
throw new FetchContentfulError(
|
|
169
|
-
`Fragment cycle detected involving "${name}".`,
|
|
170
|
-
{ code: "CONFIG" }
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
kind: Kind.INLINE_FRAGMENT,
|
|
175
|
-
typeCondition: fragment.typeCondition,
|
|
176
|
-
selectionSet: inlineSelectionSet(fragment.selectionSet, [
|
|
177
|
-
...stack,
|
|
178
|
-
name
|
|
179
|
-
])
|
|
180
|
-
};
|
|
301
|
+
const selections = selectionSet.selections.map((selection) => {
|
|
302
|
+
if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
303
|
+
const name = selection.name.value;
|
|
304
|
+
const fragment = fragments.get(name);
|
|
305
|
+
if (!fragment) {
|
|
306
|
+
throw new FetchContentfulError(`Unknown fragment "${name}" referenced in query.`, {
|
|
307
|
+
code: "CONFIG"
|
|
308
|
+
});
|
|
181
309
|
}
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
};
|
|
310
|
+
if (stack.includes(name)) {
|
|
311
|
+
throw new FetchContentfulError(`Fragment cycle detected involving "${name}".`, {
|
|
312
|
+
code: "CONFIG"
|
|
313
|
+
});
|
|
187
314
|
}
|
|
188
|
-
return
|
|
315
|
+
return {
|
|
316
|
+
kind: Kind.INLINE_FRAGMENT,
|
|
317
|
+
typeCondition: fragment.typeCondition,
|
|
318
|
+
selectionSet: inlineSelectionSet(fragment.selectionSet, [...stack, name])
|
|
319
|
+
};
|
|
189
320
|
}
|
|
190
|
-
|
|
321
|
+
if (selection.selectionSet) {
|
|
322
|
+
return {
|
|
323
|
+
...selection,
|
|
324
|
+
selectionSet: inlineSelectionSet(selection.selectionSet, stack)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return selection;
|
|
328
|
+
});
|
|
191
329
|
return { ...selectionSet, selections };
|
|
192
330
|
}
|
|
193
331
|
const definitions = document.definitions.filter((definition) => definition.kind !== Kind.FRAGMENT_DEFINITION).map(
|
|
@@ -222,26 +360,23 @@ function planSplits(document, options) {
|
|
|
222
360
|
continue;
|
|
223
361
|
}
|
|
224
362
|
if (selection.kind !== Kind.FIELD) {
|
|
225
|
-
throw new FetchContentfulError(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
);
|
|
363
|
+
throw new FetchContentfulError("Fragment spreads must be inlined before split planning.", {
|
|
364
|
+
code: "CONFIG"
|
|
365
|
+
});
|
|
229
366
|
}
|
|
230
367
|
const field = selection;
|
|
231
368
|
const isExplicitSplit = hasDirective(field, SPLIT_DIRECTIVE);
|
|
232
369
|
const isAutoSplit = options.autoSplitNestedCollections && isCollectionField(field);
|
|
370
|
+
const isForcedSplit = options.forceSplit?.(field) ?? false;
|
|
233
371
|
if (isExplicitSplit && depth === 0) {
|
|
234
372
|
throw new FetchContentfulError(
|
|
235
373
|
`Cannot split root field "${responseKeyOf(field)}": @split needs a parent entry to stitch the result back onto, and root fields have none. Move the directive to a nested field, or page through this field with its own \`limit\` and \`skip\` arguments.`,
|
|
236
374
|
{ code: "CONFIG" }
|
|
237
375
|
);
|
|
238
376
|
}
|
|
239
|
-
const shouldSplit = depth > 0 && field.selectionSet !== void 0 && !hasDirective(field, NO_SPLIT_DIRECTIVE) && (isExplicitSplit || isAutoSplit);
|
|
377
|
+
const shouldSplit = depth > 0 && field.selectionSet !== void 0 && !hasDirective(field, NO_SPLIT_DIRECTIVE) && (isExplicitSplit || isAutoSplit || isForcedSplit);
|
|
240
378
|
if (shouldSplit) {
|
|
241
|
-
const planned = withDirective(
|
|
242
|
-
withoutDirective(field, SPLIT_DIRECTIVE),
|
|
243
|
-
NO_SPLIT_DIRECTIVE
|
|
244
|
-
);
|
|
379
|
+
const planned = withDirective(withoutDirective(field, SPLIT_DIRECTIVE), NO_SPLIT_DIRECTIVE);
|
|
245
380
|
plans.push({
|
|
246
381
|
path: [...path],
|
|
247
382
|
responseKey: responseKeyOf(field),
|
|
@@ -270,8 +405,11 @@ function planSplits(document, options) {
|
|
|
270
405
|
selections.push(field);
|
|
271
406
|
}
|
|
272
407
|
}
|
|
273
|
-
if (needsMarkers) {
|
|
274
|
-
selections.push(sysIdMarker()
|
|
408
|
+
if (needsMarkers && !selections.some((s) => hasResponseKey(s, SYS_ID_ALIAS))) {
|
|
409
|
+
selections.push(sysIdMarker());
|
|
410
|
+
}
|
|
411
|
+
if (needsMarkers && !selections.some((s) => hasResponseKey(s, TYPENAME_ALIAS))) {
|
|
412
|
+
selections.push(typenameMarker());
|
|
275
413
|
}
|
|
276
414
|
return { ...selectionSet, selections };
|
|
277
415
|
}
|
|
@@ -289,6 +427,49 @@ function planSplits(document, options) {
|
|
|
289
427
|
plans
|
|
290
428
|
};
|
|
291
429
|
}
|
|
430
|
+
function findSplitCandidates(document) {
|
|
431
|
+
const operation = getOperation(document);
|
|
432
|
+
const candidates = [];
|
|
433
|
+
function walk2(selectionSet, depth) {
|
|
434
|
+
for (const selection of selectionSet.selections) {
|
|
435
|
+
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
436
|
+
walk2(selection.selectionSet, depth);
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
if (selection.kind !== Kind.FIELD || !selection.selectionSet) continue;
|
|
440
|
+
const isMarker = hasResponseKey(selection, SYS_ID_ALIAS) || hasResponseKey(selection, TYPENAME_ALIAS);
|
|
441
|
+
if (depth > 0 && selection.name.value !== "items" && !isMarker) {
|
|
442
|
+
candidates.push({ field: selection, size: print(selection).length });
|
|
443
|
+
}
|
|
444
|
+
walk2(selection.selectionSet, depth + 1);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
walk2(operation.selectionSet, 0);
|
|
448
|
+
return candidates;
|
|
449
|
+
}
|
|
450
|
+
function planSplitsWithSizeBudget(document, options) {
|
|
451
|
+
const first = planSplits(document, {
|
|
452
|
+
autoSplitNestedCollections: options.autoSplitNestedCollections
|
|
453
|
+
});
|
|
454
|
+
if (!options.autoSplitOnSize) return first;
|
|
455
|
+
let outer = first.document;
|
|
456
|
+
const plans = [...first.plans];
|
|
457
|
+
let remainingIterations = findSplitCandidates(outer).length;
|
|
458
|
+
while (options.measure(outer) > options.maxQuerySize && remainingIterations-- > 0) {
|
|
459
|
+
const candidates = findSplitCandidates(outer);
|
|
460
|
+
if (candidates.length === 0) break;
|
|
461
|
+
const target = candidates.reduce(
|
|
462
|
+
(largest, candidate) => candidate.size > largest.size ? candidate : largest
|
|
463
|
+
);
|
|
464
|
+
const next = planSplits(outer, {
|
|
465
|
+
autoSplitNestedCollections: false,
|
|
466
|
+
forceSplit: (field) => field === target.field
|
|
467
|
+
});
|
|
468
|
+
outer = next.document;
|
|
469
|
+
plans.push(...next.plans);
|
|
470
|
+
}
|
|
471
|
+
return { document: outer, plans };
|
|
472
|
+
}
|
|
292
473
|
function stringArgument(name, value) {
|
|
293
474
|
return {
|
|
294
475
|
kind: Kind.ARGUMENT,
|
|
@@ -340,10 +521,7 @@ function whereIdInArgument() {
|
|
|
340
521
|
}
|
|
341
522
|
function buildSubquery(plan, typename, batchSize, context) {
|
|
342
523
|
const rootKey = `${lowerFirst(typename)}${COLLECTION_SUFFIX}`;
|
|
343
|
-
const args = [
|
|
344
|
-
whereIdInArgument(),
|
|
345
|
-
intArgument("limit", batchSize)
|
|
346
|
-
];
|
|
524
|
+
const args = [whereIdInArgument(), intArgument("limit", batchSize)];
|
|
347
525
|
if (context.preview) {
|
|
348
526
|
args.push(booleanArgument("preview", true));
|
|
349
527
|
}
|
|
@@ -352,10 +530,7 @@ function buildSubquery(plan, typename, batchSize, context) {
|
|
|
352
530
|
}
|
|
353
531
|
const rootField = {
|
|
354
532
|
...namedField(rootKey, void 0, [
|
|
355
|
-
namedField("items", void 0, [
|
|
356
|
-
namedField("sys", void 0, [namedField("id")]),
|
|
357
|
-
plan.field
|
|
358
|
-
])
|
|
533
|
+
namedField("items", void 0, [namedField("sys", void 0, [namedField("id")]), plan.field])
|
|
359
534
|
]),
|
|
360
535
|
arguments: args
|
|
361
536
|
};
|
|
@@ -405,12 +580,68 @@ function stripInternalDirectives(document) {
|
|
|
405
580
|
});
|
|
406
581
|
}
|
|
407
582
|
|
|
583
|
+
// src/unresolvable.ts
|
|
584
|
+
var UNRESOLVABLE_LINK_CODE = "UNRESOLVABLE_LINK";
|
|
585
|
+
var COLLECTION_SUFFIX2 = "Collection";
|
|
586
|
+
function isRecord(value) {
|
|
587
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
588
|
+
}
|
|
589
|
+
function isCollectionValue(value) {
|
|
590
|
+
return isRecord(value) && Array.isArray(value["items"]);
|
|
591
|
+
}
|
|
592
|
+
function isCollectionKey(key) {
|
|
593
|
+
return key.endsWith(COLLECTION_SUFFIX2) && key !== COLLECTION_SUFFIX2;
|
|
594
|
+
}
|
|
595
|
+
function isUnresolvableLinkError(error) {
|
|
596
|
+
const contentful = error.extensions?.["contentful"];
|
|
597
|
+
return isRecord(contentful) && contentful["code"] === UNRESOLVABLE_LINK_CODE;
|
|
598
|
+
}
|
|
599
|
+
function partitionUnresolvableLinks(errors) {
|
|
600
|
+
const unresolvable = [];
|
|
601
|
+
const fatal = [];
|
|
602
|
+
for (const error of errors) {
|
|
603
|
+
if (isUnresolvableLinkError(error)) {
|
|
604
|
+
unresolvable.push(error);
|
|
605
|
+
} else {
|
|
606
|
+
fatal.push(error);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return { unresolvable, fatal };
|
|
610
|
+
}
|
|
611
|
+
function walk(value) {
|
|
612
|
+
if (Array.isArray(value)) {
|
|
613
|
+
return value.map(walk);
|
|
614
|
+
}
|
|
615
|
+
if (isRecord(value)) {
|
|
616
|
+
const result = {};
|
|
617
|
+
for (const [key, child] of Object.entries(value)) {
|
|
618
|
+
result[key] = isCollectionKey(key) && isCollectionValue(child) ? stripCollection(child) : walk(child);
|
|
619
|
+
}
|
|
620
|
+
return result;
|
|
621
|
+
}
|
|
622
|
+
return value;
|
|
623
|
+
}
|
|
624
|
+
function stripCollection(collection) {
|
|
625
|
+
const result = {};
|
|
626
|
+
for (const [key, value] of Object.entries(collection)) {
|
|
627
|
+
result[key] = key === "items" ? value.filter((item) => item !== null && item !== void 0).map(walk) : walk(value);
|
|
628
|
+
}
|
|
629
|
+
return result;
|
|
630
|
+
}
|
|
631
|
+
function omitUnresolvedLinks(data) {
|
|
632
|
+
return walk(data);
|
|
633
|
+
}
|
|
634
|
+
|
|
408
635
|
// src/client.ts
|
|
409
636
|
function graphqlEndpoint(space, environment) {
|
|
410
637
|
return `https://graphql.contentful.com/content/v1/spaces/${encodeURIComponent(
|
|
411
638
|
space
|
|
412
639
|
)}/environments/${encodeURIComponent(environment)}`;
|
|
413
640
|
}
|
|
641
|
+
function printOutgoingQuery(document, context) {
|
|
642
|
+
const printed = print(stripInternalDirectives(document));
|
|
643
|
+
return context.minifyQuery === false ? printed : minifyQuery(printed);
|
|
644
|
+
}
|
|
414
645
|
function parseRetryAfter(header) {
|
|
415
646
|
if (!header) return void 0;
|
|
416
647
|
const seconds = Number(header);
|
|
@@ -440,14 +671,47 @@ function pickDeclaredVariables(document, variables) {
|
|
|
440
671
|
function isRetryableStatus(status) {
|
|
441
672
|
return status === 408 || status === 429 || status >= 500;
|
|
442
673
|
}
|
|
674
|
+
function isRecord2(value) {
|
|
675
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
676
|
+
}
|
|
677
|
+
function reportUnresolvableLinks(errors, context) {
|
|
678
|
+
if (!context.onUnresolvableLink) return;
|
|
679
|
+
try {
|
|
680
|
+
context.onUnresolvableLink(errors);
|
|
681
|
+
} catch {
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
async function readGraphQLErrors(response) {
|
|
685
|
+
try {
|
|
686
|
+
const payload = await response.json();
|
|
687
|
+
const errors = payload?.errors;
|
|
688
|
+
return Array.isArray(errors) && errors.length > 0 ? errors : void 0;
|
|
689
|
+
} catch {
|
|
690
|
+
return void 0;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function describeFailure(summary, errors, query, context) {
|
|
694
|
+
if (!errors || errors.length === 0) return summary;
|
|
695
|
+
const message = `${summary} ${errors.map((error) => error.message).join("; ")}`;
|
|
696
|
+
if (context.annotateQueryOnError === false) return message;
|
|
697
|
+
const annotated = annotateQuery(query, errors);
|
|
698
|
+
return annotated ? `${message}
|
|
699
|
+
|
|
700
|
+
${annotated}
|
|
701
|
+
` : message;
|
|
702
|
+
}
|
|
443
703
|
async function rawRequest(document, variables, context) {
|
|
444
|
-
const query =
|
|
445
|
-
const
|
|
446
|
-
query,
|
|
447
|
-
variables: pickDeclaredVariables(document, variables)
|
|
448
|
-
});
|
|
704
|
+
const query = printOutgoingQuery(document, context);
|
|
705
|
+
const pickedVariables = pickDeclaredVariables(document, variables);
|
|
449
706
|
const url = graphqlEndpoint(context.space, context.environment);
|
|
450
|
-
|
|
707
|
+
const usePersistedQuery = context.automaticPersistedQueries === true;
|
|
708
|
+
const sha256Hash = usePersistedQuery ? await sha256Hex(query) : void 0;
|
|
709
|
+
async function send(includeQuery) {
|
|
710
|
+
const body = JSON.stringify({
|
|
711
|
+
...includeQuery ? { query } : {},
|
|
712
|
+
variables: pickedVariables,
|
|
713
|
+
...sha256Hash ? { extensions: persistedQueryExtensions(sha256Hash) } : {}
|
|
714
|
+
});
|
|
451
715
|
let response;
|
|
452
716
|
try {
|
|
453
717
|
const init = {
|
|
@@ -465,16 +729,24 @@ async function rawRequest(document, variables, context) {
|
|
|
465
729
|
} catch (cause) {
|
|
466
730
|
throw new FetchContentfulError(
|
|
467
731
|
`Network error while contacting Contentful: ${String(cause)}`,
|
|
468
|
-
{ code: "NETWORK", retryable: true, cause }
|
|
732
|
+
{ code: "NETWORK", query, retryable: true, cause }
|
|
469
733
|
);
|
|
470
734
|
}
|
|
471
735
|
if (!response.ok) {
|
|
472
736
|
const retryable = isRetryableStatus(response.status);
|
|
737
|
+
const errors = retryable ? void 0 : await readGraphQLErrors(response);
|
|
473
738
|
throw new FetchContentfulError(
|
|
474
|
-
|
|
739
|
+
describeFailure(
|
|
740
|
+
`Contentful responded with HTTP ${response.status}.`,
|
|
741
|
+
errors,
|
|
742
|
+
query,
|
|
743
|
+
context
|
|
744
|
+
),
|
|
475
745
|
{
|
|
476
746
|
code: "HTTP",
|
|
477
747
|
status: response.status,
|
|
748
|
+
errors,
|
|
749
|
+
query,
|
|
478
750
|
retryable,
|
|
479
751
|
retryAfterMs: retryable ? parseRetryAfter(response.headers.get("Retry-After")) : void 0
|
|
480
752
|
}
|
|
@@ -484,24 +756,46 @@ async function rawRequest(document, variables, context) {
|
|
|
484
756
|
try {
|
|
485
757
|
payload = await response.json();
|
|
486
758
|
} catch (cause) {
|
|
487
|
-
throw new FetchContentfulError(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
759
|
+
throw new FetchContentfulError("Contentful returned an unreadable response body.", {
|
|
760
|
+
code: "NETWORK",
|
|
761
|
+
query,
|
|
762
|
+
retryable: true,
|
|
763
|
+
cause
|
|
764
|
+
});
|
|
491
765
|
}
|
|
492
766
|
if (payload.errors && payload.errors.length > 0) {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
767
|
+
const { unresolvable, fatal } = partitionUnresolvableLinks(payload.errors);
|
|
768
|
+
const tolerable = context.unresolvableLinks !== "error" && fatal.length === 0 && unresolvable.length > 0 && isRecord2(payload.data);
|
|
769
|
+
if (!tolerable) {
|
|
770
|
+
throw new FetchContentfulError(
|
|
771
|
+
describeFailure("Contentful returned GraphQL errors:", payload.errors, query, context),
|
|
772
|
+
{ code: "GRAPHQL", errors: payload.errors, query }
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
reportUnresolvableLinks(unresolvable, context);
|
|
497
776
|
}
|
|
498
777
|
if (!payload.data || typeof payload.data !== "object") {
|
|
499
|
-
throw new FetchContentfulError(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
);
|
|
778
|
+
throw new FetchContentfulError("Contentful returned no data and no errors.", {
|
|
779
|
+
code: "GRAPHQL",
|
|
780
|
+
query
|
|
781
|
+
});
|
|
503
782
|
}
|
|
504
783
|
return payload.data;
|
|
784
|
+
}
|
|
785
|
+
let mustIncludeQuery = !usePersistedQuery;
|
|
786
|
+
return withRetries(async () => {
|
|
787
|
+
if (mustIncludeQuery) {
|
|
788
|
+
return send(true);
|
|
789
|
+
}
|
|
790
|
+
try {
|
|
791
|
+
return await send(false);
|
|
792
|
+
} catch (error) {
|
|
793
|
+
if (isFetchContentfulError(error) && error.code === "GRAPHQL" && error.errors?.some(isPersistedQueryNotFoundError)) {
|
|
794
|
+
mustIncludeQuery = true;
|
|
795
|
+
return await send(true);
|
|
796
|
+
}
|
|
797
|
+
throw error;
|
|
798
|
+
}
|
|
505
799
|
}, context.retry);
|
|
506
800
|
}
|
|
507
801
|
|
|
@@ -515,7 +809,6 @@ function readEnvSettings() {
|
|
|
515
809
|
space: void 0,
|
|
516
810
|
environment: void 0,
|
|
517
811
|
deliveryToken: void 0,
|
|
518
|
-
token: void 0,
|
|
519
812
|
previewToken: void 0
|
|
520
813
|
};
|
|
521
814
|
}
|
|
@@ -530,7 +823,6 @@ function readEnvSettings() {
|
|
|
530
823
|
process.env.CONTENTFUL_ENVIRONMENT || process.env.NEXT_PUBLIC_CONTENTFUL_ENVIRONMENT
|
|
531
824
|
),
|
|
532
825
|
deliveryToken,
|
|
533
|
-
token: deliveryToken,
|
|
534
826
|
// No `NEXT_PUBLIC_` fallback: see the note at the top of this file.
|
|
535
827
|
previewToken: orUndefined(process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN)
|
|
536
828
|
};
|
|
@@ -572,20 +864,18 @@ function injectIntoField(field, args) {
|
|
|
572
864
|
return { ...field, arguments: [...argumentsOf(field), ...additions] };
|
|
573
865
|
}
|
|
574
866
|
function injectIntoSelectionSet(selectionSet, args) {
|
|
575
|
-
const selections = selectionSet.selections.map(
|
|
576
|
-
(selection)
|
|
577
|
-
|
|
578
|
-
return injectIntoField(selection, args);
|
|
579
|
-
}
|
|
580
|
-
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
581
|
-
return {
|
|
582
|
-
...selection,
|
|
583
|
-
selectionSet: injectIntoSelectionSet(selection.selectionSet, args)
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
return selection;
|
|
867
|
+
const selections = selectionSet.selections.map((selection) => {
|
|
868
|
+
if (selection.kind === Kind.FIELD) {
|
|
869
|
+
return injectIntoField(selection, args);
|
|
587
870
|
}
|
|
588
|
-
|
|
871
|
+
if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
872
|
+
return {
|
|
873
|
+
...selection,
|
|
874
|
+
selectionSet: injectIntoSelectionSet(selection.selectionSet, args)
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
return selection;
|
|
878
|
+
});
|
|
589
879
|
return { ...selectionSet, selections };
|
|
590
880
|
}
|
|
591
881
|
function injectRootArgs(document, args) {
|
|
@@ -626,27 +916,24 @@ async function fetchLocales(context) {
|
|
|
626
916
|
if (context.signal) init.signal = context.signal;
|
|
627
917
|
response = await context.fetch(localesEndpoint(context), init);
|
|
628
918
|
} catch (cause) {
|
|
629
|
-
throw new FetchContentfulError(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
919
|
+
throw new FetchContentfulError(`Network error while fetching locales: ${String(cause)}`, {
|
|
920
|
+
code: "NETWORK",
|
|
921
|
+
retryable: true,
|
|
922
|
+
cause
|
|
923
|
+
});
|
|
633
924
|
}
|
|
634
925
|
if (!response.ok) {
|
|
635
|
-
throw new FetchContentfulError(
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
retryable: response.status === 429 || response.status >= 500
|
|
641
|
-
}
|
|
642
|
-
);
|
|
926
|
+
throw new FetchContentfulError(`Locale request failed with HTTP ${response.status}.`, {
|
|
927
|
+
code: "HTTP",
|
|
928
|
+
status: response.status,
|
|
929
|
+
retryable: response.status === 429 || response.status >= 500
|
|
930
|
+
});
|
|
643
931
|
}
|
|
644
932
|
const payload = await response.json();
|
|
645
933
|
if (!Array.isArray(payload.items)) {
|
|
646
|
-
throw new FetchContentfulError(
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
);
|
|
934
|
+
throw new FetchContentfulError("Locale response did not include an items array.", {
|
|
935
|
+
code: "NETWORK"
|
|
936
|
+
});
|
|
650
937
|
}
|
|
651
938
|
return payload.items.map((item) => ({
|
|
652
939
|
code: item.code,
|
|
@@ -674,24 +961,22 @@ function clearLocaleCache() {
|
|
|
674
961
|
}
|
|
675
962
|
|
|
676
963
|
// src/shape.ts
|
|
677
|
-
var
|
|
678
|
-
function
|
|
964
|
+
var COLLECTION_SUFFIX3 = "Collection";
|
|
965
|
+
function isRecord3(value) {
|
|
679
966
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
680
967
|
}
|
|
681
|
-
function
|
|
682
|
-
return
|
|
968
|
+
function isCollectionValue2(value) {
|
|
969
|
+
return isRecord3(value) && Array.isArray(value["items"]);
|
|
683
970
|
}
|
|
684
971
|
function shapeData(data) {
|
|
685
972
|
if (Array.isArray(data)) {
|
|
686
973
|
return data.map((item) => shapeData(item));
|
|
687
974
|
}
|
|
688
|
-
if (
|
|
975
|
+
if (isRecord3(data)) {
|
|
689
976
|
const shaped = {};
|
|
690
977
|
for (const [key, value] of Object.entries(data)) {
|
|
691
|
-
if (key.endsWith(
|
|
692
|
-
shaped[key.slice(0, -
|
|
693
|
-
value.items
|
|
694
|
-
);
|
|
978
|
+
if (key.endsWith(COLLECTION_SUFFIX3) && key !== COLLECTION_SUFFIX3 && isCollectionValue2(value)) {
|
|
979
|
+
shaped[key.slice(0, -COLLECTION_SUFFIX3.length)] = shapeData(value.items);
|
|
695
980
|
} else {
|
|
696
981
|
shaped[key] = shapeData(value);
|
|
697
982
|
}
|
|
@@ -701,7 +986,7 @@ function shapeData(data) {
|
|
|
701
986
|
return data;
|
|
702
987
|
}
|
|
703
988
|
function unwrapSingleRoot(data) {
|
|
704
|
-
if (
|
|
989
|
+
if (isRecord3(data)) {
|
|
705
990
|
const keys = Object.keys(data);
|
|
706
991
|
if (keys.length === 1) {
|
|
707
992
|
return data[keys[0]];
|
|
@@ -716,7 +1001,9 @@ var DEFAULT_RETRIES = 5;
|
|
|
716
1001
|
var DEFAULT_RETRY_DELAY_MS = 250;
|
|
717
1002
|
var DEFAULT_MAX_RETRY_DELAY_MS = 8e3;
|
|
718
1003
|
var DEFAULT_SPLIT_BATCH_SIZE = 50;
|
|
719
|
-
|
|
1004
|
+
var DEFAULT_MAX_QUERY_SIZE = 7500;
|
|
1005
|
+
var DEFAULT_MAX_QUERY_SIZE_WITH_APQ = 15500;
|
|
1006
|
+
function isRecord4(value) {
|
|
720
1007
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
721
1008
|
}
|
|
722
1009
|
function collectAtPath(data, path) {
|
|
@@ -724,7 +1011,7 @@ function collectAtPath(data, path) {
|
|
|
724
1011
|
for (const segment of path) {
|
|
725
1012
|
const next = [];
|
|
726
1013
|
for (const value of current) {
|
|
727
|
-
if (
|
|
1014
|
+
if (isRecord4(value)) {
|
|
728
1015
|
const child = value[segment];
|
|
729
1016
|
if (Array.isArray(child)) {
|
|
730
1017
|
next.push(...child);
|
|
@@ -735,14 +1022,14 @@ function collectAtPath(data, path) {
|
|
|
735
1022
|
}
|
|
736
1023
|
current = next;
|
|
737
1024
|
}
|
|
738
|
-
return current.filter(
|
|
1025
|
+
return current.filter(isRecord4);
|
|
739
1026
|
}
|
|
740
1027
|
function resolveContext(options) {
|
|
741
1028
|
const env = readEnvSettings();
|
|
742
1029
|
const space = options.space ?? env.space;
|
|
743
1030
|
const environment = options.environment ?? env.environment ?? "master";
|
|
744
1031
|
const preview = options.preview ?? false;
|
|
745
|
-
const token = preview ? options.previewToken ??
|
|
1032
|
+
const token = preview ? options.previewToken ?? env.previewToken : options.deliveryToken ?? env.deliveryToken;
|
|
746
1033
|
if (!space || !token) {
|
|
747
1034
|
const missing = [];
|
|
748
1035
|
if (!space) {
|
|
@@ -766,6 +1053,7 @@ function resolveContext(options) {
|
|
|
766
1053
|
maxDelayMs: options.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS
|
|
767
1054
|
};
|
|
768
1055
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1056
|
+
const automaticPersistedQueries = options.automaticPersistedQueries ?? false;
|
|
769
1057
|
const context = {
|
|
770
1058
|
space,
|
|
771
1059
|
environment,
|
|
@@ -776,8 +1064,19 @@ function resolveContext(options) {
|
|
|
776
1064
|
fetch: fetchImpl,
|
|
777
1065
|
retry,
|
|
778
1066
|
autoSplitNestedCollections: options.autoSplitNestedCollections ?? true,
|
|
779
|
-
|
|
1067
|
+
autoSplitOnSize: options.autoSplitOnSize ?? true,
|
|
1068
|
+
// APQ lifts Contentful's size ceiling from 8 KB to 16 KB, so the budget
|
|
1069
|
+
// that triggers a size-driven split follows suit unless overridden.
|
|
1070
|
+
maxQuerySize: options.maxQuerySize ?? (automaticPersistedQueries ? DEFAULT_MAX_QUERY_SIZE_WITH_APQ : DEFAULT_MAX_QUERY_SIZE),
|
|
1071
|
+
splitBatchSize: options.splitBatchSize ?? DEFAULT_SPLIT_BATCH_SIZE,
|
|
1072
|
+
annotateQueryOnError: options.annotateQueryOnError ?? true,
|
|
1073
|
+
unresolvableLinks: options.unresolvableLinks ?? "omit",
|
|
1074
|
+
minifyQuery: options.minifyQuery ?? true,
|
|
1075
|
+
automaticPersistedQueries
|
|
780
1076
|
};
|
|
1077
|
+
if (options.onUnresolvableLink) {
|
|
1078
|
+
context.onUnresolvableLink = options.onUnresolvableLink;
|
|
1079
|
+
}
|
|
781
1080
|
if (options.signal) context.signal = options.signal;
|
|
782
1081
|
if (options.next) context.next = options.next;
|
|
783
1082
|
if (options.cache) context.cache = options.cache;
|
|
@@ -795,7 +1094,7 @@ async function resolvePlan(plan, data, variables, context) {
|
|
|
795
1094
|
for (const parent of relevant) {
|
|
796
1095
|
const typename = parent[TYPENAME_ALIAS];
|
|
797
1096
|
const sys = parent[SYS_ID_ALIAS];
|
|
798
|
-
if (!
|
|
1097
|
+
if (!isRecord4(sys) || typeof sys["id"] !== "string") {
|
|
799
1098
|
throw new FetchContentfulError(
|
|
800
1099
|
`Cannot split "${plan.responseKey}": a parent entry is missing its sys id.`,
|
|
801
1100
|
{ code: "STITCH" }
|
|
@@ -818,19 +1117,14 @@ async function resolvePlan(plan, data, variables, context) {
|
|
|
818
1117
|
];
|
|
819
1118
|
await Promise.all(
|
|
820
1119
|
chunk(ids, context.splitBatchSize).map(async (idBatch) => {
|
|
821
|
-
const { document, rootKey } = buildSubquery(
|
|
822
|
-
plan,
|
|
823
|
-
typename,
|
|
824
|
-
idBatch.length,
|
|
825
|
-
context
|
|
826
|
-
);
|
|
1120
|
+
const { document, rootKey } = buildSubquery(plan, typename, idBatch.length, context);
|
|
827
1121
|
const subData = await executeDocument(
|
|
828
1122
|
document,
|
|
829
1123
|
{ ...variables, _splitIds: idBatch },
|
|
830
1124
|
context
|
|
831
1125
|
);
|
|
832
1126
|
const collection = subData[rootKey];
|
|
833
|
-
const items =
|
|
1127
|
+
const items = isRecord4(collection) && Array.isArray(collection["items"]) ? collection["items"] : void 0;
|
|
834
1128
|
if (!items) {
|
|
835
1129
|
throw new FetchContentfulError(
|
|
836
1130
|
`Split subquery for "${typename}" returned no "${rootKey}.items". Check that the content type follows Contentful naming conventions.`,
|
|
@@ -838,9 +1132,9 @@ async function resolvePlan(plan, data, variables, context) {
|
|
|
838
1132
|
);
|
|
839
1133
|
}
|
|
840
1134
|
for (const item of items) {
|
|
841
|
-
if (
|
|
1135
|
+
if (isRecord4(item)) {
|
|
842
1136
|
const sys = item["sys"];
|
|
843
|
-
if (
|
|
1137
|
+
if (isRecord4(sys) && typeof sys["id"] === "string") {
|
|
844
1138
|
resolved.set(`${typename}:${sys["id"]}`, item[plan.responseKey]);
|
|
845
1139
|
}
|
|
846
1140
|
}
|
|
@@ -870,12 +1164,18 @@ function cleanupMarkers(data, plans) {
|
|
|
870
1164
|
}
|
|
871
1165
|
}
|
|
872
1166
|
}
|
|
1167
|
+
function byteLength(text) {
|
|
1168
|
+
return new TextEncoder().encode(text).length;
|
|
1169
|
+
}
|
|
873
1170
|
async function executeDocument(document, variables, context) {
|
|
874
|
-
const { document: outer, plans } =
|
|
1171
|
+
const { document: outer, plans } = planSplitsWithSizeBudget(document, {
|
|
1172
|
+
autoSplitNestedCollections: context.autoSplitNestedCollections,
|
|
1173
|
+
autoSplitOnSize: context.autoSplitOnSize,
|
|
1174
|
+
maxQuerySize: context.maxQuerySize,
|
|
1175
|
+
measure: (doc) => byteLength(printOutgoingQuery(doc, context))
|
|
1176
|
+
});
|
|
875
1177
|
const data = await rawRequest(outer, variables, context);
|
|
876
|
-
await Promise.all(
|
|
877
|
-
plans.map((plan) => resolvePlan(plan, data, variables, context))
|
|
878
|
-
);
|
|
1178
|
+
await Promise.all(plans.map((plan) => resolvePlan(plan, data, variables, context)));
|
|
879
1179
|
cleanupMarkers(data, plans);
|
|
880
1180
|
return data;
|
|
881
1181
|
}
|
|
@@ -889,10 +1189,10 @@ function toDocument(query) {
|
|
|
889
1189
|
try {
|
|
890
1190
|
return parse(typeof query === "string" ? query : String(query));
|
|
891
1191
|
} catch (cause) {
|
|
892
|
-
throw new FetchContentfulError(
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
);
|
|
1192
|
+
throw new FetchContentfulError(`Failed to parse GraphQL query: ${String(cause)}`, {
|
|
1193
|
+
code: "CONFIG",
|
|
1194
|
+
cause
|
|
1195
|
+
});
|
|
896
1196
|
}
|
|
897
1197
|
}
|
|
898
1198
|
function withAutoVariables(document, variables, context) {
|
|
@@ -928,13 +1228,10 @@ async function runFetchContentful(query, options) {
|
|
|
928
1228
|
);
|
|
929
1229
|
}
|
|
930
1230
|
}
|
|
931
|
-
const variables = withAutoVariables(
|
|
932
|
-
document,
|
|
933
|
-
options.variables ?? {},
|
|
934
|
-
context
|
|
935
|
-
);
|
|
1231
|
+
const variables = withAutoVariables(document, options.variables ?? {}, context);
|
|
936
1232
|
const data = await executeDocument(document, variables, context);
|
|
937
|
-
const
|
|
1233
|
+
const resolved = context.unresolvableLinks === "null" ? data : omitUnresolvedLinks(data);
|
|
1234
|
+
const result = options.shapeResponseData === false ? resolved : shapeData(resolved);
|
|
938
1235
|
if (options.unwrapRootField === false) {
|
|
939
1236
|
return result;
|
|
940
1237
|
}
|
|
@@ -954,6 +1251,6 @@ function createFetchContentful(defaults = {}) {
|
|
|
954
1251
|
}
|
|
955
1252
|
var index_default = fetchContentful;
|
|
956
1253
|
|
|
957
|
-
export { FetchContentfulError, clearLocaleCache, collectAtPath, createFetchContentful, index_default as default, fetchContentful, getLocales, injectRootArgs, inlineFragments, isFetchContentfulError, readEnvSettings, shapeData, unwrapSingleRoot };
|
|
1254
|
+
export { FetchContentfulError, UNRESOLVABLE_LINK_CODE, annotateQuery, clearLocaleCache, collectAtPath, createFetchContentful, index_default as default, fetchContentful, getLocales, injectRootArgs, inlineFragments, isFetchContentfulError, isUnresolvableLinkError, minifyQuery, omitUnresolvedLinks, partitionUnresolvableLinks, readEnvSettings, shapeData, unwrapSingleRoot };
|
|
958
1255
|
//# sourceMappingURL=index.mjs.map
|
|
959
1256
|
//# sourceMappingURL=index.mjs.map
|