@fourtwelvelabs/fetch-contentful 1.0.0 → 1.2.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 +32 -0
- package/README.md +37 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +144 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.mjs +145 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @fourtwelvelabs/fetch-contentful
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4712d22: Added three ways to stay under (or get past) Contentful's `QUERY_TOO_BIG` limit, and to opt into Automatic Persisted Queries.
|
|
8
|
+
|
|
9
|
+
**Every outgoing query is minified by default.** `graphql`'s `print()` is a pretty-printer — every level of nesting costs two bytes of indentation before a single field has been named, and Contentful's size limit counts that whitespace like anything else. Queries are now re-tokenized and rejoined with the least whitespace that keeps them distinct (the same idea as GQLMin), which is usually the single largest win available without touching a query's shape. Set `minifyQuery: false` to opt out — for example to read a request off the wire while debugging. `FetchContentfulError.query` and the annotated caret display always reflect whatever text was actually sent, minified or not.
|
|
10
|
+
|
|
11
|
+
**A new `autoSplitOnSize` option (default `true`) adds a static-size pass on top of existing query splitting.** Today's `autoSplitNestedCollections` and `@split` decide what to split by shape — every nested `*Collection` field, or whatever's explicitly annotated — regardless of whether the query actually needs it. The new pass instead measures the (minified) query exactly as it will be sent and, only if it's still over `maxQuerySize` (7500 bytes by default), peels off the single largest remaining field — one-to-one references included, not just collections — and re-measures, repeating until it fits or nothing splittable is left. A query that still doesn't fit at that point is sent as-is; Contentful's own `QUERY_TOO_BIG` is the accurate error to see, since there's nothing left for this pass to remove.
|
|
12
|
+
|
|
13
|
+
**A new `automaticPersistedQueries` option (default `false`) implements Contentful's APQ support.** The optimistic first attempt sends only a SHA-256 hash of the query; only the first time Contentful reports that hash unknown does the query text get sent (once), registering it for every request after. This is what actually raises Contentful's own size ceiling from 8 KB to 16 KB — `maxQuerySize` defaults to 15500 instead of 7500 whenever it's on — and it's off by default because it requires the Premium plan or above: on any other plan it would silently double every request's round trips for no benefit.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Fixed `automaticPersistedQueries` being unusable against real Contentful: the optimistic hash-only attempt never fell back to sending the query text, so every request failed and no hash ever registered.
|
|
18
|
+
|
|
19
|
+
The fallback was gated on the miss arriving as a GraphQL error (`code: 'GRAPHQL'`) — the shape Apollo Server uses to report an unregistered hash. Contentful's CDA instead answers with HTTP 404 (`code: 'HTTP'`), carrying the same `PersistedQueryNotFound` marker in the same `errors` shape. The gate now accepts the marker on either transport, matching what Apollo's spec actually guarantees (the marker) rather than what it doesn't (a status code).
|
|
20
|
+
|
|
21
|
+
Thanks to a report from a real Enterprise-plan user for the exact repro and root cause.
|
|
22
|
+
|
|
23
|
+
## 1.1.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- 4712d22: Added three ways to stay under (or get past) Contentful's `QUERY_TOO_BIG` limit, and to opt into Automatic Persisted Queries.
|
|
28
|
+
|
|
29
|
+
**Every outgoing query is minified by default.** `graphql`'s `print()` is a pretty-printer — every level of nesting costs two bytes of indentation before a single field has been named, and Contentful's size limit counts that whitespace like anything else. Queries are now re-tokenized and rejoined with the least whitespace that keeps them distinct (the same idea as GQLMin), which is usually the single largest win available without touching a query's shape. Set `minifyQuery: false` to opt out — for example to read a request off the wire while debugging. `FetchContentfulError.query` and the annotated caret display always reflect whatever text was actually sent, minified or not.
|
|
30
|
+
|
|
31
|
+
**A new `autoSplitOnSize` option (default `true`) adds a static-size pass on top of existing query splitting.** Today's `autoSplitNestedCollections` and `@split` decide what to split by shape — every nested `*Collection` field, or whatever's explicitly annotated — regardless of whether the query actually needs it. The new pass instead measures the (minified) query exactly as it will be sent and, only if it's still over `maxQuerySize` (7500 bytes by default), peels off the single largest remaining field — one-to-one references included, not just collections — and re-measures, repeating until it fits or nothing splittable is left. A query that still doesn't fit at that point is sent as-is; Contentful's own `QUERY_TOO_BIG` is the accurate error to see, since there's nothing left for this pass to remove.
|
|
32
|
+
|
|
33
|
+
**A new `automaticPersistedQueries` option (default `false`) implements Contentful's APQ support.** The optimistic first attempt sends only a SHA-256 hash of the query; only the first time Contentful reports that hash unknown does the query text get sent (once), registering it for every request after. This is what actually raises Contentful's own size ceiling from 8 KB to 16 KB — `maxQuerySize` defaults to 15500 instead of 7500 whenever it's on — and it's off by default because it requires the Premium plan or above: on any other plan it would silently double every request's round trips for no benefit.
|
|
34
|
+
|
|
3
35
|
## 1.0.0
|
|
4
36
|
|
|
5
37
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
A foolproof, type-safe GraphQL fetching utility for Contentful. One function in, shaped data out:
|
|
4
4
|
|
|
5
5
|
- **Automatic query splitting** — nested reference collections (and `@split`-annotated one-to-one references) are broken into separate subqueries, fetched in id batches, and stitched back into the original response shape. Fully recursive, so deeply nested queries never hit Contentful's query complexity limit.
|
|
6
|
+
- **Automatic query minification** — every outgoing query has its insignificant whitespace stripped before it's sent, which is usually the single biggest lever against Contentful's `QUERY_TOO_BIG` limit. Combined with a static-size pass (`autoSplitOnSize`, on by default) that splits off more fields only when a query still measures too big, and optional support for Automatic Persisted Queries. See [Staying under the query size limit](#staying-under-the-query-size-limit).
|
|
6
7
|
- **Automatic retries** — transient failures (network errors, 408/429/5xx) retry with exponential backoff + jitter, honoring `Retry-After`. Configurable, default 5.
|
|
7
8
|
- **Response shaping (built in)** — before the promise resolves, every `fooCollection.items` in the response becomes `foo` (a plain array), at runtime _and_ in the return type. No separate call needed.
|
|
8
9
|
- **Single-root unwrapping (built in)** — when a query has one root field, the promise resolves with that field's contents directly (`data` _is_ the array/entry, not `{ siteSettings: ... }`). Multi-root queries stay wrapped.
|
|
@@ -253,7 +254,14 @@ fetchContentful(query, {
|
|
|
253
254
|
autoInjectArgs: true, // inject preview/locale args on root fields
|
|
254
255
|
autoSplitNestedCollections: true, // auto-detect non-root *Collection fields
|
|
255
256
|
// (@split works regardless — see below)
|
|
256
|
-
splitBatchSize: 50 // parent ids per subquery
|
|
257
|
+
splitBatchSize: 50, // parent ids per subquery
|
|
258
|
+
|
|
259
|
+
// Query size
|
|
260
|
+
minifyQuery: true, // strip insignificant whitespace before sending
|
|
261
|
+
autoSplitOnSize: true, // split further if the query still measures too big
|
|
262
|
+
maxQuerySize: 7500, // byte budget that triggers autoSplitOnSize
|
|
263
|
+
// (15500 by default when automaticPersistedQueries is on — see below)
|
|
264
|
+
automaticPersistedQueries: false // requires the Premium plan or above
|
|
257
265
|
});
|
|
258
266
|
```
|
|
259
267
|
|
|
@@ -462,6 +470,32 @@ query {
|
|
|
462
470
|
|
|
463
471
|
A root field has no parent entry to stitch its result back onto, so there is nothing for the directive to do. Reach for `limit` and `skip` on the field itself instead. (Before 0.2.1 the directive was silently stripped here — if an existing query relies on that, remove the directive.)
|
|
464
472
|
|
|
473
|
+
## Staying under the query size limit
|
|
474
|
+
|
|
475
|
+
Separately from the complexity limit that query splitting exists for, Contentful also rejects a query whose **text** — whitespace and newlines included — exceeds [8 KB](https://www.contentful.com/developers/docs/references/graphql/overview/#query-size-limits) with a `QUERY_TOO_BIG` error. Three settings work together to avoid it, all on by default except the last:
|
|
476
|
+
|
|
477
|
+
1. **`minifyQuery` (default `true`)** — every outgoing query is re-tokenized and rejoined with the least whitespace that keeps it valid, the same effect a tool like [GQLMin](https://github.com/drwpow/gqlmin) has. `graphql`'s pretty-printer spends two bytes of indentation per level of nesting before naming a single field, so this is usually the single biggest lever available, and it changes nothing about what the query asks for. Disable it only to read a request off the wire while debugging — `FetchContentfulError.query` and the annotated caret display always show whatever text was actually sent, so turning it off does not lose any diagnostic power.
|
|
478
|
+
|
|
479
|
+
2. **`autoSplitOnSize` (default `true`)** — a static-size pass that runs after ordinary query splitting. `autoSplitNestedCollections` and `@split` decide what to split by a query's *shape*: every nested `*Collection` field, or whatever's explicitly annotated, whether or not the query actually needs the help. This pass instead measures the query exactly as it will be sent and, only when it's still over `maxQuerySize`, peels off the single largest remaining field — a one-to-one reference works exactly as well as a collection — and re-measures, repeating until it fits or nothing splittable is left. A query that still doesn't fit at that point is sent as-is: Contentful's own `QUERY_TOO_BIG` is the accurate error to see, since there's nothing left for this library to remove.
|
|
480
|
+
|
|
481
|
+
```ts
|
|
482
|
+
const data = await fetchContentful(QUERY, {
|
|
483
|
+
maxQuerySize: 6000 // lower the default 7500-byte budget
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
3. **`automaticPersistedQueries` (default `false`)** — implements Contentful's [Automatic Persisted Queries](https://www.contentful.com/developers/docs/references/graphql/automatic-persisted-queries/) support, adopted from Apollo's spec. The optimistic first attempt sends only a SHA-256 hash of the query in `extensions`, with no `query` field at all; only the first time Contentful reports that hash unknown does the query text get sent (once, alongside the hash, which registers it). Every request after that — from this process or any other client — hits on the hash alone. This is what actually raises Contentful's ceiling from 8 KB to 16 KB, which is why `maxQuerySize` defaults to `15500` instead of `7500` whenever this is on.
|
|
488
|
+
|
|
489
|
+
**Requires the Premium plan or above.** On any other plan every request would silently cost two round trips forever instead of one, which is why this defaults to `false` rather than detecting the plan automatically — there is no API to check it from the client.
|
|
490
|
+
|
|
491
|
+
```ts
|
|
492
|
+
const data = await fetchContentful(QUERY, {
|
|
493
|
+
automaticPersistedQueries: true
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
None of this touches `autoSplitNestedCollections` or `@split`, which remain about the complexity limit, not the size limit — a query can be simple enough to never need splitting and still be big enough (long field lists, deep `where` filters) to trip `QUERY_TOO_BIG`, which is exactly the case `autoSplitOnSize` exists for.
|
|
498
|
+
|
|
465
499
|
## Error handling
|
|
466
500
|
|
|
467
501
|
Every rejection is a `FetchContentfulError`:
|
|
@@ -534,6 +568,7 @@ import {
|
|
|
534
568
|
injectRootArgs, // the preview/locale argument injector (advanced AST use)
|
|
535
569
|
inlineFragments, // fragment inliner (advanced AST use)
|
|
536
570
|
isUnresolvableLinkError, // classify one GraphQL error as a broken link
|
|
571
|
+
minifyQuery, // the whitespace minifier (already applied by fetchContentful)
|
|
537
572
|
omitUnresolvedLinks, // the runtime null-position dropper (applied too)
|
|
538
573
|
partitionUnresolvableLinks, // split an errors array into broken links vs the rest
|
|
539
574
|
shapeData, // the runtime collection shaper (already applied by fetchContentful)
|
|
@@ -555,6 +590,7 @@ import type { ContentfulScalars, JsonValue } from '@fourtwelvelabs/fetch-content
|
|
|
555
590
|
- Splitting relies on Contentful's naming conventions: a parent of type `BlogPost` must be re-queryable via `blogPostCollection`. Custom schemas that break this convention will fail with a `STITCH` error rather than return wrong data.
|
|
556
591
|
- Root-level collections are never split (there is no parent to stitch onto); only nested ones are.
|
|
557
592
|
- `@split`/auto-split fields inside `... on Entry { ... }` fragments are treated as unconditional, since `Entry` is an interface and never matches a concrete `__typename`.
|
|
593
|
+
- `autoSplitOnSize` picks candidates by measured size, not by name, so it can choose a field whose parent type does not follow Contentful's `blogPostCollection` naming convention — the same `STITCH` error above, just reached automatically rather than by writing `@split` yourself.
|
|
558
594
|
|
|
559
595
|
## Development
|
|
560
596
|
|
package/dist/cli/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/env.ts","../../src/cli/errors.ts","../../src/cli/args.ts","../../src/cli/diff.ts","../../src/cli/env-file.ts","../../src/cli/graphql-module.ts","../../src/client.ts","../../src/cli/introspect.ts","../../src/cli/package-manager.ts","../../src/cli/jsonc.ts","../../src/cli/tsconfig.ts","../../src/cli/run.ts","../../src/cli/index.ts"],"names":["existsSync","readFileSync","indent","resolve","relative","dirname"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Environment-derived configuration.\n *\n * Two families of variable names are supported, checked in this order:\n *\n * 1. Framework-neutral names — `CONTENTFUL_SPACE_ID`, `CONTENTFUL_ENVIRONMENT`,\n * `CONTENTFUL_ACCESS_TOKEN`, `CONTENTFUL_PREVIEW_ACCESS_TOKEN`.\n * 2. `NEXT_PUBLIC_`-prefixed equivalents for Next.js projects that call\n * Contentful from the browser — for the space, the environment and the\n * **delivery** token only.\n *\n * The preview token is deliberately absent from that second family. Next.js\n * inlines `NEXT_PUBLIC_` variables into client bundles by string-replacing\n * the literal accesses below, so merely importing this module in a project\n * that set `NEXT_PUBLIC_CONTENTFUL_PREVIEW_ACCESS_TOKEN` would bake the\n * token into public JavaScript — whether or not any client code ever asks\n * for preview content. A delivery token is read-only and commonly public; a\n * preview token reads unpublished content and must not leak. Callers that\n * genuinely need preview in the browser pass `previewToken` explicitly, so\n * the exposure is their deliberate choice rather than this module's.\n *\n * IMPORTANT: every lookup below is written as a literal\n * `process.env.SOME_NAME` property access, never a dynamic `process.env[x]`.\n * Next.js exposes `NEXT_PUBLIC_` variables to client bundles by\n * string-replacing those literal expressions at build time — dynamic access\n * is invisible to the inliner and resolves to `undefined` in the browser.\n * Do not \"refactor\" these into a loop or a name table.\n *\n * This module reads the already-populated `process.env`; loading `.env`\n * files from disk is deliberately left to the platform (Next.js, Vite,\n * dotenv, ...), whose precedence rules would otherwise be duplicated here.\n */\n\n/*\n * These variables are read at runtime inside the consuming application, not\n * while this package is built — the bundle ships the literal `process.env.X`\n * accesses untouched. Declaring them in turbo.json would therefore be\n * inaccurate and would invalidate the build cache for no reason.\n */\n/* eslint-disable turbo/no-undeclared-env-vars */\n\nexport interface EnvSettings {\n space: string | undefined;\n environment: string | undefined;\n /** Content Delivery API token, for published content. */\n deliveryToken: string | undefined;\n /** Content Preview API token, for draft content. Server-side only. */\n previewToken: string | undefined;\n}\n\nfunction orUndefined(value: string | undefined): string | undefined {\n return value || undefined;\n}\n\n/** Reads Contentful settings from `process.env` (neutral names first). */\nexport function readEnvSettings(): EnvSettings {\n /* v8 ignore next 10 -- process always exists in the test runtime */\n if (typeof process === 'undefined' || !process.env) {\n return {\n space: undefined,\n environment: undefined,\n deliveryToken: undefined,\n previewToken: undefined\n };\n }\n const deliveryToken = orUndefined(\n process.env.CONTENTFUL_ACCESS_TOKEN || process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN\n );\n return {\n space: orUndefined(\n process.env.CONTENTFUL_SPACE_ID || process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID\n ),\n environment: orUndefined(\n process.env.CONTENTFUL_ENVIRONMENT || process.env.NEXT_PUBLIC_CONTENTFUL_ENVIRONMENT\n ),\n deliveryToken,\n // No `NEXT_PUBLIC_` fallback: see the note at the top of this file.\n previewToken: orUndefined(process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN)\n };\n}\n","/**\n * An expected CLI failure: printed as a plain message with exit code 1,\n * never as a stack trace.\n */\nexport class CliError extends Error {\n override name = 'CliError';\n}\n\n/**\n * Removes an access token from text that is about to be printed.\n *\n * Contentful echoes request details in some error bodies, and a token\n * pasted into a bug report is a token that has to be rotated.\n */\nexport function redact(text: string, token: string | undefined): string {\n if (!token) return text;\n return text.split(token).join('[redacted]');\n}\n","/**\n * A tiny `process.argv` parser.\n *\n * `node:util`'s `parseArgs` would do, but it prints an experimental warning\n * on Node 18 — which this package still supports — and that warning would\n * land in the middle of the CLI's output.\n */\n\nimport { CliError } from './errors.js';\n\n/** Flags that take no value. */\nexport const BOOLEAN_FLAGS = ['dry-run', 'force', 'help'] as const;\n\n/** Flags that take a value. */\nexport const VALUE_FLAGS = [\n 'space',\n 'environment',\n 'token',\n 'schema-path',\n 'tada-output',\n 'graphql-file',\n 'tsconfig',\n 'cwd',\n 'env-file'\n] as const;\n\nexport interface ParsedArgs {\n /** Positional arguments, e.g. `['tada-init']`. */\n positionals: string[];\n values: Partial<Record<(typeof VALUE_FLAGS)[number], string>>;\n flags: Set<(typeof BOOLEAN_FLAGS)[number]>;\n}\n\nfunction isBooleanFlag(name: string): name is (typeof BOOLEAN_FLAGS)[number] {\n return (BOOLEAN_FLAGS as readonly string[]).includes(name);\n}\n\nfunction isValueFlag(name: string): name is (typeof VALUE_FLAGS)[number] {\n return (VALUE_FLAGS as readonly string[]).includes(name);\n}\n\n/** Parses `argv` (already stripped of `node` and the script path). */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const parsed: ParsedArgs = {\n positionals: [],\n values: {},\n flags: new Set()\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] as string;\n\n if (argument === '-h') {\n parsed.flags.add('help');\n continue;\n }\n\n if (!argument.startsWith('--')) {\n parsed.positionals.push(argument);\n continue;\n }\n\n const equals = argument.indexOf('=');\n const name = argument.slice(2, equals === -1 ? undefined : equals);\n const inlineValue = equals === -1 ? undefined : argument.slice(equals + 1);\n\n if (isBooleanFlag(name)) {\n if (inlineValue !== undefined) {\n throw new CliError(`--${name} does not take a value.`);\n }\n parsed.flags.add(name);\n continue;\n }\n\n if (!isValueFlag(name)) {\n throw new CliError(`Unknown option \"--${name}\".`);\n }\n\n const value = inlineValue ?? argv[++index];\n if (value === undefined) {\n throw new CliError(`--${name} needs a value.`);\n }\n parsed.values[name] = value;\n }\n\n return parsed;\n}\n","/**\n * A line diff for `--dry-run` output.\n *\n * Only ever used on hand-sized files (a tsconfig, a generated module), so a\n * plain quadratic LCS is the right trade for having no dependency.\n */\n\nconst MAX_LINES = 400;\n\n/** Length of the longest common subsequence, as a DP table. */\nfunction lcsTable(before: string[], after: string[]): number[][] {\n const table: number[][] = Array.from({ length: before.length + 1 }, () =>\n new Array<number>(after.length + 1).fill(0)\n );\n for (let i = before.length - 1; i >= 0; i -= 1) {\n for (let j = after.length - 1; j >= 0; j -= 1) {\n const row = table[i] as number[];\n const next = table[i + 1] as number[];\n row[j] =\n before[i] === after[j]\n ? (next[j + 1] as number) + 1\n : Math.max(next[j] as number, row[j + 1] as number);\n }\n }\n return table;\n}\n\n/**\n * Renders `before` → `after` as `-`/`+`/` `-prefixed lines.\n *\n * Not a `patch(1)`-compatible unified diff — there are no hunk headers, and\n * unchanged lines are all kept — but it reads the same way and is enough to\n * see exactly what a run would change.\n */\nexport function lineDiff(before: string, after: string): string[] {\n if (before === after) return [];\n\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n\n if (beforeLines.length + afterLines.length > MAX_LINES * 2) {\n return [\n ` (${String(beforeLines.length)} lines → ${String(\n afterLines.length\n )} lines; too large to diff)`\n ];\n }\n\n const table = lcsTable(beforeLines, afterLines);\n const output: string[] = [];\n let i = 0;\n let j = 0;\n\n while (i < beforeLines.length && j < afterLines.length) {\n if (beforeLines[i] === afterLines[j]) {\n output.push(` ${beforeLines[i] as string}`);\n i += 1;\n j += 1;\n } else if (\n ((table[i + 1] as number[])[j] as number) >= ((table[i] as number[])[j + 1] as number)\n ) {\n output.push(` - ${beforeLines[i] as string}`);\n i += 1;\n } else {\n output.push(` + ${afterLines[j] as string}`);\n j += 1;\n }\n }\n while (i < beforeLines.length) {\n output.push(` - ${beforeLines[i] as string}`);\n i += 1;\n }\n while (j < afterLines.length) {\n output.push(` + ${afterLines[j] as string}`);\n j += 1;\n }\n\n return output;\n}\n\n/** Formats a byte count for humans. */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${String(bytes)} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} kB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","/**\n * `.env` file loading, for the CLI only.\n *\n * The library deliberately never reads the disk: doing so would break\n * bundlers and edge runtimes, and every platform (Next.js, Vite, dotenv)\n * already owns that job at runtime, with its own precedence rules.\n *\n * A CLI is a different situation. It runs from a shell, before anything has\n * populated `process.env` — and a Next.js project keeps its Contentful\n * credentials in `.env.local`, which Next reads only when Next itself boots.\n * Without this module the CLI would report the credentials missing while\n * they sit in a file two lines away.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { CliError } from './errors.js';\n\n/** Files checked when `--env-file` is not given, in precedence order. */\nexport const ENV_FILES = ['.env.local', '.env'] as const;\n\nconst ASSIGNMENT = /^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/;\n\n/**\n * Parses `.env` contents into key/value pairs.\n *\n * Covers the syntax these files actually use: comments, blank lines, an\n * optional `export` prefix, and single- or double-quoted values (`\\n` is\n * unescaped inside double quotes only). Multi-line values are not supported\n * — no Contentful credential needs one.\n */\nexport function parseEnvFile(source: string): Record<string, string> {\n const values: Record<string, string> = {};\n\n for (const rawLine of source.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === '' || line.startsWith('#')) continue;\n\n const match = ASSIGNMENT.exec(line);\n if (!match) continue;\n\n const key = match[1] as string;\n let value = (match[2] as string).trim();\n\n const quote = value[0];\n if ((quote === '\"' || quote === \"'\") && value.length > 1 && value.endsWith(quote)) {\n value = value.slice(1, -1);\n if (quote === '\"') value = value.replace(/\\\\n/g, '\\n');\n } else {\n // An unquoted value ends at an inline comment. The `#` has to be\n // preceded by whitespace, so a `#` inside a token is left alone.\n const comment = value.search(/\\s#/);\n if (comment !== -1) value = value.slice(0, comment).trimEnd();\n }\n\n values[key] = value;\n }\n\n return values;\n}\n\nexport interface EnvFileLoad {\n /** Directory the files were looked for in. */\n directory: string;\n /** Files that were read, in the order they were applied. */\n files: string[];\n /** Variables this load actually set. */\n applied: string[];\n}\n\n/**\n * Reads `.env.local` and `.env` (or one explicit file) into `process.env`.\n *\n * Nothing already present in the environment is overwritten, so a real\n * exported variable — and therefore anything a CI system or a shell sets —\n * still wins over a file. An empty value counts as absent, matching how the\n * library treats blank variables everywhere else.\n */\nexport function loadEnvFiles(directory: string, explicit?: string): EnvFileLoad {\n const load: EnvFileLoad = { directory, files: [], applied: [] };\n\n if (explicit !== undefined && !existsSync(resolve(directory, explicit))) {\n throw new CliError(`No env file at ${explicit}.`);\n }\n\n for (const candidate of explicit === undefined ? ENV_FILES : [explicit]) {\n const path = resolve(directory, candidate);\n if (!existsSync(path)) continue;\n\n load.files.push(candidate);\n for (const [key, value] of Object.entries(parseEnvFile(readFileSync(path, 'utf8')))) {\n if (!process.env[key]) {\n process.env[key] = value;\n load.applied.push(key);\n }\n }\n }\n\n return load;\n}\n\n/** A sentence explaining where the CLI looked for configuration. */\nexport function describeEnvFiles(load: EnvFileLoad): string {\n if (load.files.length === 0) {\n return (\n `No ${ENV_FILES.join(' or ')} file was found in ${load.directory}, ` +\n 'so only the shell environment was read. Point at one with --env-file ' +\n 'if it lives elsewhere.'\n );\n }\n return (\n `Read ${load.files.join(' and ')}; anything already set in the ` +\n 'environment takes precedence over them.'\n );\n}\n","/**\n * Renders the `graphql.ts` module that binds gql.tada to the space's\n * introspection output and Contentful's scalar map.\n */\n\nimport { dirname, relative, sep } from 'node:path';\n\n/** The published package name, used in the generated import. */\nexport const PACKAGE_NAME = '@fourtwelvelabs/fetch-contentful';\n\n/**\n * The path of `toFile` as seen from the directory holding `fromFile`,\n * always relative and always POSIX-separated — the form both an `import`\n * specifier and a tsconfig plugin path want.\n */\nexport function relativeSpecifier(fromFile: string, toFile: string): string {\n const path = relative(dirname(fromFile), toFile).split(sep).join('/');\n return path.startsWith('.') ? path : `./${path}`;\n}\n\n/**\n * The contents of the generated `graphql.ts`.\n *\n * `introspectionImport` is the specifier for gql.tada's generated types —\n * kept with its `.d.ts` extension, which is gql.tada's own convention.\n */\nexport function renderGraphqlModule(introspectionImport: string): string {\n return `/**\n * gql.tada, bound to this space's schema.\n *\n * Generated by \\`fetch-contentful tada-init\\`. Safe to edit and to commit;\n * re-running \\`tada-init\\` will not overwrite it without \\`--force\\`.\n *\n * Refresh the schema after a content-model change with:\n * fetch-contentful tada-refresh\n */\nimport { initGraphQLTada } from 'gql.tada';\nimport type { ContentfulScalars } from '${PACKAGE_NAME}/tada';\nimport type { introspection } from '${introspectionImport}';\n\nexport const graphql = initGraphQLTada<{\n introspection: introspection;\n scalars: ContentfulScalars;\n}>();\n\nexport { readFragment } from 'gql.tada';\nexport type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada';\n`;\n}\n","import { print, type DocumentNode } from 'graphql';\nimport { annotateQuery } from './annotate.js';\nimport { FetchContentfulError } from './errors.js';\nimport { withRetries, type RetryConfig } from './retry.js';\nimport { getOperation, stripInternalDirectives } from './split.js';\nimport type {\n ContentfulGraphQLError,\n GraphQLVariables,\n NextFetchOptions,\n UnresolvableLinkMode\n} from './types.js';\nimport { partitionUnresolvableLinks } from './unresolvable.js';\n\nexport interface RequestContext {\n space: string;\n environment: string;\n token: string;\n fetch: typeof fetch;\n retry: RetryConfig;\n signal?: AbortSignal;\n next?: NextFetchOptions;\n cache?: RequestCache;\n /** Append the annotated query to error messages. Defaults to `true`. */\n annotateQueryOnError?: boolean;\n /**\n * How to treat an `UNRESOLVABLE_LINK` error. Anything but `'error'` lets\n * the partial response through. Defaults to `'omit'`.\n */\n unresolvableLinks?: UnresolvableLinkMode;\n /** Notified of the unresolvable links a tolerated response carried. */\n onUnresolvableLink?: (errors: ContentfulGraphQLError[]) => void;\n}\n\nexport function graphqlEndpoint(space: string, environment: string): string {\n return `https://graphql.contentful.com/content/v1/spaces/${encodeURIComponent(\n space\n )}/environments/${encodeURIComponent(environment)}`;\n}\n\n/** Parse a Retry-After header (seconds or HTTP date) into milliseconds. */\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) {\n return Math.max(0, seconds * 1000);\n }\n const date = Date.parse(header);\n if (Number.isFinite(date)) {\n return Math.max(0, date - Date.now());\n }\n return undefined;\n}\n\n/** Keep only the variables the document actually declares. */\nexport function pickDeclaredVariables(\n document: DocumentNode,\n variables: GraphQLVariables\n): GraphQLVariables {\n const declared = new Set(\n (getOperation(document).variableDefinitions ?? []).map(\n (definition) => definition.variable.name.value\n )\n );\n const picked: GraphQLVariables = {};\n for (const [name, value] of Object.entries(variables)) {\n if (declared.has(name)) {\n picked[name] = value;\n }\n }\n return picked;\n}\n\nfunction isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || status >= 500;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Hands the tolerated unresolvable links to the caller's reporter.\n *\n * Anything it throws is swallowed deliberately. This sits inside the retry\n * loop, so a reporter that failed would not merely surface as the fetch's\n * rejection — it would look like a failed request and send the very same\n * query again.\n */\nfunction reportUnresolvableLinks(errors: ContentfulGraphQLError[], context: RequestContext): void {\n if (!context.onUnresolvableLink) return;\n try {\n context.onUnresolvableLink(errors);\n } catch {\n // See above: a logger must not be able to fail — or repeat — a fetch.\n }\n}\n\n/**\n * Reads the `errors` array out of a failed response body.\n *\n * Contentful answers a query it cannot validate with HTTP 400 and the very\n * same error objects a 200 would have carried, locations included — so the\n * status alone is the least useful half of what it just told us.\n */\nasync function readGraphQLErrors(\n response: Response\n): Promise<ContentfulGraphQLError[] | undefined> {\n try {\n const payload = (await response.json()) as {\n errors?: ContentfulGraphQLError[];\n } | null;\n const errors = payload?.errors;\n return Array.isArray(errors) && errors.length > 0 ? errors : undefined;\n } catch {\n // A body that is not JSON tells us nothing the status has not already.\n return undefined;\n }\n}\n\n/**\n * Builds the message for a failure Contentful explained: the summary, the\n * messages themselves, and — when any of them says where in the query it\n * went wrong — that query with a caret under the spot.\n */\nfunction describeFailure(\n summary: string,\n errors: ContentfulGraphQLError[] | undefined,\n query: string,\n context: RequestContext\n): string {\n if (!errors || errors.length === 0) return summary;\n const message = `${summary} ${errors.map((error) => error.message).join('; ')}`;\n if (context.annotateQueryOnError === false) return message;\n const annotated = annotateQuery(query, errors);\n // The trailing newline keeps the stack trace off the last caret line.\n return annotated ? `${message}\\n\\n${annotated}\\n` : message;\n}\n\n/**\n * Sends one GraphQL request (with retries) and returns `data`.\n *\n * Rejects with a {@link FetchContentfulError} on any HTTP, network, or\n * GraphQL error. The one exception is a partial response whose only\n * complaint is an unresolvable link: that data is returned, with the holes\n * still in it, for `omitUnresolvedLinks` to clean up once the full response\n * (subqueries included) has been stitched together.\n */\nexport async function rawRequest(\n document: DocumentNode,\n variables: GraphQLVariables,\n context: RequestContext\n): Promise<Record<string, unknown>> {\n const query = print(stripInternalDirectives(document));\n const body = JSON.stringify({\n query,\n variables: pickDeclaredVariables(document, variables)\n });\n const url = graphqlEndpoint(context.space, context.environment);\n\n return withRetries(async () => {\n let response: Response;\n try {\n const init: RequestInit & { next?: NextFetchOptions } = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${context.token}`\n },\n body\n };\n if (context.signal) init.signal = context.signal;\n if (context.cache) init.cache = context.cache;\n if (context.next) init.next = context.next;\n response = await context.fetch(url, init);\n } catch (cause) {\n throw new FetchContentfulError(\n `Network error while contacting Contentful: ${String(cause)}`,\n { code: 'NETWORK', query, retryable: true, cause }\n );\n }\n\n if (!response.ok) {\n const retryable = isRetryableStatus(response.status);\n // Only a rejected request has a query to explain; a 5xx body is a\n // server-side failure with nothing to point at, and this one is on\n // its way to another attempt anyway.\n const errors = retryable ? undefined : await readGraphQLErrors(response);\n throw new FetchContentfulError(\n describeFailure(\n `Contentful responded with HTTP ${response.status}.`,\n errors,\n query,\n context\n ),\n {\n code: 'HTTP',\n status: response.status,\n errors,\n query,\n retryable,\n retryAfterMs: retryable ? parseRetryAfter(response.headers.get('Retry-After')) : undefined\n }\n );\n }\n\n let payload: {\n data?: Record<string, unknown> | null;\n errors?: ContentfulGraphQLError[];\n };\n try {\n payload = (await response.json()) as typeof payload;\n } catch (cause) {\n throw new FetchContentfulError('Contentful returned an unreadable response body.', {\n code: 'NETWORK',\n query,\n retryable: true,\n cause\n });\n }\n\n if (payload.errors && payload.errors.length > 0) {\n // A response can be both errored and correct: an unresolvable link\n // reports content that is missing, not a query that was wrong, and\n // everything else Contentful sent is exactly what was asked for. It is\n // tolerated only when it is the *sole* complaint and there is data to\n // keep — a validation error alongside it means the query itself was\n // never answered, and the whole list goes into the rejection.\n const { unresolvable, fatal } = partitionUnresolvableLinks(payload.errors);\n const tolerable =\n context.unresolvableLinks !== 'error' &&\n fatal.length === 0 &&\n unresolvable.length > 0 &&\n isRecord(payload.data);\n\n if (!tolerable) {\n throw new FetchContentfulError(\n describeFailure('Contentful returned GraphQL errors:', payload.errors, query, context),\n { code: 'GRAPHQL', errors: payload.errors, query }\n );\n }\n reportUnresolvableLinks(unresolvable, context);\n }\n\n if (!payload.data || typeof payload.data !== 'object') {\n throw new FetchContentfulError('Contentful returned no data and no errors.', {\n code: 'GRAPHQL',\n query\n });\n }\n\n return payload.data;\n }, context.retry);\n}\n","/**\n * Downloads a space's GraphQL schema as SDL.\n *\n * This is the one network operation the CLI performs, and the only step\n * `tada-refresh` runs.\n */\n\nimport {\n buildClientSchema,\n getIntrospectionQuery,\n printSchema,\n type IntrospectionQuery\n} from 'graphql';\nimport { graphqlEndpoint } from '../client.js';\nimport { CliError, redact } from './errors.js';\n\nexport interface IntrospectOptions {\n space: string;\n environment: string;\n token: string;\n fetch: typeof fetch;\n}\n\n/** Trims a response body down to something safe to show in a terminal. */\nfunction bodySnippet(body: string, token: string): string {\n const cleaned = redact(body, token).trim();\n if (cleaned === '') return '(empty response body)';\n return cleaned.length > 300 ? `${cleaned.slice(0, 300)}…` : cleaned;\n}\n\n/**\n * Runs an introspection query against Contentful and returns the schema\n * printed as SDL, with a trailing newline.\n */\nexport async function fetchSchemaSdl(options: IntrospectOptions): Promise<string> {\n const url = graphqlEndpoint(options.space, options.environment);\n\n let response: Response;\n try {\n response = await options.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${options.token}`\n },\n body: JSON.stringify({ query: getIntrospectionQuery() })\n });\n } catch (cause) {\n throw new CliError(\n `Could not reach Contentful at ${url}: ${redact(String(cause), options.token)}`\n );\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new CliError(\n `Contentful rejected the access token (HTTP ${String(response.status)}).\\n` +\n ` Check that the token is a Content Delivery API token for space ` +\n `\"${options.space}\", and that it has access to environment ` +\n `\"${options.environment}\".`\n );\n }\n\n if (!response.ok) {\n const body = bodySnippet(await response.text().catch(() => ''), options.token);\n throw new CliError(`Contentful responded with HTTP ${String(response.status)}.\\n ${body}`);\n }\n\n let payload: {\n data?: IntrospectionQuery;\n errors?: Array<{ message?: string }>;\n };\n try {\n payload = (await response.json()) as typeof payload;\n } catch {\n throw new CliError('Contentful returned an unreadable response body.');\n }\n\n if (payload.errors && payload.errors.length > 0) {\n const messages = payload.errors.map((error) => error.message ?? 'unknown error').join('; ');\n throw new CliError(\n `Contentful returned GraphQL errors during introspection: ${redact(messages, options.token)}`\n );\n }\n\n if (!payload.data) {\n throw new CliError(\n 'Contentful returned no introspection data. Check the space and environment ids.'\n );\n }\n\n try {\n return `${printSchema(buildClientSchema(payload.data))}\\n`;\n } catch (cause) {\n throw new CliError(\n `Could not build a schema from Contentful's introspection response: ${String(cause)}`\n );\n }\n}\n","/**\n * Detects the consumer's package manager so the CLI can print an install\n * command they can paste as-is.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';\n\n/** Lockfiles in the order they are checked. */\nconst LOCKFILES: Array<[PackageManager, string]> = [\n ['bun', 'bun.lock'],\n ['bun', 'bun.lockb'],\n ['pnpm', 'pnpm-lock.yaml'],\n ['yarn', 'yarn.lock'],\n ['npm', 'package-lock.json']\n];\n\n/** Identifies the package manager from the lockfile in `cwd`. */\nexport function detectPackageManager(cwd: string): PackageManager {\n for (const [manager, lockfile] of LOCKFILES) {\n if (existsSync(join(cwd, lockfile))) return manager;\n }\n return 'npm';\n}\n\n/** The command that adds `packages` as dev dependencies. */\nexport function installCommand(manager: PackageManager, packages: string[]): string {\n const list = packages.join(' ');\n switch (manager) {\n case 'bun':\n return `bun add -d ${list}`;\n case 'pnpm':\n return `pnpm add -D ${list}`;\n case 'yarn':\n return `yarn add -D ${list}`;\n case 'npm':\n return `npm install -D ${list}`;\n }\n}\n\n/**\n * Returns the packages that are not declared anywhere in the consumer's\n * `package.json`. An unreadable or absent manifest means \"declare all of\n * them\" — printing an install command the user may not need is harmless,\n * silently skipping a required one is not.\n */\nexport function missingDependencies(cwd: string, packages: string[]): string[] {\n let manifest: Record<string, unknown>;\n try {\n manifest = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n } catch {\n return [...packages];\n }\n\n const declared = new Set<string>();\n for (const field of [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies'\n ]) {\n const section = manifest[field];\n if (typeof section === 'object' && section !== null) {\n for (const name of Object.keys(section)) declared.add(name);\n }\n }\n return packages.filter((name) => !declared.has(name));\n}\n","/**\n * A minimal JSONC scanner that records source offsets.\n *\n * `tsconfig.json` files are JSON with comments and trailing commas, and are\n * hand-maintained — reading one with a comment-stripping parser and writing\n * it back would destroy the author's comments and formatting. So instead of\n * parsing to a value and re-serializing, this scanner produces a tree of\n * nodes annotated with their offsets in the original text, which the patcher\n * uses to make surgical string edits.\n *\n * It is deliberately not a general JSON validator: it accepts the shapes it\n * needs to locate and rejects everything else, so the caller can fall back\n * to printing manual instructions rather than mangling a file it did not\n * understand.\n */\n\nexport class JsoncError extends Error {\n override name = 'JsoncError';\n}\n\nexport interface JsoncMember {\n /** The parsed key, e.g. `compilerOptions`. */\n key: string;\n /** Offset of the member's first character (the key's opening quote). */\n start: number;\n /** Offset just past the member's value. */\n end: number;\n value: JsoncNode;\n}\n\nexport type JsoncNode =\n | { kind: 'object'; start: number; end: number; members: JsoncMember[] }\n | { kind: 'array'; start: number; end: number; elements: JsoncNode[] }\n | { kind: 'string'; start: number; end: number; value: string }\n | { kind: 'literal'; start: number; end: number };\n\nconst WHITESPACE = ' \\t\\n\\r';\n\nclass Scanner {\n private index = 0;\n\n constructor(private readonly source: string) {}\n\n /** Skips whitespace, `//` line comments and `/* *\\/` block comments. */\n private skipTrivia(): void {\n for (;;) {\n while (\n this.index < this.source.length &&\n WHITESPACE.includes(this.source[this.index] as string)\n ) {\n this.index += 1;\n }\n if (this.source.startsWith('//', this.index)) {\n const newline = this.source.indexOf('\\n', this.index);\n this.index = newline === -1 ? this.source.length : newline + 1;\n continue;\n }\n if (this.source.startsWith('/*', this.index)) {\n const close = this.source.indexOf('*/', this.index + 2);\n if (close === -1) {\n throw new JsoncError('Unterminated block comment.');\n }\n this.index = close + 2;\n continue;\n }\n return;\n }\n }\n\n private peek(): string {\n this.skipTrivia();\n if (this.index >= this.source.length) {\n throw new JsoncError('Unexpected end of input.');\n }\n return this.source[this.index] as string;\n }\n\n private expect(character: string): void {\n if (this.peek() !== character) {\n throw new JsoncError(`Expected \"${character}\" at offset ${String(this.index)}.`);\n }\n this.index += 1;\n }\n\n parseRoot(): JsoncNode {\n const node = this.parseValue();\n this.skipTrivia();\n if (this.index !== this.source.length) {\n throw new JsoncError(`Unexpected trailing content at offset ${String(this.index)}.`);\n }\n return node;\n }\n\n private parseValue(): JsoncNode {\n const character = this.peek();\n if (character === '{') return this.parseObject();\n if (character === '[') return this.parseArray();\n if (character === '\"') return this.parseString();\n return this.parseLiteral();\n }\n\n private parseObject(): JsoncNode {\n const start = this.index;\n this.expect('{');\n const members: JsoncMember[] = [];\n for (;;) {\n if (this.peek() === '}') {\n this.index += 1;\n return { kind: 'object', start, end: this.index, members };\n }\n const memberStart = this.index;\n const key = this.parseString();\n this.expect(':');\n const value = this.parseValue();\n members.push({\n key: key.value,\n start: memberStart,\n end: value.end,\n value\n });\n if (this.peek() === ',') {\n this.index += 1;\n }\n }\n }\n\n private parseArray(): JsoncNode {\n const start = this.index;\n this.expect('[');\n const elements: JsoncNode[] = [];\n for (;;) {\n if (this.peek() === ']') {\n this.index += 1;\n return { kind: 'array', start, end: this.index, elements };\n }\n elements.push(this.parseValue());\n if (this.peek() === ',') {\n this.index += 1;\n }\n }\n }\n\n private parseString(): JsoncNode & { kind: 'string' } {\n this.skipTrivia();\n const start = this.index;\n if (this.source[start] !== '\"') {\n throw new JsoncError(`Expected a string at offset ${String(start)}.`);\n }\n this.index += 1;\n while (this.index < this.source.length) {\n const character = this.source[this.index];\n if (character === '\\\\') {\n this.index += 2;\n continue;\n }\n this.index += 1;\n if (character === '\"') {\n const end = this.index;\n return {\n kind: 'string',\n start,\n end,\n value: JSON.parse(this.source.slice(start, end)) as string\n };\n }\n }\n throw new JsoncError(`Unterminated string at offset ${String(start)}.`);\n }\n\n /** Numbers, `true`, `false` and `null` — read as an opaque token. */\n private parseLiteral(): JsoncNode {\n this.skipTrivia();\n const start = this.index;\n while (\n this.index < this.source.length &&\n !',]}'.includes(this.source[this.index] as string) &&\n !WHITESPACE.includes(this.source[this.index] as string)\n ) {\n this.index += 1;\n }\n if (this.index === start) {\n throw new JsoncError(`Unexpected character at offset ${String(start)}.`);\n }\n return { kind: 'literal', start, end: this.index };\n }\n}\n\n/** Parses JSONC into an offset-annotated tree. Throws {@link JsoncError}. */\nexport function parseJsonc(source: string): JsoncNode {\n return new Scanner(source).parseRoot();\n}\n\n/** Finds a member by key, or `undefined`. */\nexport function findMember(node: JsoncNode, key: string): JsoncMember | undefined {\n if (node.kind !== 'object') return undefined;\n return node.members.find((member) => member.key === key);\n}\n","/**\n * Idempotent, comment-preserving patching of a consumer's `tsconfig.json`.\n *\n * Every change is a surgical string edit computed from source offsets, so\n * comments, trailing commas and the author's formatting all survive. When\n * the file's shape isn't understood, nothing is written and the caller is\n * told to insert the block by hand — a mangled tsconfig is far worse than a\n * manual step.\n */\n\nimport { findMember, JsoncError, parseJsonc, type JsoncNode } from './jsonc.js';\n\n/** The TypeScript language-service plugin gql.tada drives. */\nexport const GRAPHQLSP_PLUGIN = '@0no-co/graphqlsp';\n\nexport interface TsconfigPluginConfig {\n /** Path to the SDL file, relative to the tsconfig. */\n schema: string;\n /** Path gql.tada writes its generated types to, relative to the tsconfig. */\n tadaOutputLocation: string;\n}\n\nexport type TsconfigPatchResult =\n /** The plugin was already configured exactly as requested. */\n | { status: 'unchanged' }\n /** `source` is the patched file content. */\n | { status: 'patched'; source: string }\n /** The file could not be patched safely; `reason` says why. */\n | { status: 'manual'; reason: string };\n\ninterface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n let result = source;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n}\n\n/** The leading whitespace of the line containing `offset`. */\nfunction indentAt(source: string, offset: number): string {\n const lineStart = source.lastIndexOf('\\n', offset - 1) + 1;\n const line = source.slice(lineStart, offset);\n return line.slice(0, line.length - line.trimStart().length);\n}\n\n/** The file's own indentation unit, falling back to two spaces. */\nexport function detectIndentUnit(source: string): string {\n const match = /\\n([ \\t]+)\\S/.exec(source);\n return match?.[1] ?? ' ';\n}\n\n/** Renders the plugin entry, with `indent` as the entry's own indentation. */\nfunction renderPluginEntry(indent: string, unit: string, config: TsconfigPluginConfig): string {\n return [\n '{',\n `${indent}${unit}\"name\": ${JSON.stringify(GRAPHQLSP_PLUGIN)},`,\n `${indent}${unit}\"schema\": ${JSON.stringify(config.schema)},`,\n `${indent}${unit}\"tadaOutputLocation\": ${JSON.stringify(config.tadaOutputLocation)}`,\n `${indent}}`\n ].join('\\n');\n}\n\n/**\n * An edit that adds `\"key\": <value>` to an object node, matching the\n * object's existing layout.\n */\nfunction insertMember(\n source: string,\n object: JsoncNode & { kind: 'object' },\n key: string,\n renderValue: (indent: string) => string,\n unit: string\n): Edit {\n const last = object.members[object.members.length - 1];\n if (last) {\n const indent = indentAt(source, last.start);\n return {\n start: last.end,\n end: last.end,\n text: `,\\n${indent}\"${key}\": ${renderValue(indent)}`\n };\n }\n // `{}` — open it up onto its own lines.\n const closeIndent = indentAt(source, object.start);\n const indent = `${closeIndent}${unit}`;\n return {\n start: object.start + 1,\n end: object.end - 1,\n text: `\\n${indent}\"${key}\": ${renderValue(indent)}\\n${closeIndent}`\n };\n}\n\n/** Renders a `plugins` array containing only the graphqlsp entry. */\nfunction renderPluginsArray(indent: string, unit: string, config: TsconfigPluginConfig): string {\n const entryIndent = `${indent}${unit}`;\n return `[\\n${entryIndent}${renderPluginEntry(entryIndent, unit, config)}\\n${indent}]`;\n}\n\n/**\n * Adds — or updates in place — the `@0no-co/graphqlsp` entry in\n * `compilerOptions.plugins`.\n *\n * Running this twice with the same configuration is a no-op: the second run\n * reports `unchanged`.\n */\nexport function patchTsconfig(source: string, config: TsconfigPluginConfig): TsconfigPatchResult {\n let root: JsoncNode;\n try {\n root = parseJsonc(source);\n } catch (cause) {\n /* v8 ignore next 3 -- defensive: only JsoncError can be thrown here */\n const reason = cause instanceof JsoncError ? cause.message : String(cause);\n return { status: 'manual', reason: `could not be parsed (${reason})` };\n }\n\n if (root.kind !== 'object') {\n return { status: 'manual', reason: 'its root is not an object' };\n }\n\n const unit = detectIndentUnit(source);\n const compilerOptions = findMember(root, 'compilerOptions');\n\n // No `compilerOptions` at all — add it, with the plugin inside.\n if (!compilerOptions) {\n const edit = insertMember(\n source,\n root,\n 'compilerOptions',\n (indent) =>\n `{\\n${indent}${unit}\"plugins\": ${renderPluginsArray(\n `${indent}${unit}`,\n unit,\n config\n )}\\n${indent}}`,\n unit\n );\n return { status: 'patched', source: applyEdits(source, [edit]) };\n }\n\n if (compilerOptions.value.kind !== 'object') {\n return { status: 'manual', reason: '\"compilerOptions\" is not an object' };\n }\n\n const plugins = findMember(compilerOptions.value, 'plugins');\n\n // `compilerOptions` without `plugins` — add the array.\n if (!plugins) {\n const edit = insertMember(\n source,\n compilerOptions.value,\n 'plugins',\n (indent) => renderPluginsArray(indent, unit, config),\n unit\n );\n return { status: 'patched', source: applyEdits(source, [edit]) };\n }\n\n if (plugins.value.kind !== 'array') {\n return { status: 'manual', reason: '\"compilerOptions.plugins\" is not an array' };\n }\n\n const existing = plugins.value.elements.find((element) => {\n const name = findMember(element, 'name');\n return name?.value.kind === 'string' && name.value.value === GRAPHQLSP_PLUGIN;\n });\n\n // A graphqlsp entry is already there — update its fields in place rather\n // than appending a second, conflicting one.\n if (existing) {\n /* v8 ignore next 3 -- `findMember` only matches object elements */\n if (existing.kind !== 'object') {\n return { status: 'manual', reason: 'its graphqlsp plugin entry is not an object' };\n }\n const edits: Edit[] = [];\n for (const [key, value] of [\n ['schema', config.schema],\n ['tadaOutputLocation', config.tadaOutputLocation]\n ] as const) {\n const member = findMember(existing, key);\n if (member) {\n edits.push({\n start: member.value.start,\n end: member.value.end,\n text: JSON.stringify(value)\n });\n } else {\n edits.push(insertMember(source, existing, key, () => JSON.stringify(value), unit));\n }\n }\n const patched = applyEdits(source, edits);\n return patched === source ? { status: 'unchanged' } : { status: 'patched', source: patched };\n }\n\n // Unrelated plugins are configured — append, never replace.\n const last = plugins.value.elements[plugins.value.elements.length - 1];\n if (last) {\n const indent = indentAt(source, last.start);\n return {\n status: 'patched',\n source: applyEdits(source, [\n {\n start: last.end,\n end: last.end,\n text: `,\\n${indent}${renderPluginEntry(indent, unit, config)}`\n }\n ])\n };\n }\n\n // An empty `plugins: []`.\n const closeIndent = indentAt(source, plugins.value.start);\n const entryIndent = `${closeIndent}${unit}`;\n return {\n status: 'patched',\n source: applyEdits(source, [\n {\n start: plugins.value.start + 1,\n end: plugins.value.end - 1,\n text: `\\n${entryIndent}${renderPluginEntry(entryIndent, unit, config)}\\n${closeIndent}`\n }\n ])\n };\n}\n\n/** The block to print when the caller has to edit the file by hand. */\nexport function manualPluginBlock(config: TsconfigPluginConfig): string {\n return renderPluginEntry('', ' ', config);\n}\n","/**\n * The `fetch-contentful` CLI: `tada-init` and `tada-refresh`.\n *\n * Everything is driven through {@link CliIo} so the whole command surface is\n * testable without spawning a process — including the guarantee that a\n * `--dry-run` writes nothing and that the access token never reaches the\n * terminal.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport { readEnvSettings } from '../env.js';\nimport { parseArgs, type ParsedArgs } from './args.js';\nimport { formatBytes, lineDiff } from './diff.js';\nimport { describeEnvFiles, loadEnvFiles, type EnvFileLoad } from './env-file.js';\nimport { CliError, redact } from './errors.js';\nimport { PACKAGE_NAME, relativeSpecifier, renderGraphqlModule } from './graphql-module.js';\nimport { fetchSchemaSdl } from './introspect.js';\nimport { detectPackageManager, installCommand, missingDependencies } from './package-manager.js';\nimport { GRAPHQLSP_PLUGIN, manualPluginBlock, patchTsconfig } from './tsconfig.js';\n\nexport interface CliIo {\n /** Directory the command runs against. */\n cwd: string;\n fetch: typeof fetch;\n stdout: (line: string) => void;\n stderr: (line: string) => void;\n}\n\n/** Packages the generated setup needs the consumer to install. */\nconst REQUIRED_PEERS = ['gql.tada', GRAPHQLSP_PLUGIN];\n\nconst DEFAULTS = {\n schemaPath: './contentful-schema.graphql',\n tadaOutput: './src/contentful-env.d.ts',\n graphqlFile: './src/graphql.ts',\n tsconfig: './tsconfig.json'\n} as const;\n\n/** Width of the verb column in the action log. */\nconst VERB_WIDTH = 12;\n\nconst HELP = `fetch-contentful — gql.tada setup for a Contentful space\n\nUsage:\n fetch-contentful tada-init [options] Set up gql.tada in this project\n fetch-contentful tada-refresh [options] Re-download the schema only\n\nConfiguration (flags win over environment variables):\n --space <id> CONTENTFUL_SPACE_ID\n --environment <id> CONTENTFUL_ENVIRONMENT (default \"master\")\n --token <token> CONTENTFUL_ACCESS_TOKEN (Content Delivery API)\n\nPaths (relative to the working directory):\n --schema-path <path> default ${DEFAULTS.schemaPath}\n --tada-output <path> default ${DEFAULTS.tadaOutput}\n --graphql-file <path> default ${DEFAULTS.graphqlFile}\n --tsconfig <path> default ${DEFAULTS.tsconfig}\n\nOther:\n --dry-run Show what would change; write nothing\n --force Overwrite an existing graphql file (tada-init)\n --cwd <path> Run against another directory\n --env-file <path> Read this file instead of .env.local / .env\n -h, --help Show this help\n\nConfiguration is read from .env.local, then .env, then the shell — anything\nalready exported wins over a file, and flags win over everything. The\nNEXT_PUBLIC_-prefixed names are accepted as fallbacks, exactly as the\nlibrary reads them at runtime.`;\n\n/* ------------------------------------------------------------------ */\n/* Configuration */\n/* ------------------------------------------------------------------ */\n\ninterface Config {\n space: string;\n environment: string;\n token: string;\n}\n\nfunction resolveConfig(args: ParsedArgs, envFiles: EnvFileLoad): Config {\n const env = readEnvSettings();\n const space = args.values.space ?? env.space;\n // Introspection is a Content Delivery API operation, so there is only one\n // token in play here and the flag stays plain `--token`.\n const token = args.values.token ?? env.deliveryToken;\n const environment = args.values.environment ?? env.environment ?? 'master';\n\n const missing: string[] = [];\n if (!space) {\n missing.push(\n 'space (pass --space, or set CONTENTFUL_SPACE_ID / NEXT_PUBLIC_CONTENTFUL_SPACE_ID)'\n );\n }\n if (!token) {\n missing.push(\n 'access token (pass --token, or set CONTENTFUL_ACCESS_TOKEN / NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN)'\n );\n }\n if (!space || !token) {\n throw new CliError(\n `Missing required Contentful configuration:\\n - ${missing.join(\n '\\n - '\n )}\\n${describeEnvFiles(envFiles)}`\n );\n }\n return { space, environment, token };\n}\n\ninterface Paths {\n root: string;\n schema: string;\n tadaOutput: string;\n graphqlFile: string;\n tsconfig: string;\n}\n\nfunction resolvePaths(args: ParsedArgs, io: CliIo): Paths {\n const root = resolve(io.cwd, args.values.cwd ?? '.');\n const at = (value: string | undefined, fallback: string): string =>\n resolve(root, value ?? fallback);\n return {\n root,\n schema: at(args.values['schema-path'], DEFAULTS.schemaPath),\n tadaOutput: at(args.values['tada-output'], DEFAULTS.tadaOutput),\n graphqlFile: at(args.values['graphql-file'], DEFAULTS.graphqlFile),\n tsconfig: at(args.values.tsconfig, DEFAULTS.tsconfig)\n };\n}\n\n/** A path as the user would type it, for display. */\nfunction display(root: string, path: string): string {\n const shown = relative(root, path);\n return shown === '' || shown.startsWith('..') || isAbsolute(shown) ? path : shown;\n}\n\nfunction readIfExists(path: string): string | undefined {\n return existsSync(path) ? readFileSync(path, 'utf8') : undefined;\n}\n\n/* ------------------------------------------------------------------ */\n/* Planned changes */\n/* ------------------------------------------------------------------ */\n\ntype Preview = 'size' | 'diff' | 'content';\n\ntype Action =\n | {\n kind: 'write';\n path: string;\n before: string | undefined;\n after: string;\n preview: Preview;\n }\n | { kind: 'unchanged'; path: string }\n | { kind: 'skip'; path: string; reason: string }\n | { kind: 'manual'; path: string; reason: string; block: string };\n\n/** Plans the schema download, shared by both commands. */\nfunction planSchema(sdl: string, paths: Paths): Action {\n const before = readIfExists(paths.schema);\n if (before === sdl) return { kind: 'unchanged', path: paths.schema };\n return {\n kind: 'write',\n path: paths.schema,\n before,\n after: sdl,\n preview: 'size'\n };\n}\n\nfunction planTsconfig(paths: Paths): Action {\n const before = readIfExists(paths.tsconfig);\n if (before === undefined) {\n throw new CliError(\n `No tsconfig at ${display(paths.root, paths.tsconfig)}. ` +\n 'Pass --tsconfig if it lives elsewhere.'\n );\n }\n const config = {\n schema: relativeSpecifier(paths.tsconfig, paths.schema),\n tadaOutputLocation: relativeSpecifier(paths.tsconfig, paths.tadaOutput)\n };\n const result = patchTsconfig(before, config);\n if (result.status === 'unchanged') {\n return { kind: 'unchanged', path: paths.tsconfig };\n }\n if (result.status === 'manual') {\n return {\n kind: 'manual',\n path: paths.tsconfig,\n reason: result.reason,\n block: manualPluginBlock(config)\n };\n }\n return {\n kind: 'write',\n path: paths.tsconfig,\n before,\n after: result.source,\n preview: 'diff'\n };\n}\n\nfunction planGraphqlModule(paths: Paths, force: boolean): Action {\n const before = readIfExists(paths.graphqlFile);\n const after = renderGraphqlModule(relativeSpecifier(paths.graphqlFile, paths.tadaOutput));\n if (before !== undefined && !force) {\n return {\n kind: 'skip',\n path: paths.graphqlFile,\n reason: 'already exists; pass --force to overwrite'\n };\n }\n if (before === after) return { kind: 'unchanged', path: paths.graphqlFile };\n return {\n kind: 'write',\n path: paths.graphqlFile,\n before,\n after,\n preview: 'content'\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Reporting and applying */\n/* ------------------------------------------------------------------ */\n\nfunction logAction(io: CliIo, verb: string, detail: string): void {\n io.stdout(` ${verb.padEnd(VERB_WIDTH)} ${detail}`);\n}\n\nfunction report(action: Action, paths: Paths, dryRun: boolean, io: CliIo): void {\n const name = display(paths.root, action.path);\n if (action.kind === 'unchanged') {\n logAction(io, 'unchanged', name);\n return;\n }\n if (action.kind === 'skip') {\n logAction(io, 'skipped', `${name} (${action.reason})`);\n return;\n }\n if (action.kind === 'manual') {\n logAction(io, 'manual', `${name} (${action.reason})`);\n return;\n }\n\n const created = action.before === undefined;\n const verb = dryRun\n ? created\n ? 'would create'\n : 'would update'\n : created\n ? 'created'\n : 'updated';\n const size =\n action.preview === 'size' ? ` (${formatBytes(Buffer.byteLength(action.after))})` : '';\n logAction(io, verb, `${name}${size}`);\n\n if (!dryRun) return;\n\n if (action.preview === 'content') {\n for (const line of action.after.replace(/\\n$/, '').split('\\n')) {\n io.stdout(` + ${line}`);\n }\n return;\n }\n\n // Everything below compares against the file already on disk.\n if (action.before === undefined) return;\n\n if (action.preview === 'diff') {\n for (const line of lineDiff(action.before, action.after)) {\n io.stdout(` ${line}`);\n }\n return;\n }\n\n // Exact counts, not rounded ones: two files that both format as\n // \"23.1 kB\" would otherwise look identical.\n const beforeBytes = Buffer.byteLength(action.before);\n const afterBytes = Buffer.byteLength(action.after);\n const delta = afterBytes - beforeBytes;\n io.stdout(\n ` ${String(beforeBytes)} → ${String(afterBytes)} bytes (${\n delta >= 0 ? '+' : ''\n }${String(delta)})`\n );\n}\n\nfunction apply(action: Action): void {\n if (action.kind !== 'write') return;\n mkdirSync(dirname(action.path), { recursive: true });\n writeFileSync(action.path, action.after, 'utf8');\n}\n\n/** Prints the manual tsconfig block, when patching was not safe. */\nfunction reportManual(action: Action, paths: Paths, io: CliIo): void {\n if (action.kind !== 'manual') return;\n io.stdout('');\n io.stdout(`${display(paths.root, action.path)} was left untouched because ${action.reason}.`);\n io.stdout('Add this entry to \"compilerOptions.plugins\" by hand:');\n io.stdout('');\n for (const line of action.block.split('\\n')) io.stdout(` ${line}`);\n}\n\nfunction reportPeers(paths: Paths, io: CliIo): void {\n const missing = missingDependencies(paths.root, REQUIRED_PEERS);\n if (missing.length === 0) return;\n io.stdout('');\n io.stdout(`Install the packages the generated setup needs:`);\n io.stdout(` ${installCommand(detectPackageManager(paths.root), missing)}`);\n}\n\n/* ------------------------------------------------------------------ */\n/* Commands */\n/* ------------------------------------------------------------------ */\n\nasync function tadaInit(args: ParsedArgs, io: CliIo): Promise<number> {\n // Paths first: the env files are read from the directory the command\n // targets, which `--cwd` can move.\n const paths = resolvePaths(args, io);\n const envFiles = loadEnvFiles(paths.root, args.values['env-file']);\n const config = resolveConfig(args, envFiles);\n const dryRun = args.flags.has('dry-run');\n\n // Planned before the network call, so a missing tsconfig fails fast.\n const tsconfigAction = planTsconfig(paths);\n const sdl = await fetchSchemaSdl({ ...config, fetch: io.fetch });\n\n // Everything is planned before anything is written, so a failure part-way\n // through cannot leave a half-configured project behind.\n const actions = [\n planSchema(sdl, paths),\n tsconfigAction,\n planGraphqlModule(paths, args.flags.has('force'))\n ];\n\n io.stdout(\n dryRun\n ? `Dry run — nothing will be written (space ${config.space}, environment ${config.environment}).`\n : `Configuring gql.tada for space ${config.space}, environment ${config.environment}.`\n );\n for (const action of actions) {\n if (!dryRun) apply(action);\n report(action, paths, dryRun, io);\n }\n for (const action of actions) reportManual(action, paths, io);\n\n reportPeers(paths, io);\n\n // A dry run changed nothing, so there is nothing to do next.\n if (dryRun) return 0;\n\n io.stdout('');\n io.stdout('Next steps:');\n io.stdout(` 1. Restart the TypeScript server so ${GRAPHQLSP_PLUGIN} loads.`);\n io.stdout(\n ` 2. Write a query with the \\`graphql\\` helper from ${display(paths.root, paths.graphqlFile)},`\n );\n io.stdout(` then pass it to fetchContentful from ${PACKAGE_NAME}.`);\n io.stdout(' Result and variable types are inferred from the document.');\n io.stdout(' 3. After a content-model change, run `fetch-contentful tada-refresh`.');\n return 0;\n}\n\nasync function tadaRefresh(args: ParsedArgs, io: CliIo): Promise<number> {\n // Paths first: the env files are read from the directory the command\n // targets, which `--cwd` can move.\n const paths = resolvePaths(args, io);\n const envFiles = loadEnvFiles(paths.root, args.values['env-file']);\n const config = resolveConfig(args, envFiles);\n const dryRun = args.flags.has('dry-run');\n\n const sdl = await fetchSchemaSdl({ ...config, fetch: io.fetch });\n const action = planSchema(sdl, paths);\n\n if (action.kind === 'unchanged') {\n // Leave the file's mtime alone: an unchanged schema should not show up\n // in `git status`, and should not invalidate a build cache.\n io.stdout(\n `Schema is already up to date — ${display(paths.root, paths.schema)} left untouched.`\n );\n return 0;\n }\n\n if (!dryRun) apply(action);\n report(action, paths, dryRun, io);\n return 0;\n}\n\n/* ------------------------------------------------------------------ */\n/* Entry point */\n/* ------------------------------------------------------------------ */\n\nasync function dispatch(argv: string[], io: CliIo): Promise<number> {\n const args = parseArgs(argv);\n // Accept both `tada-init` and `tada init`.\n const command = args.positionals.join('-');\n\n if (args.flags.has('help') || command === '' || command === 'help') {\n io.stdout(HELP);\n return 0;\n }\n if (command === 'tada-init') return tadaInit(args, io);\n if (command === 'tada-refresh') return tadaRefresh(args, io);\n\n throw new CliError(\n `Unknown command \"${args.positionals.join(\n ' '\n )}\". Run with --help to see the available commands.`\n );\n}\n\n/** Any token reachable from the environment or the command line. */\nfunction knownTokens(argv: string[]): Array<string | undefined> {\n const env = readEnvSettings();\n const tokens: Array<string | undefined> = [env.deliveryToken, env.previewToken];\n for (const [index, argument] of argv.entries()) {\n if (argument.startsWith('--token=')) tokens.push(argument.slice(8));\n else if (argument === '--token') tokens.push(argv[index + 1]);\n }\n return tokens;\n}\n\n/**\n * Runs the CLI and resolves with the process exit code. Never rejects, and\n * never prints the access token.\n */\nexport async function run(argv: string[], io: CliIo): Promise<number> {\n try {\n return await dispatch(argv, io);\n } catch (error) {\n const raw = error instanceof CliError ? error.message : `Unexpected failure: ${String(error)}`;\n let message = raw;\n for (const token of knownTokens(argv)) message = redact(message, token);\n io.stderr(`error: ${message}`);\n return 1;\n }\n}\n","#!/usr/bin/env node\n/**\n * The `fetch-contentful` binary.\n *\n * A thin shell around {@link run}: everything worth testing lives there,\n * reached without spawning a process.\n */\nimport { run } from './run.js';\n\nconst code = await run(process.argv.slice(2), {\n cwd: process.cwd(),\n fetch: globalThis.fetch,\n stdout: (line) => process.stdout.write(`${line}\\n`),\n stderr: (line) => process.stderr.write(`${line}\\n`)\n});\nprocess.exitCode = code;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/env.ts","../../src/cli/errors.ts","../../src/cli/args.ts","../../src/cli/diff.ts","../../src/cli/env-file.ts","../../src/cli/graphql-module.ts","../../src/client.ts","../../src/cli/introspect.ts","../../src/cli/package-manager.ts","../../src/cli/jsonc.ts","../../src/cli/tsconfig.ts","../../src/cli/run.ts","../../src/cli/index.ts"],"names":["existsSync","readFileSync","indent","resolve","relative","dirname"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Environment-derived configuration.\n *\n * Two families of variable names are supported, checked in this order:\n *\n * 1. Framework-neutral names — `CONTENTFUL_SPACE_ID`, `CONTENTFUL_ENVIRONMENT`,\n * `CONTENTFUL_ACCESS_TOKEN`, `CONTENTFUL_PREVIEW_ACCESS_TOKEN`.\n * 2. `NEXT_PUBLIC_`-prefixed equivalents for Next.js projects that call\n * Contentful from the browser — for the space, the environment and the\n * **delivery** token only.\n *\n * The preview token is deliberately absent from that second family. Next.js\n * inlines `NEXT_PUBLIC_` variables into client bundles by string-replacing\n * the literal accesses below, so merely importing this module in a project\n * that set `NEXT_PUBLIC_CONTENTFUL_PREVIEW_ACCESS_TOKEN` would bake the\n * token into public JavaScript — whether or not any client code ever asks\n * for preview content. A delivery token is read-only and commonly public; a\n * preview token reads unpublished content and must not leak. Callers that\n * genuinely need preview in the browser pass `previewToken` explicitly, so\n * the exposure is their deliberate choice rather than this module's.\n *\n * IMPORTANT: every lookup below is written as a literal\n * `process.env.SOME_NAME` property access, never a dynamic `process.env[x]`.\n * Next.js exposes `NEXT_PUBLIC_` variables to client bundles by\n * string-replacing those literal expressions at build time — dynamic access\n * is invisible to the inliner and resolves to `undefined` in the browser.\n * Do not \"refactor\" these into a loop or a name table.\n *\n * This module reads the already-populated `process.env`; loading `.env`\n * files from disk is deliberately left to the platform (Next.js, Vite,\n * dotenv, ...), whose precedence rules would otherwise be duplicated here.\n */\n\n/*\n * These variables are read at runtime inside the consuming application, not\n * while this package is built — the bundle ships the literal `process.env.X`\n * accesses untouched. Declaring them in turbo.json would therefore be\n * inaccurate and would invalidate the build cache for no reason.\n */\n/* eslint-disable turbo/no-undeclared-env-vars */\n\nexport interface EnvSettings {\n space: string | undefined;\n environment: string | undefined;\n /** Content Delivery API token, for published content. */\n deliveryToken: string | undefined;\n /** Content Preview API token, for draft content. Server-side only. */\n previewToken: string | undefined;\n}\n\nfunction orUndefined(value: string | undefined): string | undefined {\n return value || undefined;\n}\n\n/** Reads Contentful settings from `process.env` (neutral names first). */\nexport function readEnvSettings(): EnvSettings {\n /* v8 ignore next 10 -- process always exists in the test runtime */\n if (typeof process === 'undefined' || !process.env) {\n return {\n space: undefined,\n environment: undefined,\n deliveryToken: undefined,\n previewToken: undefined\n };\n }\n const deliveryToken = orUndefined(\n process.env.CONTENTFUL_ACCESS_TOKEN || process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN\n );\n return {\n space: orUndefined(\n process.env.CONTENTFUL_SPACE_ID || process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID\n ),\n environment: orUndefined(\n process.env.CONTENTFUL_ENVIRONMENT || process.env.NEXT_PUBLIC_CONTENTFUL_ENVIRONMENT\n ),\n deliveryToken,\n // No `NEXT_PUBLIC_` fallback: see the note at the top of this file.\n previewToken: orUndefined(process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN)\n };\n}\n","/**\n * An expected CLI failure: printed as a plain message with exit code 1,\n * never as a stack trace.\n */\nexport class CliError extends Error {\n override name = 'CliError';\n}\n\n/**\n * Removes an access token from text that is about to be printed.\n *\n * Contentful echoes request details in some error bodies, and a token\n * pasted into a bug report is a token that has to be rotated.\n */\nexport function redact(text: string, token: string | undefined): string {\n if (!token) return text;\n return text.split(token).join('[redacted]');\n}\n","/**\n * A tiny `process.argv` parser.\n *\n * `node:util`'s `parseArgs` would do, but it prints an experimental warning\n * on Node 18 — which this package still supports — and that warning would\n * land in the middle of the CLI's output.\n */\n\nimport { CliError } from './errors.js';\n\n/** Flags that take no value. */\nexport const BOOLEAN_FLAGS = ['dry-run', 'force', 'help'] as const;\n\n/** Flags that take a value. */\nexport const VALUE_FLAGS = [\n 'space',\n 'environment',\n 'token',\n 'schema-path',\n 'tada-output',\n 'graphql-file',\n 'tsconfig',\n 'cwd',\n 'env-file'\n] as const;\n\nexport interface ParsedArgs {\n /** Positional arguments, e.g. `['tada-init']`. */\n positionals: string[];\n values: Partial<Record<(typeof VALUE_FLAGS)[number], string>>;\n flags: Set<(typeof BOOLEAN_FLAGS)[number]>;\n}\n\nfunction isBooleanFlag(name: string): name is (typeof BOOLEAN_FLAGS)[number] {\n return (BOOLEAN_FLAGS as readonly string[]).includes(name);\n}\n\nfunction isValueFlag(name: string): name is (typeof VALUE_FLAGS)[number] {\n return (VALUE_FLAGS as readonly string[]).includes(name);\n}\n\n/** Parses `argv` (already stripped of `node` and the script path). */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const parsed: ParsedArgs = {\n positionals: [],\n values: {},\n flags: new Set()\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const argument = argv[index] as string;\n\n if (argument === '-h') {\n parsed.flags.add('help');\n continue;\n }\n\n if (!argument.startsWith('--')) {\n parsed.positionals.push(argument);\n continue;\n }\n\n const equals = argument.indexOf('=');\n const name = argument.slice(2, equals === -1 ? undefined : equals);\n const inlineValue = equals === -1 ? undefined : argument.slice(equals + 1);\n\n if (isBooleanFlag(name)) {\n if (inlineValue !== undefined) {\n throw new CliError(`--${name} does not take a value.`);\n }\n parsed.flags.add(name);\n continue;\n }\n\n if (!isValueFlag(name)) {\n throw new CliError(`Unknown option \"--${name}\".`);\n }\n\n const value = inlineValue ?? argv[++index];\n if (value === undefined) {\n throw new CliError(`--${name} needs a value.`);\n }\n parsed.values[name] = value;\n }\n\n return parsed;\n}\n","/**\n * A line diff for `--dry-run` output.\n *\n * Only ever used on hand-sized files (a tsconfig, a generated module), so a\n * plain quadratic LCS is the right trade for having no dependency.\n */\n\nconst MAX_LINES = 400;\n\n/** Length of the longest common subsequence, as a DP table. */\nfunction lcsTable(before: string[], after: string[]): number[][] {\n const table: number[][] = Array.from({ length: before.length + 1 }, () =>\n new Array<number>(after.length + 1).fill(0)\n );\n for (let i = before.length - 1; i >= 0; i -= 1) {\n for (let j = after.length - 1; j >= 0; j -= 1) {\n const row = table[i] as number[];\n const next = table[i + 1] as number[];\n row[j] =\n before[i] === after[j]\n ? (next[j + 1] as number) + 1\n : Math.max(next[j] as number, row[j + 1] as number);\n }\n }\n return table;\n}\n\n/**\n * Renders `before` → `after` as `-`/`+`/` `-prefixed lines.\n *\n * Not a `patch(1)`-compatible unified diff — there are no hunk headers, and\n * unchanged lines are all kept — but it reads the same way and is enough to\n * see exactly what a run would change.\n */\nexport function lineDiff(before: string, after: string): string[] {\n if (before === after) return [];\n\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n\n if (beforeLines.length + afterLines.length > MAX_LINES * 2) {\n return [\n ` (${String(beforeLines.length)} lines → ${String(\n afterLines.length\n )} lines; too large to diff)`\n ];\n }\n\n const table = lcsTable(beforeLines, afterLines);\n const output: string[] = [];\n let i = 0;\n let j = 0;\n\n while (i < beforeLines.length && j < afterLines.length) {\n if (beforeLines[i] === afterLines[j]) {\n output.push(` ${beforeLines[i] as string}`);\n i += 1;\n j += 1;\n } else if (\n ((table[i + 1] as number[])[j] as number) >= ((table[i] as number[])[j + 1] as number)\n ) {\n output.push(` - ${beforeLines[i] as string}`);\n i += 1;\n } else {\n output.push(` + ${afterLines[j] as string}`);\n j += 1;\n }\n }\n while (i < beforeLines.length) {\n output.push(` - ${beforeLines[i] as string}`);\n i += 1;\n }\n while (j < afterLines.length) {\n output.push(` + ${afterLines[j] as string}`);\n j += 1;\n }\n\n return output;\n}\n\n/** Formats a byte count for humans. */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${String(bytes)} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} kB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n","/**\n * `.env` file loading, for the CLI only.\n *\n * The library deliberately never reads the disk: doing so would break\n * bundlers and edge runtimes, and every platform (Next.js, Vite, dotenv)\n * already owns that job at runtime, with its own precedence rules.\n *\n * A CLI is a different situation. It runs from a shell, before anything has\n * populated `process.env` — and a Next.js project keeps its Contentful\n * credentials in `.env.local`, which Next reads only when Next itself boots.\n * Without this module the CLI would report the credentials missing while\n * they sit in a file two lines away.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { CliError } from './errors.js';\n\n/** Files checked when `--env-file` is not given, in precedence order. */\nexport const ENV_FILES = ['.env.local', '.env'] as const;\n\nconst ASSIGNMENT = /^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/;\n\n/**\n * Parses `.env` contents into key/value pairs.\n *\n * Covers the syntax these files actually use: comments, blank lines, an\n * optional `export` prefix, and single- or double-quoted values (`\\n` is\n * unescaped inside double quotes only). Multi-line values are not supported\n * — no Contentful credential needs one.\n */\nexport function parseEnvFile(source: string): Record<string, string> {\n const values: Record<string, string> = {};\n\n for (const rawLine of source.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === '' || line.startsWith('#')) continue;\n\n const match = ASSIGNMENT.exec(line);\n if (!match) continue;\n\n const key = match[1] as string;\n let value = (match[2] as string).trim();\n\n const quote = value[0];\n if ((quote === '\"' || quote === \"'\") && value.length > 1 && value.endsWith(quote)) {\n value = value.slice(1, -1);\n if (quote === '\"') value = value.replace(/\\\\n/g, '\\n');\n } else {\n // An unquoted value ends at an inline comment. The `#` has to be\n // preceded by whitespace, so a `#` inside a token is left alone.\n const comment = value.search(/\\s#/);\n if (comment !== -1) value = value.slice(0, comment).trimEnd();\n }\n\n values[key] = value;\n }\n\n return values;\n}\n\nexport interface EnvFileLoad {\n /** Directory the files were looked for in. */\n directory: string;\n /** Files that were read, in the order they were applied. */\n files: string[];\n /** Variables this load actually set. */\n applied: string[];\n}\n\n/**\n * Reads `.env.local` and `.env` (or one explicit file) into `process.env`.\n *\n * Nothing already present in the environment is overwritten, so a real\n * exported variable — and therefore anything a CI system or a shell sets —\n * still wins over a file. An empty value counts as absent, matching how the\n * library treats blank variables everywhere else.\n */\nexport function loadEnvFiles(directory: string, explicit?: string): EnvFileLoad {\n const load: EnvFileLoad = { directory, files: [], applied: [] };\n\n if (explicit !== undefined && !existsSync(resolve(directory, explicit))) {\n throw new CliError(`No env file at ${explicit}.`);\n }\n\n for (const candidate of explicit === undefined ? ENV_FILES : [explicit]) {\n const path = resolve(directory, candidate);\n if (!existsSync(path)) continue;\n\n load.files.push(candidate);\n for (const [key, value] of Object.entries(parseEnvFile(readFileSync(path, 'utf8')))) {\n if (!process.env[key]) {\n process.env[key] = value;\n load.applied.push(key);\n }\n }\n }\n\n return load;\n}\n\n/** A sentence explaining where the CLI looked for configuration. */\nexport function describeEnvFiles(load: EnvFileLoad): string {\n if (load.files.length === 0) {\n return (\n `No ${ENV_FILES.join(' or ')} file was found in ${load.directory}, ` +\n 'so only the shell environment was read. Point at one with --env-file ' +\n 'if it lives elsewhere.'\n );\n }\n return (\n `Read ${load.files.join(' and ')}; anything already set in the ` +\n 'environment takes precedence over them.'\n );\n}\n","/**\n * Renders the `graphql.ts` module that binds gql.tada to the space's\n * introspection output and Contentful's scalar map.\n */\n\nimport { dirname, relative, sep } from 'node:path';\n\n/** The published package name, used in the generated import. */\nexport const PACKAGE_NAME = '@fourtwelvelabs/fetch-contentful';\n\n/**\n * The path of `toFile` as seen from the directory holding `fromFile`,\n * always relative and always POSIX-separated — the form both an `import`\n * specifier and a tsconfig plugin path want.\n */\nexport function relativeSpecifier(fromFile: string, toFile: string): string {\n const path = relative(dirname(fromFile), toFile).split(sep).join('/');\n return path.startsWith('.') ? path : `./${path}`;\n}\n\n/**\n * The contents of the generated `graphql.ts`.\n *\n * `introspectionImport` is the specifier for gql.tada's generated types —\n * kept with its `.d.ts` extension, which is gql.tada's own convention.\n */\nexport function renderGraphqlModule(introspectionImport: string): string {\n return `/**\n * gql.tada, bound to this space's schema.\n *\n * Generated by \\`fetch-contentful tada-init\\`. Safe to edit and to commit;\n * re-running \\`tada-init\\` will not overwrite it without \\`--force\\`.\n *\n * Refresh the schema after a content-model change with:\n * fetch-contentful tada-refresh\n */\nimport { initGraphQLTada } from 'gql.tada';\nimport type { ContentfulScalars } from '${PACKAGE_NAME}/tada';\nimport type { introspection } from '${introspectionImport}';\n\nexport const graphql = initGraphQLTada<{\n introspection: introspection;\n scalars: ContentfulScalars;\n}>();\n\nexport { readFragment } from 'gql.tada';\nexport type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada';\n`;\n}\n","import { print, type DocumentNode } from 'graphql';\nimport { annotateQuery } from './annotate.js';\nimport { FetchContentfulError, isFetchContentfulError } from './errors.js';\nimport { minifyQuery } from './minify.js';\nimport {\n isPersistedQueryNotFoundError,\n persistedQueryExtensions,\n sha256Hex\n} from './persisted-query.js';\nimport { withRetries, type RetryConfig } from './retry.js';\nimport { getOperation, stripInternalDirectives } from './split.js';\nimport type {\n ContentfulGraphQLError,\n GraphQLVariables,\n NextFetchOptions,\n UnresolvableLinkMode\n} from './types.js';\nimport { partitionUnresolvableLinks } from './unresolvable.js';\n\nexport interface RequestContext {\n space: string;\n environment: string;\n token: string;\n fetch: typeof fetch;\n retry: RetryConfig;\n signal?: AbortSignal;\n next?: NextFetchOptions;\n cache?: RequestCache;\n /** Append the annotated query to error messages. Defaults to `true`. */\n annotateQueryOnError?: boolean;\n /**\n * How to treat an `UNRESOLVABLE_LINK` error. Anything but `'error'` lets\n * the partial response through. Defaults to `'omit'`.\n */\n unresolvableLinks?: UnresolvableLinkMode;\n /** Notified of the unresolvable links a tolerated response carried. */\n onUnresolvableLink?: (errors: ContentfulGraphQLError[]) => void;\n /** Strip insignificant whitespace from the outgoing query. Defaults to `true`. */\n minifyQuery?: boolean;\n /** Send this query via Automatic Persisted Queries. Defaults to `false`. */\n automaticPersistedQueries?: boolean;\n}\n\nexport function graphqlEndpoint(space: string, environment: string): string {\n return `https://graphql.contentful.com/content/v1/spaces/${encodeURIComponent(\n space\n )}/environments/${encodeURIComponent(environment)}`;\n}\n\n/**\n * Renders the document exactly as it will go out on the wire: fragments and\n * `preview`/`locale` injection have already happened by the time a document\n * reaches here, so this is just the printer plus (by default) minification.\n * Used both to build the request body and — since Contentful's `line`/\n * `column` error locations point into whatever text was actually sent — as\n * the text {@link annotateQuery} renders back.\n */\nexport function printOutgoingQuery(document: DocumentNode, context: RequestContext): string {\n const printed = print(stripInternalDirectives(document));\n return context.minifyQuery === false ? printed : minifyQuery(printed);\n}\n\n/** Parse a Retry-After header (seconds or HTTP date) into milliseconds. */\nexport function parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) {\n return Math.max(0, seconds * 1000);\n }\n const date = Date.parse(header);\n if (Number.isFinite(date)) {\n return Math.max(0, date - Date.now());\n }\n return undefined;\n}\n\n/** Keep only the variables the document actually declares. */\nexport function pickDeclaredVariables(\n document: DocumentNode,\n variables: GraphQLVariables\n): GraphQLVariables {\n const declared = new Set(\n (getOperation(document).variableDefinitions ?? []).map(\n (definition) => definition.variable.name.value\n )\n );\n const picked: GraphQLVariables = {};\n for (const [name, value] of Object.entries(variables)) {\n if (declared.has(name)) {\n picked[name] = value;\n }\n }\n return picked;\n}\n\nfunction isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || status >= 500;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Hands the tolerated unresolvable links to the caller's reporter.\n *\n * Anything it throws is swallowed deliberately. This sits inside the retry\n * loop, so a reporter that failed would not merely surface as the fetch's\n * rejection — it would look like a failed request and send the very same\n * query again.\n */\nfunction reportUnresolvableLinks(errors: ContentfulGraphQLError[], context: RequestContext): void {\n if (!context.onUnresolvableLink) return;\n try {\n context.onUnresolvableLink(errors);\n } catch {\n // See above: a logger must not be able to fail — or repeat — a fetch.\n }\n}\n\n/**\n * Reads the `errors` array out of a failed response body.\n *\n * Contentful answers a query it cannot validate with HTTP 400 and the very\n * same error objects a 200 would have carried, locations included — so the\n * status alone is the least useful half of what it just told us.\n */\nasync function readGraphQLErrors(\n response: Response\n): Promise<ContentfulGraphQLError[] | undefined> {\n try {\n const payload = (await response.json()) as {\n errors?: ContentfulGraphQLError[];\n } | null;\n const errors = payload?.errors;\n return Array.isArray(errors) && errors.length > 0 ? errors : undefined;\n } catch {\n // A body that is not JSON tells us nothing the status has not already.\n return undefined;\n }\n}\n\n/**\n * Builds the message for a failure Contentful explained: the summary, the\n * messages themselves, and — when any of them says where in the query it\n * went wrong — that query with a caret under the spot.\n */\nfunction describeFailure(\n summary: string,\n errors: ContentfulGraphQLError[] | undefined,\n query: string,\n context: RequestContext\n): string {\n if (!errors || errors.length === 0) return summary;\n const message = `${summary} ${errors.map((error) => error.message).join('; ')}`;\n if (context.annotateQueryOnError === false) return message;\n const annotated = annotateQuery(query, errors);\n // The trailing newline keeps the stack trace off the last caret line.\n return annotated ? `${message}\\n\\n${annotated}\\n` : message;\n}\n\n/**\n * Sends one GraphQL request (with retries) and returns `data`.\n *\n * Rejects with a {@link FetchContentfulError} on any HTTP, network, or\n * GraphQL error. The one exception is a partial response whose only\n * complaint is an unresolvable link: that data is returned, with the holes\n * still in it, for `omitUnresolvedLinks` to clean up once the full response\n * (subqueries included) has been stitched together.\n */\nexport async function rawRequest(\n document: DocumentNode,\n variables: GraphQLVariables,\n context: RequestContext\n): Promise<Record<string, unknown>> {\n const query = printOutgoingQuery(document, context);\n const pickedVariables = pickDeclaredVariables(document, variables);\n const url = graphqlEndpoint(context.space, context.environment);\n const usePersistedQuery = context.automaticPersistedQueries === true;\n // Computed once up front (it's pure and identical on every attempt) rather\n // than inside the retryable unit below.\n const sha256Hash = usePersistedQuery ? await sha256Hex(query) : undefined;\n\n /**\n * One HTTP round trip. `includeQuery` controls only whether the `query`\n * field is present in the body — APQ's entire savings comes from omitting\n * it on the optimistic first attempt — everything else about handling the\n * response is identical either way.\n */\n async function send(includeQuery: boolean): Promise<Record<string, unknown>> {\n const body = JSON.stringify({\n ...(includeQuery ? { query } : {}),\n variables: pickedVariables,\n ...(sha256Hash ? { extensions: persistedQueryExtensions(sha256Hash) } : {})\n });\n\n let response: Response;\n try {\n const init: RequestInit & { next?: NextFetchOptions } = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${context.token}`\n },\n body\n };\n if (context.signal) init.signal = context.signal;\n if (context.cache) init.cache = context.cache;\n if (context.next) init.next = context.next;\n response = await context.fetch(url, init);\n } catch (cause) {\n throw new FetchContentfulError(\n `Network error while contacting Contentful: ${String(cause)}`,\n { code: 'NETWORK', query, retryable: true, cause }\n );\n }\n\n if (!response.ok) {\n const retryable = isRetryableStatus(response.status);\n // Only a rejected request has a query to explain; a 5xx body is a\n // server-side failure with nothing to point at, and this one is on\n // its way to another attempt anyway.\n const errors = retryable ? undefined : await readGraphQLErrors(response);\n throw new FetchContentfulError(\n describeFailure(\n `Contentful responded with HTTP ${response.status}.`,\n errors,\n query,\n context\n ),\n {\n code: 'HTTP',\n status: response.status,\n errors,\n query,\n retryable,\n retryAfterMs: retryable ? parseRetryAfter(response.headers.get('Retry-After')) : undefined\n }\n );\n }\n\n let payload: {\n data?: Record<string, unknown> | null;\n errors?: ContentfulGraphQLError[];\n };\n try {\n payload = (await response.json()) as typeof payload;\n } catch (cause) {\n throw new FetchContentfulError('Contentful returned an unreadable response body.', {\n code: 'NETWORK',\n query,\n retryable: true,\n cause\n });\n }\n\n if (payload.errors && payload.errors.length > 0) {\n // A response can be both errored and correct: an unresolvable link\n // reports content that is missing, not a query that was wrong, and\n // everything else Contentful sent is exactly what was asked for. It is\n // tolerated only when it is the *sole* complaint and there is data to\n // keep — a validation error alongside it means the query itself was\n // never answered, and the whole list goes into the rejection.\n const { unresolvable, fatal } = partitionUnresolvableLinks(payload.errors);\n const tolerable =\n context.unresolvableLinks !== 'error' &&\n fatal.length === 0 &&\n unresolvable.length > 0 &&\n isRecord(payload.data);\n\n if (!tolerable) {\n throw new FetchContentfulError(\n describeFailure('Contentful returned GraphQL errors:', payload.errors, query, context),\n { code: 'GRAPHQL', errors: payload.errors, query }\n );\n }\n reportUnresolvableLinks(unresolvable, context);\n }\n\n if (!payload.data || typeof payload.data !== 'object') {\n throw new FetchContentfulError('Contentful returned no data and no errors.', {\n code: 'GRAPHQL',\n query\n });\n }\n\n return payload.data;\n }\n\n // Once a hash-only attempt has actually needed the fallback, later retries\n // (of a transient failure on *that* fallback) skip straight to it rather\n // than re-running a probe already known to miss.\n let mustIncludeQuery = !usePersistedQuery;\n\n return withRetries(async () => {\n if (mustIncludeQuery) {\n return send(true);\n }\n try {\n return await send(false);\n } catch (error) {\n // Apollo's APQ spec never mandates a status for an unregistered hash,\n // and implementations disagree: Apollo Server answers HTTP 200 with\n // the marker in a GraphQL `errors` array (code: 'GRAPHQL'), Contentful\n // answers HTTP 404 with the same marker in the same shape of `errors`\n // (code: 'HTTP'). Either transport is a miss, not a failure, as long\n // as the marker itself is the precise thing being matched.\n if (\n isFetchContentfulError(error) &&\n (error.code === 'GRAPHQL' || error.code === 'HTTP') &&\n error.errors?.some(isPersistedQueryNotFoundError)\n ) {\n mustIncludeQuery = true;\n return await send(true);\n }\n throw error;\n }\n }, context.retry);\n}\n","/**\n * Downloads a space's GraphQL schema as SDL.\n *\n * This is the one network operation the CLI performs, and the only step\n * `tada-refresh` runs.\n */\n\nimport {\n buildClientSchema,\n getIntrospectionQuery,\n printSchema,\n type IntrospectionQuery\n} from 'graphql';\nimport { graphqlEndpoint } from '../client.js';\nimport { CliError, redact } from './errors.js';\n\nexport interface IntrospectOptions {\n space: string;\n environment: string;\n token: string;\n fetch: typeof fetch;\n}\n\n/** Trims a response body down to something safe to show in a terminal. */\nfunction bodySnippet(body: string, token: string): string {\n const cleaned = redact(body, token).trim();\n if (cleaned === '') return '(empty response body)';\n return cleaned.length > 300 ? `${cleaned.slice(0, 300)}…` : cleaned;\n}\n\n/**\n * Runs an introspection query against Contentful and returns the schema\n * printed as SDL, with a trailing newline.\n */\nexport async function fetchSchemaSdl(options: IntrospectOptions): Promise<string> {\n const url = graphqlEndpoint(options.space, options.environment);\n\n let response: Response;\n try {\n response = await options.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${options.token}`\n },\n body: JSON.stringify({ query: getIntrospectionQuery() })\n });\n } catch (cause) {\n throw new CliError(\n `Could not reach Contentful at ${url}: ${redact(String(cause), options.token)}`\n );\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new CliError(\n `Contentful rejected the access token (HTTP ${String(response.status)}).\\n` +\n ` Check that the token is a Content Delivery API token for space ` +\n `\"${options.space}\", and that it has access to environment ` +\n `\"${options.environment}\".`\n );\n }\n\n if (!response.ok) {\n const body = bodySnippet(await response.text().catch(() => ''), options.token);\n throw new CliError(`Contentful responded with HTTP ${String(response.status)}.\\n ${body}`);\n }\n\n let payload: {\n data?: IntrospectionQuery;\n errors?: Array<{ message?: string }>;\n };\n try {\n payload = (await response.json()) as typeof payload;\n } catch {\n throw new CliError('Contentful returned an unreadable response body.');\n }\n\n if (payload.errors && payload.errors.length > 0) {\n const messages = payload.errors.map((error) => error.message ?? 'unknown error').join('; ');\n throw new CliError(\n `Contentful returned GraphQL errors during introspection: ${redact(messages, options.token)}`\n );\n }\n\n if (!payload.data) {\n throw new CliError(\n 'Contentful returned no introspection data. Check the space and environment ids.'\n );\n }\n\n try {\n return `${printSchema(buildClientSchema(payload.data))}\\n`;\n } catch (cause) {\n throw new CliError(\n `Could not build a schema from Contentful's introspection response: ${String(cause)}`\n );\n }\n}\n","/**\n * Detects the consumer's package manager so the CLI can print an install\n * command they can paste as-is.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';\n\n/** Lockfiles in the order they are checked. */\nconst LOCKFILES: Array<[PackageManager, string]> = [\n ['bun', 'bun.lock'],\n ['bun', 'bun.lockb'],\n ['pnpm', 'pnpm-lock.yaml'],\n ['yarn', 'yarn.lock'],\n ['npm', 'package-lock.json']\n];\n\n/** Identifies the package manager from the lockfile in `cwd`. */\nexport function detectPackageManager(cwd: string): PackageManager {\n for (const [manager, lockfile] of LOCKFILES) {\n if (existsSync(join(cwd, lockfile))) return manager;\n }\n return 'npm';\n}\n\n/** The command that adds `packages` as dev dependencies. */\nexport function installCommand(manager: PackageManager, packages: string[]): string {\n const list = packages.join(' ');\n switch (manager) {\n case 'bun':\n return `bun add -d ${list}`;\n case 'pnpm':\n return `pnpm add -D ${list}`;\n case 'yarn':\n return `yarn add -D ${list}`;\n case 'npm':\n return `npm install -D ${list}`;\n }\n}\n\n/**\n * Returns the packages that are not declared anywhere in the consumer's\n * `package.json`. An unreadable or absent manifest means \"declare all of\n * them\" — printing an install command the user may not need is harmless,\n * silently skipping a required one is not.\n */\nexport function missingDependencies(cwd: string, packages: string[]): string[] {\n let manifest: Record<string, unknown>;\n try {\n manifest = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8')) as Record<\n string,\n unknown\n >;\n } catch {\n return [...packages];\n }\n\n const declared = new Set<string>();\n for (const field of [\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies'\n ]) {\n const section = manifest[field];\n if (typeof section === 'object' && section !== null) {\n for (const name of Object.keys(section)) declared.add(name);\n }\n }\n return packages.filter((name) => !declared.has(name));\n}\n","/**\n * A minimal JSONC scanner that records source offsets.\n *\n * `tsconfig.json` files are JSON with comments and trailing commas, and are\n * hand-maintained — reading one with a comment-stripping parser and writing\n * it back would destroy the author's comments and formatting. So instead of\n * parsing to a value and re-serializing, this scanner produces a tree of\n * nodes annotated with their offsets in the original text, which the patcher\n * uses to make surgical string edits.\n *\n * It is deliberately not a general JSON validator: it accepts the shapes it\n * needs to locate and rejects everything else, so the caller can fall back\n * to printing manual instructions rather than mangling a file it did not\n * understand.\n */\n\nexport class JsoncError extends Error {\n override name = 'JsoncError';\n}\n\nexport interface JsoncMember {\n /** The parsed key, e.g. `compilerOptions`. */\n key: string;\n /** Offset of the member's first character (the key's opening quote). */\n start: number;\n /** Offset just past the member's value. */\n end: number;\n value: JsoncNode;\n}\n\nexport type JsoncNode =\n | { kind: 'object'; start: number; end: number; members: JsoncMember[] }\n | { kind: 'array'; start: number; end: number; elements: JsoncNode[] }\n | { kind: 'string'; start: number; end: number; value: string }\n | { kind: 'literal'; start: number; end: number };\n\nconst WHITESPACE = ' \\t\\n\\r';\n\nclass Scanner {\n private index = 0;\n\n constructor(private readonly source: string) {}\n\n /** Skips whitespace, `//` line comments and `/* *\\/` block comments. */\n private skipTrivia(): void {\n for (;;) {\n while (\n this.index < this.source.length &&\n WHITESPACE.includes(this.source[this.index] as string)\n ) {\n this.index += 1;\n }\n if (this.source.startsWith('//', this.index)) {\n const newline = this.source.indexOf('\\n', this.index);\n this.index = newline === -1 ? this.source.length : newline + 1;\n continue;\n }\n if (this.source.startsWith('/*', this.index)) {\n const close = this.source.indexOf('*/', this.index + 2);\n if (close === -1) {\n throw new JsoncError('Unterminated block comment.');\n }\n this.index = close + 2;\n continue;\n }\n return;\n }\n }\n\n private peek(): string {\n this.skipTrivia();\n if (this.index >= this.source.length) {\n throw new JsoncError('Unexpected end of input.');\n }\n return this.source[this.index] as string;\n }\n\n private expect(character: string): void {\n if (this.peek() !== character) {\n throw new JsoncError(`Expected \"${character}\" at offset ${String(this.index)}.`);\n }\n this.index += 1;\n }\n\n parseRoot(): JsoncNode {\n const node = this.parseValue();\n this.skipTrivia();\n if (this.index !== this.source.length) {\n throw new JsoncError(`Unexpected trailing content at offset ${String(this.index)}.`);\n }\n return node;\n }\n\n private parseValue(): JsoncNode {\n const character = this.peek();\n if (character === '{') return this.parseObject();\n if (character === '[') return this.parseArray();\n if (character === '\"') return this.parseString();\n return this.parseLiteral();\n }\n\n private parseObject(): JsoncNode {\n const start = this.index;\n this.expect('{');\n const members: JsoncMember[] = [];\n for (;;) {\n if (this.peek() === '}') {\n this.index += 1;\n return { kind: 'object', start, end: this.index, members };\n }\n const memberStart = this.index;\n const key = this.parseString();\n this.expect(':');\n const value = this.parseValue();\n members.push({\n key: key.value,\n start: memberStart,\n end: value.end,\n value\n });\n if (this.peek() === ',') {\n this.index += 1;\n }\n }\n }\n\n private parseArray(): JsoncNode {\n const start = this.index;\n this.expect('[');\n const elements: JsoncNode[] = [];\n for (;;) {\n if (this.peek() === ']') {\n this.index += 1;\n return { kind: 'array', start, end: this.index, elements };\n }\n elements.push(this.parseValue());\n if (this.peek() === ',') {\n this.index += 1;\n }\n }\n }\n\n private parseString(): JsoncNode & { kind: 'string' } {\n this.skipTrivia();\n const start = this.index;\n if (this.source[start] !== '\"') {\n throw new JsoncError(`Expected a string at offset ${String(start)}.`);\n }\n this.index += 1;\n while (this.index < this.source.length) {\n const character = this.source[this.index];\n if (character === '\\\\') {\n this.index += 2;\n continue;\n }\n this.index += 1;\n if (character === '\"') {\n const end = this.index;\n return {\n kind: 'string',\n start,\n end,\n value: JSON.parse(this.source.slice(start, end)) as string\n };\n }\n }\n throw new JsoncError(`Unterminated string at offset ${String(start)}.`);\n }\n\n /** Numbers, `true`, `false` and `null` — read as an opaque token. */\n private parseLiteral(): JsoncNode {\n this.skipTrivia();\n const start = this.index;\n while (\n this.index < this.source.length &&\n !',]}'.includes(this.source[this.index] as string) &&\n !WHITESPACE.includes(this.source[this.index] as string)\n ) {\n this.index += 1;\n }\n if (this.index === start) {\n throw new JsoncError(`Unexpected character at offset ${String(start)}.`);\n }\n return { kind: 'literal', start, end: this.index };\n }\n}\n\n/** Parses JSONC into an offset-annotated tree. Throws {@link JsoncError}. */\nexport function parseJsonc(source: string): JsoncNode {\n return new Scanner(source).parseRoot();\n}\n\n/** Finds a member by key, or `undefined`. */\nexport function findMember(node: JsoncNode, key: string): JsoncMember | undefined {\n if (node.kind !== 'object') return undefined;\n return node.members.find((member) => member.key === key);\n}\n","/**\n * Idempotent, comment-preserving patching of a consumer's `tsconfig.json`.\n *\n * Every change is a surgical string edit computed from source offsets, so\n * comments, trailing commas and the author's formatting all survive. When\n * the file's shape isn't understood, nothing is written and the caller is\n * told to insert the block by hand — a mangled tsconfig is far worse than a\n * manual step.\n */\n\nimport { findMember, JsoncError, parseJsonc, type JsoncNode } from './jsonc.js';\n\n/** The TypeScript language-service plugin gql.tada drives. */\nexport const GRAPHQLSP_PLUGIN = '@0no-co/graphqlsp';\n\nexport interface TsconfigPluginConfig {\n /** Path to the SDL file, relative to the tsconfig. */\n schema: string;\n /** Path gql.tada writes its generated types to, relative to the tsconfig. */\n tadaOutputLocation: string;\n}\n\nexport type TsconfigPatchResult =\n /** The plugin was already configured exactly as requested. */\n | { status: 'unchanged' }\n /** `source` is the patched file content. */\n | { status: 'patched'; source: string }\n /** The file could not be patched safely; `reason` says why. */\n | { status: 'manual'; reason: string };\n\ninterface Edit {\n start: number;\n end: number;\n text: string;\n}\n\nfunction applyEdits(source: string, edits: Edit[]): string {\n let result = source;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n}\n\n/** The leading whitespace of the line containing `offset`. */\nfunction indentAt(source: string, offset: number): string {\n const lineStart = source.lastIndexOf('\\n', offset - 1) + 1;\n const line = source.slice(lineStart, offset);\n return line.slice(0, line.length - line.trimStart().length);\n}\n\n/** The file's own indentation unit, falling back to two spaces. */\nexport function detectIndentUnit(source: string): string {\n const match = /\\n([ \\t]+)\\S/.exec(source);\n return match?.[1] ?? ' ';\n}\n\n/** Renders the plugin entry, with `indent` as the entry's own indentation. */\nfunction renderPluginEntry(indent: string, unit: string, config: TsconfigPluginConfig): string {\n return [\n '{',\n `${indent}${unit}\"name\": ${JSON.stringify(GRAPHQLSP_PLUGIN)},`,\n `${indent}${unit}\"schema\": ${JSON.stringify(config.schema)},`,\n `${indent}${unit}\"tadaOutputLocation\": ${JSON.stringify(config.tadaOutputLocation)}`,\n `${indent}}`\n ].join('\\n');\n}\n\n/**\n * An edit that adds `\"key\": <value>` to an object node, matching the\n * object's existing layout.\n */\nfunction insertMember(\n source: string,\n object: JsoncNode & { kind: 'object' },\n key: string,\n renderValue: (indent: string) => string,\n unit: string\n): Edit {\n const last = object.members[object.members.length - 1];\n if (last) {\n const indent = indentAt(source, last.start);\n return {\n start: last.end,\n end: last.end,\n text: `,\\n${indent}\"${key}\": ${renderValue(indent)}`\n };\n }\n // `{}` — open it up onto its own lines.\n const closeIndent = indentAt(source, object.start);\n const indent = `${closeIndent}${unit}`;\n return {\n start: object.start + 1,\n end: object.end - 1,\n text: `\\n${indent}\"${key}\": ${renderValue(indent)}\\n${closeIndent}`\n };\n}\n\n/** Renders a `plugins` array containing only the graphqlsp entry. */\nfunction renderPluginsArray(indent: string, unit: string, config: TsconfigPluginConfig): string {\n const entryIndent = `${indent}${unit}`;\n return `[\\n${entryIndent}${renderPluginEntry(entryIndent, unit, config)}\\n${indent}]`;\n}\n\n/**\n * Adds — or updates in place — the `@0no-co/graphqlsp` entry in\n * `compilerOptions.plugins`.\n *\n * Running this twice with the same configuration is a no-op: the second run\n * reports `unchanged`.\n */\nexport function patchTsconfig(source: string, config: TsconfigPluginConfig): TsconfigPatchResult {\n let root: JsoncNode;\n try {\n root = parseJsonc(source);\n } catch (cause) {\n /* v8 ignore next 3 -- defensive: only JsoncError can be thrown here */\n const reason = cause instanceof JsoncError ? cause.message : String(cause);\n return { status: 'manual', reason: `could not be parsed (${reason})` };\n }\n\n if (root.kind !== 'object') {\n return { status: 'manual', reason: 'its root is not an object' };\n }\n\n const unit = detectIndentUnit(source);\n const compilerOptions = findMember(root, 'compilerOptions');\n\n // No `compilerOptions` at all — add it, with the plugin inside.\n if (!compilerOptions) {\n const edit = insertMember(\n source,\n root,\n 'compilerOptions',\n (indent) =>\n `{\\n${indent}${unit}\"plugins\": ${renderPluginsArray(\n `${indent}${unit}`,\n unit,\n config\n )}\\n${indent}}`,\n unit\n );\n return { status: 'patched', source: applyEdits(source, [edit]) };\n }\n\n if (compilerOptions.value.kind !== 'object') {\n return { status: 'manual', reason: '\"compilerOptions\" is not an object' };\n }\n\n const plugins = findMember(compilerOptions.value, 'plugins');\n\n // `compilerOptions` without `plugins` — add the array.\n if (!plugins) {\n const edit = insertMember(\n source,\n compilerOptions.value,\n 'plugins',\n (indent) => renderPluginsArray(indent, unit, config),\n unit\n );\n return { status: 'patched', source: applyEdits(source, [edit]) };\n }\n\n if (plugins.value.kind !== 'array') {\n return { status: 'manual', reason: '\"compilerOptions.plugins\" is not an array' };\n }\n\n const existing = plugins.value.elements.find((element) => {\n const name = findMember(element, 'name');\n return name?.value.kind === 'string' && name.value.value === GRAPHQLSP_PLUGIN;\n });\n\n // A graphqlsp entry is already there — update its fields in place rather\n // than appending a second, conflicting one.\n if (existing) {\n /* v8 ignore next 3 -- `findMember` only matches object elements */\n if (existing.kind !== 'object') {\n return { status: 'manual', reason: 'its graphqlsp plugin entry is not an object' };\n }\n const edits: Edit[] = [];\n for (const [key, value] of [\n ['schema', config.schema],\n ['tadaOutputLocation', config.tadaOutputLocation]\n ] as const) {\n const member = findMember(existing, key);\n if (member) {\n edits.push({\n start: member.value.start,\n end: member.value.end,\n text: JSON.stringify(value)\n });\n } else {\n edits.push(insertMember(source, existing, key, () => JSON.stringify(value), unit));\n }\n }\n const patched = applyEdits(source, edits);\n return patched === source ? { status: 'unchanged' } : { status: 'patched', source: patched };\n }\n\n // Unrelated plugins are configured — append, never replace.\n const last = plugins.value.elements[plugins.value.elements.length - 1];\n if (last) {\n const indent = indentAt(source, last.start);\n return {\n status: 'patched',\n source: applyEdits(source, [\n {\n start: last.end,\n end: last.end,\n text: `,\\n${indent}${renderPluginEntry(indent, unit, config)}`\n }\n ])\n };\n }\n\n // An empty `plugins: []`.\n const closeIndent = indentAt(source, plugins.value.start);\n const entryIndent = `${closeIndent}${unit}`;\n return {\n status: 'patched',\n source: applyEdits(source, [\n {\n start: plugins.value.start + 1,\n end: plugins.value.end - 1,\n text: `\\n${entryIndent}${renderPluginEntry(entryIndent, unit, config)}\\n${closeIndent}`\n }\n ])\n };\n}\n\n/** The block to print when the caller has to edit the file by hand. */\nexport function manualPluginBlock(config: TsconfigPluginConfig): string {\n return renderPluginEntry('', ' ', config);\n}\n","/**\n * The `fetch-contentful` CLI: `tada-init` and `tada-refresh`.\n *\n * Everything is driven through {@link CliIo} so the whole command surface is\n * testable without spawning a process — including the guarantee that a\n * `--dry-run` writes nothing and that the access token never reaches the\n * terminal.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport { readEnvSettings } from '../env.js';\nimport { parseArgs, type ParsedArgs } from './args.js';\nimport { formatBytes, lineDiff } from './diff.js';\nimport { describeEnvFiles, loadEnvFiles, type EnvFileLoad } from './env-file.js';\nimport { CliError, redact } from './errors.js';\nimport { PACKAGE_NAME, relativeSpecifier, renderGraphqlModule } from './graphql-module.js';\nimport { fetchSchemaSdl } from './introspect.js';\nimport { detectPackageManager, installCommand, missingDependencies } from './package-manager.js';\nimport { GRAPHQLSP_PLUGIN, manualPluginBlock, patchTsconfig } from './tsconfig.js';\n\nexport interface CliIo {\n /** Directory the command runs against. */\n cwd: string;\n fetch: typeof fetch;\n stdout: (line: string) => void;\n stderr: (line: string) => void;\n}\n\n/** Packages the generated setup needs the consumer to install. */\nconst REQUIRED_PEERS = ['gql.tada', GRAPHQLSP_PLUGIN];\n\nconst DEFAULTS = {\n schemaPath: './contentful-schema.graphql',\n tadaOutput: './src/contentful-env.d.ts',\n graphqlFile: './src/graphql.ts',\n tsconfig: './tsconfig.json'\n} as const;\n\n/** Width of the verb column in the action log. */\nconst VERB_WIDTH = 12;\n\nconst HELP = `fetch-contentful — gql.tada setup for a Contentful space\n\nUsage:\n fetch-contentful tada-init [options] Set up gql.tada in this project\n fetch-contentful tada-refresh [options] Re-download the schema only\n\nConfiguration (flags win over environment variables):\n --space <id> CONTENTFUL_SPACE_ID\n --environment <id> CONTENTFUL_ENVIRONMENT (default \"master\")\n --token <token> CONTENTFUL_ACCESS_TOKEN (Content Delivery API)\n\nPaths (relative to the working directory):\n --schema-path <path> default ${DEFAULTS.schemaPath}\n --tada-output <path> default ${DEFAULTS.tadaOutput}\n --graphql-file <path> default ${DEFAULTS.graphqlFile}\n --tsconfig <path> default ${DEFAULTS.tsconfig}\n\nOther:\n --dry-run Show what would change; write nothing\n --force Overwrite an existing graphql file (tada-init)\n --cwd <path> Run against another directory\n --env-file <path> Read this file instead of .env.local / .env\n -h, --help Show this help\n\nConfiguration is read from .env.local, then .env, then the shell — anything\nalready exported wins over a file, and flags win over everything. The\nNEXT_PUBLIC_-prefixed names are accepted as fallbacks, exactly as the\nlibrary reads them at runtime.`;\n\n/* ------------------------------------------------------------------ */\n/* Configuration */\n/* ------------------------------------------------------------------ */\n\ninterface Config {\n space: string;\n environment: string;\n token: string;\n}\n\nfunction resolveConfig(args: ParsedArgs, envFiles: EnvFileLoad): Config {\n const env = readEnvSettings();\n const space = args.values.space ?? env.space;\n // Introspection is a Content Delivery API operation, so there is only one\n // token in play here and the flag stays plain `--token`.\n const token = args.values.token ?? env.deliveryToken;\n const environment = args.values.environment ?? env.environment ?? 'master';\n\n const missing: string[] = [];\n if (!space) {\n missing.push(\n 'space (pass --space, or set CONTENTFUL_SPACE_ID / NEXT_PUBLIC_CONTENTFUL_SPACE_ID)'\n );\n }\n if (!token) {\n missing.push(\n 'access token (pass --token, or set CONTENTFUL_ACCESS_TOKEN / NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN)'\n );\n }\n if (!space || !token) {\n throw new CliError(\n `Missing required Contentful configuration:\\n - ${missing.join(\n '\\n - '\n )}\\n${describeEnvFiles(envFiles)}`\n );\n }\n return { space, environment, token };\n}\n\ninterface Paths {\n root: string;\n schema: string;\n tadaOutput: string;\n graphqlFile: string;\n tsconfig: string;\n}\n\nfunction resolvePaths(args: ParsedArgs, io: CliIo): Paths {\n const root = resolve(io.cwd, args.values.cwd ?? '.');\n const at = (value: string | undefined, fallback: string): string =>\n resolve(root, value ?? fallback);\n return {\n root,\n schema: at(args.values['schema-path'], DEFAULTS.schemaPath),\n tadaOutput: at(args.values['tada-output'], DEFAULTS.tadaOutput),\n graphqlFile: at(args.values['graphql-file'], DEFAULTS.graphqlFile),\n tsconfig: at(args.values.tsconfig, DEFAULTS.tsconfig)\n };\n}\n\n/** A path as the user would type it, for display. */\nfunction display(root: string, path: string): string {\n const shown = relative(root, path);\n return shown === '' || shown.startsWith('..') || isAbsolute(shown) ? path : shown;\n}\n\nfunction readIfExists(path: string): string | undefined {\n return existsSync(path) ? readFileSync(path, 'utf8') : undefined;\n}\n\n/* ------------------------------------------------------------------ */\n/* Planned changes */\n/* ------------------------------------------------------------------ */\n\ntype Preview = 'size' | 'diff' | 'content';\n\ntype Action =\n | {\n kind: 'write';\n path: string;\n before: string | undefined;\n after: string;\n preview: Preview;\n }\n | { kind: 'unchanged'; path: string }\n | { kind: 'skip'; path: string; reason: string }\n | { kind: 'manual'; path: string; reason: string; block: string };\n\n/** Plans the schema download, shared by both commands. */\nfunction planSchema(sdl: string, paths: Paths): Action {\n const before = readIfExists(paths.schema);\n if (before === sdl) return { kind: 'unchanged', path: paths.schema };\n return {\n kind: 'write',\n path: paths.schema,\n before,\n after: sdl,\n preview: 'size'\n };\n}\n\nfunction planTsconfig(paths: Paths): Action {\n const before = readIfExists(paths.tsconfig);\n if (before === undefined) {\n throw new CliError(\n `No tsconfig at ${display(paths.root, paths.tsconfig)}. ` +\n 'Pass --tsconfig if it lives elsewhere.'\n );\n }\n const config = {\n schema: relativeSpecifier(paths.tsconfig, paths.schema),\n tadaOutputLocation: relativeSpecifier(paths.tsconfig, paths.tadaOutput)\n };\n const result = patchTsconfig(before, config);\n if (result.status === 'unchanged') {\n return { kind: 'unchanged', path: paths.tsconfig };\n }\n if (result.status === 'manual') {\n return {\n kind: 'manual',\n path: paths.tsconfig,\n reason: result.reason,\n block: manualPluginBlock(config)\n };\n }\n return {\n kind: 'write',\n path: paths.tsconfig,\n before,\n after: result.source,\n preview: 'diff'\n };\n}\n\nfunction planGraphqlModule(paths: Paths, force: boolean): Action {\n const before = readIfExists(paths.graphqlFile);\n const after = renderGraphqlModule(relativeSpecifier(paths.graphqlFile, paths.tadaOutput));\n if (before !== undefined && !force) {\n return {\n kind: 'skip',\n path: paths.graphqlFile,\n reason: 'already exists; pass --force to overwrite'\n };\n }\n if (before === after) return { kind: 'unchanged', path: paths.graphqlFile };\n return {\n kind: 'write',\n path: paths.graphqlFile,\n before,\n after,\n preview: 'content'\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Reporting and applying */\n/* ------------------------------------------------------------------ */\n\nfunction logAction(io: CliIo, verb: string, detail: string): void {\n io.stdout(` ${verb.padEnd(VERB_WIDTH)} ${detail}`);\n}\n\nfunction report(action: Action, paths: Paths, dryRun: boolean, io: CliIo): void {\n const name = display(paths.root, action.path);\n if (action.kind === 'unchanged') {\n logAction(io, 'unchanged', name);\n return;\n }\n if (action.kind === 'skip') {\n logAction(io, 'skipped', `${name} (${action.reason})`);\n return;\n }\n if (action.kind === 'manual') {\n logAction(io, 'manual', `${name} (${action.reason})`);\n return;\n }\n\n const created = action.before === undefined;\n const verb = dryRun\n ? created\n ? 'would create'\n : 'would update'\n : created\n ? 'created'\n : 'updated';\n const size =\n action.preview === 'size' ? ` (${formatBytes(Buffer.byteLength(action.after))})` : '';\n logAction(io, verb, `${name}${size}`);\n\n if (!dryRun) return;\n\n if (action.preview === 'content') {\n for (const line of action.after.replace(/\\n$/, '').split('\\n')) {\n io.stdout(` + ${line}`);\n }\n return;\n }\n\n // Everything below compares against the file already on disk.\n if (action.before === undefined) return;\n\n if (action.preview === 'diff') {\n for (const line of lineDiff(action.before, action.after)) {\n io.stdout(` ${line}`);\n }\n return;\n }\n\n // Exact counts, not rounded ones: two files that both format as\n // \"23.1 kB\" would otherwise look identical.\n const beforeBytes = Buffer.byteLength(action.before);\n const afterBytes = Buffer.byteLength(action.after);\n const delta = afterBytes - beforeBytes;\n io.stdout(\n ` ${String(beforeBytes)} → ${String(afterBytes)} bytes (${\n delta >= 0 ? '+' : ''\n }${String(delta)})`\n );\n}\n\nfunction apply(action: Action): void {\n if (action.kind !== 'write') return;\n mkdirSync(dirname(action.path), { recursive: true });\n writeFileSync(action.path, action.after, 'utf8');\n}\n\n/** Prints the manual tsconfig block, when patching was not safe. */\nfunction reportManual(action: Action, paths: Paths, io: CliIo): void {\n if (action.kind !== 'manual') return;\n io.stdout('');\n io.stdout(`${display(paths.root, action.path)} was left untouched because ${action.reason}.`);\n io.stdout('Add this entry to \"compilerOptions.plugins\" by hand:');\n io.stdout('');\n for (const line of action.block.split('\\n')) io.stdout(` ${line}`);\n}\n\nfunction reportPeers(paths: Paths, io: CliIo): void {\n const missing = missingDependencies(paths.root, REQUIRED_PEERS);\n if (missing.length === 0) return;\n io.stdout('');\n io.stdout(`Install the packages the generated setup needs:`);\n io.stdout(` ${installCommand(detectPackageManager(paths.root), missing)}`);\n}\n\n/* ------------------------------------------------------------------ */\n/* Commands */\n/* ------------------------------------------------------------------ */\n\nasync function tadaInit(args: ParsedArgs, io: CliIo): Promise<number> {\n // Paths first: the env files are read from the directory the command\n // targets, which `--cwd` can move.\n const paths = resolvePaths(args, io);\n const envFiles = loadEnvFiles(paths.root, args.values['env-file']);\n const config = resolveConfig(args, envFiles);\n const dryRun = args.flags.has('dry-run');\n\n // Planned before the network call, so a missing tsconfig fails fast.\n const tsconfigAction = planTsconfig(paths);\n const sdl = await fetchSchemaSdl({ ...config, fetch: io.fetch });\n\n // Everything is planned before anything is written, so a failure part-way\n // through cannot leave a half-configured project behind.\n const actions = [\n planSchema(sdl, paths),\n tsconfigAction,\n planGraphqlModule(paths, args.flags.has('force'))\n ];\n\n io.stdout(\n dryRun\n ? `Dry run — nothing will be written (space ${config.space}, environment ${config.environment}).`\n : `Configuring gql.tada for space ${config.space}, environment ${config.environment}.`\n );\n for (const action of actions) {\n if (!dryRun) apply(action);\n report(action, paths, dryRun, io);\n }\n for (const action of actions) reportManual(action, paths, io);\n\n reportPeers(paths, io);\n\n // A dry run changed nothing, so there is nothing to do next.\n if (dryRun) return 0;\n\n io.stdout('');\n io.stdout('Next steps:');\n io.stdout(` 1. Restart the TypeScript server so ${GRAPHQLSP_PLUGIN} loads.`);\n io.stdout(\n ` 2. Write a query with the \\`graphql\\` helper from ${display(paths.root, paths.graphqlFile)},`\n );\n io.stdout(` then pass it to fetchContentful from ${PACKAGE_NAME}.`);\n io.stdout(' Result and variable types are inferred from the document.');\n io.stdout(' 3. After a content-model change, run `fetch-contentful tada-refresh`.');\n return 0;\n}\n\nasync function tadaRefresh(args: ParsedArgs, io: CliIo): Promise<number> {\n // Paths first: the env files are read from the directory the command\n // targets, which `--cwd` can move.\n const paths = resolvePaths(args, io);\n const envFiles = loadEnvFiles(paths.root, args.values['env-file']);\n const config = resolveConfig(args, envFiles);\n const dryRun = args.flags.has('dry-run');\n\n const sdl = await fetchSchemaSdl({ ...config, fetch: io.fetch });\n const action = planSchema(sdl, paths);\n\n if (action.kind === 'unchanged') {\n // Leave the file's mtime alone: an unchanged schema should not show up\n // in `git status`, and should not invalidate a build cache.\n io.stdout(\n `Schema is already up to date — ${display(paths.root, paths.schema)} left untouched.`\n );\n return 0;\n }\n\n if (!dryRun) apply(action);\n report(action, paths, dryRun, io);\n return 0;\n}\n\n/* ------------------------------------------------------------------ */\n/* Entry point */\n/* ------------------------------------------------------------------ */\n\nasync function dispatch(argv: string[], io: CliIo): Promise<number> {\n const args = parseArgs(argv);\n // Accept both `tada-init` and `tada init`.\n const command = args.positionals.join('-');\n\n if (args.flags.has('help') || command === '' || command === 'help') {\n io.stdout(HELP);\n return 0;\n }\n if (command === 'tada-init') return tadaInit(args, io);\n if (command === 'tada-refresh') return tadaRefresh(args, io);\n\n throw new CliError(\n `Unknown command \"${args.positionals.join(\n ' '\n )}\". Run with --help to see the available commands.`\n );\n}\n\n/** Any token reachable from the environment or the command line. */\nfunction knownTokens(argv: string[]): Array<string | undefined> {\n const env = readEnvSettings();\n const tokens: Array<string | undefined> = [env.deliveryToken, env.previewToken];\n for (const [index, argument] of argv.entries()) {\n if (argument.startsWith('--token=')) tokens.push(argument.slice(8));\n else if (argument === '--token') tokens.push(argv[index + 1]);\n }\n return tokens;\n}\n\n/**\n * Runs the CLI and resolves with the process exit code. Never rejects, and\n * never prints the access token.\n */\nexport async function run(argv: string[], io: CliIo): Promise<number> {\n try {\n return await dispatch(argv, io);\n } catch (error) {\n const raw = error instanceof CliError ? error.message : `Unexpected failure: ${String(error)}`;\n let message = raw;\n for (const token of knownTokens(argv)) message = redact(message, token);\n io.stderr(`error: ${message}`);\n return 1;\n }\n}\n","#!/usr/bin/env node\n/**\n * The `fetch-contentful` binary.\n *\n * A thin shell around {@link run}: everything worth testing lives there,\n * reached without spawning a process.\n */\nimport { run } from './run.js';\n\nconst code = await run(process.argv.slice(2), {\n cwd: process.cwd(),\n fetch: globalThis.fetch,\n stdout: (line) => process.stdout.write(`${line}\\n`),\n stderr: (line) => process.stderr.write(`${line}\\n`)\n});\nprocess.exitCode = code;\n"]}
|