Skip to content

Commit

Permalink
fix(cli-utils): Add missing deduplication and normalization to `gener…
Browse files Browse the repository at this point in the history
…ate persisted` output (#275)
  • Loading branch information
kitten committed Apr 28, 2024
1 parent 6bc8424 commit c5e82be
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-boxes-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@gql.tada/cli-utils": patch
---

Add missing fragment deduplication to `generate persisted` command's output and add document normalization, which can be disabled using the `--disable-normalization` argument.
2 changes: 1 addition & 1 deletion packages/cli-utils/src/commands/generate-output/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface OutputOptions {
forceTSFormat?: boolean;
/** Whether to disable the optimized output format for `.d.ts` files.
* @defaultValue `false` */
disablePreprocessing: boolean;
disablePreprocessing?: boolean;
/** The filename to write the cache file to.
* @defaultValue The `tadaTurboLocation` configuration option */
output: string | undefined;
Expand Down
5 changes: 5 additions & 0 deletions packages/cli-utils/src/commands/generate-persisted/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class GeneratePersisted extends Command {
description: 'Specify the `tsconfig.json` used to read, unless `--output` is passed.',
});

disableNormalization = Option.Boolean('--disable-normalization', false, {
description: 'Disables normalizing of GraphQL documents (parsing then printing documents)',
});

failOnWarn = Option.Boolean('--fail-on-warn', false, {
description: 'Triggers an error and a non-zero exit code if any warnings have been reported',
});
Expand All @@ -25,6 +29,7 @@ export class GeneratePersisted extends Command {
const tty = initTTY();
const result = await tty.start(
run(tty, {
disableNormalization: this.disableNormalization,
failOnWarn: this.failOnWarn,
output: this.output,
tsconfig: this.tsconfig,
Expand Down
8 changes: 8 additions & 0 deletions packages/cli-utils/src/commands/generate-persisted/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import type { PersistedDocument } from './types';
import * as logger from './logger';

export interface PersistedOptions {
/** Whether to disable normalization of GraphQL documents in the output.
* @defaultValue `false`
* @remarks
* Normalizing a GraphQL document means to parse then print them, which
* removes comments and normalizes formatting.
*/
disableNormalization?: boolean;
/** The `tsconfig.json` to use for configurations and the TypeScript program.
* @defaultValue A `tsconfig.json` in the current or any parent directory. */
tsconfig: string | undefined;
Expand All @@ -35,6 +42,7 @@ export async function* run(tty: TTY, opts: PersistedOptions): AsyncIterable<Comp
if (tty.isInteractive) yield logger.runningPersisted();

const generator = runPersisted({
disableNormalization: !!opts.disableNormalization,
rootPath: configResult.rootPath,
configPath: configResult.configPath,
pluginConfig,
Expand Down
37 changes: 32 additions & 5 deletions packages/cli-utils/src/commands/generate-persisted/thread.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ts from 'typescript';
import { print } from '@0no-co/graphql.web';
import { parse, print } from '@0no-co/graphql.web';

import type { FragmentDefinitionNode } from '@0no-co/graphql.web';
import type { GraphQLSPConfig } from '@gql.tada/internal';
Expand All @@ -18,6 +18,7 @@ import { expose } from '../../threads';
import type { PersistedSignal, PersistedWarning, PersistedDocument } from './types';

export interface PersistedParams {
disableNormalization: boolean;
rootPath: string;
configPath: string;
pluginConfig: GraphQLSPConfig;
Expand Down Expand Up @@ -139,18 +140,44 @@ async function* _runPersisted(params: PersistedParams): AsyncIterableIterator<Pe
continue;
}

const fragments: FragmentDefinitionNode[] = [];
const fragmentDefs: FragmentDefinitionNode[] = [];
const operation = foundNode.arguments[0].getText().slice(1, -1);
if (foundNode.arguments[1] && ts.isArrayLiteralExpression(foundNode.arguments[1])) {
unrollTadaFragments(
foundNode.arguments[1],
fragments,
fragmentDefs,
container.buildPluginInfo(params.pluginConfig)
);
}

let document = operation;
for (const fragment of fragments) document += '\n\n' + print(fragment);
const seen = new Set<string>();
let document: string;
if (params.disableNormalization) {
document = operation;
} else {
try {
document = print(parse(operation));
} catch (_error) {
warnings.push({
message:
`The referenced document of "${referencingNode.getText()}" could not be parsed.\n` +
'Run `check` to see specific validation errors.',
file: position.fileName,
line: position.line,
col: position.col,
});
continue;
}
}

// NOTE: Update graphqlsp not to pre-parse fragments, which also swallows errors
for (const fragmentDef of fragmentDefs) {
const printedFragmentDef = print(fragmentDef);
if (!seen.has(printedFragmentDef)) {
document += '\n\n' + print(fragmentDef);
seen.add(printedFragmentDef);
}
}

documents.push({
schemaName: call.schema,
Expand Down
2 changes: 2 additions & 0 deletions website/reference/gql-tada-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ When this command is run inside a GitHub Action, [workflow commands](https://doc

| Option | Description |
| ------------------- | ------------------------------------------------------------------------------------------------ |
| `--disable-normalization` | Whether to disable normalizing the GraphQL document. (Default: false) |
| `--tsconfig,-c` | Optionally, a `tsconfig.json` file to use instead of an automatically discovered one. |
| `--fail-on-warn,-w` | Triggers an error and a non-zero exit code if any warnings have been reported. |
| `--output,-o` | Specify where to output the file to. (Default: The `tadaPersistedLocation` configuration option) |
Expand Down Expand Up @@ -172,6 +173,7 @@ await generateOutput({

| | Description |
| ------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `disableNormalization` | Disables normalizing the GraphQL document |
| `output` option | The filename to write the persisted JSON manifest file to (Default: the `tadaPersistedLocation` configuration option) |
| `tsconfig` option | The `tsconfig.json` to use instead of an automatically discovered one. |
| `failOnWarn` option | Whether to throw an error instead of logging warnings. |
Expand Down

0 comments on commit c5e82be

Please sign in to comment.