Skip to content

fix: plugin bugs found while documenting - #18

Merged
mvantellingen merged 14 commits into
mainfrom
fix/plugin-bugs
Oct 26, 2026
Merged

mvantellingen merged 14 commits into
mainfrom
fix/plugin-bugs

Conversation

@mvantellingen

Copy link
Copy Markdown
Member

Fixes the bugs found while documenting the plugins in #17 (merged), and updates the README "notes and limitations" sections accordingly. One commit per fix.

k6

  • graphQLTag (default) / external: missing DocumentNode import — the Requester type used DocumentNode without importing it. The visitor now adds the import (from documentNodeImport, respecting useTypeImports) for every mode except string.
  • documentMode: "string": undefined TypedDocumentString — the class is now emitted in the output, the same class typed-document-node / the client preset generate (a String subclass), without the dependency on @graphql-typed-document-node/core (__apiType is structurally compatible with DocumentTypeDecoration). Operation documents are cast to TypedDocumentString<Result, Variables> and the requester gets doc: TypedDocumentString<R, V>. Checked that the class serializes to the query string with JSON.stringify in k6 itself (k6 v2.3).
  • Duplicate declarations with typescript + typescript-operations v6 — not caused by this plugin: typescript-operations v6 generates the enum and input types itself, so they clash with the typescript plugin's. The k6 plugin only emits documents and the SDK (now asserted in a test). The README documents to use typescript-operations on its own.
  • Tests — replaced the dummy test: snapshots of the output for every documentMode, and a type check that compiles the typescript-operations + k6 output together with a k6 script using the SDK (with @ts-expect-error cases for missing variables / bad enum values) with tsc. New devDependencies: @graphql-codegen/typescript-operations, @types/k6, @types/node, graphql-tag.

bruno

  • Whole source document per request — a request now contains only its operation followed by the fragments it transitively uses (also from other documents), each once, printed with graphql's print.
  • clean: true emptied the output directory — now only removes the .bru files (except folder.bru) in queries/, mutations/ and subscriptions/ and those folders when empty. bruno.json, collection.bru, environments and other files are never touched. Tested.
  • Subscriptions in mutations/ — now written to subscriptions/.
  • Hardcoded URL / auth — new url and auth options, defaulting to {{graphql-gateway}}/graphql and none.
  • prettier bundled — prettier was only needed to format the request body; with print it is no longer needed, so it is dropped entirely. dist/index.js: 5.0 MB (+ 7.5 MB source map) → 6.9 kB.
  • Tests write to a temp dir instead of the tracked src/__output__ (removed).

typedefs

  • extend schema: intended (it works with plain schemas: graphql's buildSchema and makeExecutableSchema accept extend schema without a schema definition, and it merges with other type defs), but the implementation prefixed the whole printed schema with extend. That broke schemas without root types (extend type A ..., extend directive ...) and schemas with a description (invalid syntax). Now only the schema definition is converted to a schema extension (description dropped, extensions cannot have one).
  • New extendSchema option (default true) to print a plain schema { ... } instead.
  • Added tests (the package had none), including round-tripping the output through buildSchema.

Changesets

  • k6: patch (fixes).
  • bruno: minor — new options, and output changes (fragments, subscriptions/ folder, clean semantics, no comments in body); noted in the changeset.
  • typedefs: minor — new option; whitespace of the first line changes ( extend \tschema { → \textend schema {).

pnpm check, pnpm build (incl. publint) and pnpm test:ci pass locally.

The Requester type refers to DocumentNode, but the base visitor only
imports it for the documentNode modes. Import it for graphQLTag and
external as well, respecting documentNodeImport and useTypeImports.
documentMode string referenced a TypedDocumentString class that was
never defined. Emit the class (as typed-document-node and the client
preset do, without the @graphql-typed-document-node/core dependency),
type the operation documents with their result and variables, and pass
the TypedDocumentString to the requester.
Replace the dummy test with snapshots of the generated output for every
documentMode, and compile the output of typescript-operations plus this
plugin, together with a k6 script using the SDK, with tsc.
… setup

typescript-operations v6 generates the enum and input types itself, so
combining it with the typescript plugin duplicates those declarations;
this plugin does not emit schema types. Document to use
typescript-operations on its own, and document documentMode string.
Every request embedded the complete source document (all operations and
fragments in it), followed by the used fragments, so fragments defined
in the same document were included twice. Emit only the operation
itself followed by the fragments it transitively uses, each once.
prettier was used at runtime but only a devDependency, so it was bundled
into dist (5.0 MB index.js plus a 7.5 MB source map). The request body
is now printed with graphql's print, which already formats the
operation and fragments, so prettier is no longer needed. dist/index.js
is now about 7 kB.
Subscriptions were written to the mutations/ folder.
clean: true emptied the whole output directory, which removed bruno.json
and environments when the output pointed to the collection root. Only
remove the .bru files (except folder.bru) in the queries/, mutations/
and subscriptions/ folders the plugin writes to, and those folders when
they are empty afterwards.
Add the url and auth options, defaulting to the previously hardcoded
{{graphql-gateway}}/graphql and none. Make all options optional and
export the BrunoPluginConfig type.
Test the generated requests of several operations per document
(fragments from other documents, subscriptions), the url, auth, headers
and defaults options, and that clean only removes generated requests.
Write the output to a temporary directory instead of the tracked
src/__output__.
The output prefixed the whole printed schema with 'extend', which only
worked when it started with a schema definition without description. A
schema without root types resulted in 'extend type ...' or 'extend
directive ...', and a schema description in invalid syntax. Convert
just the schema definition to a schema extension (dropping its
description, which extensions cannot have). Plain schemas keep working:
graphql's buildSchema and makeExecutableSchema accept 'extend schema'
without a schema definition.
Set extendSchema: false to print a plain schema definition (including
its description) instead of 'extend schema'. Defaults to true, the
previous behaviour.
@mvantellingen
mvantellingen merged commit 8ce45bb into main Oct 26, 2026
6 checks passed
@mvantellingen
mvantellingen deleted the fix/plugin-bugs branch October 26, 2026 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant