Skip to content

Instantly share code, notes, and snippets.

@nilshartmann
Created April 30, 2018 16:14
Show Gist options
  • Save nilshartmann/39e6dc755c91a60c1dc1911180e154b5 to your computer and use it in GitHub Desktop.
Save nilshartmann/39e6dc755c91a60c1dc1911180e154b5 to your computer and use it in GitHub Desktop.
Transform Apollo GraphQL Query Types

Currently when using apollo-codegen to generate TypeScript types for query definitions (ts-modern target), the generated types are called as the query name. So if you have a GetUserQuery your basetype is called GetUserQuery.
But in fact the type does not desribe the actual query, but the outcome, the result of the query, so it would be better if the type would have been named like UserQueryResult.

There is an issue in apollo-codegen where this issue is discussed: apollographql/apollo-tooling#315

But as there is currently no progress I wrote a little codemod (using jscodeshift) that renames the types after they have been generated. You can find the transform.js script below.

Please make sure that you have installed:

  • jscodeshift
  • [email protected] (the babylon version shipped with jscodeshift does not work with TypeScript correctly).

You can run the generator (in "dry" mode) like this:

yarn jscodeshift src --dry --extensions ts -t scripts/transform.js

It transforms all Query-files in all __generated__ folders.

So complete steps are:

  1. (optional) run apollo-codegen introspect-schema . . . to get the newest GraphQL Schema for your API
  2. run apollo-codegen generate . . . --target ts-modern to generate the TypeScript types for your queries
  3. run yarn jscodeshift . . . to modify the generated query types

Note: this works in my scenario, don't know if this is really a "general" solution. Please feel free to conact me with ideas etc

@nilshartmann

const path = require("path");
const babylon = require("babylon");
// https://github.com/facebook/jscodeshift#transform-module
function transformer(file, api) {
// file.path: src/x/y/__generated__/ZzzQuery.ts
if (file.path.indexOf("__generated__") === -1) {
return;
}
const fileName = path.basename(file.path);
const queryName = fileName.substring(0, fileName.indexOf(".ts")); // + "Query";
const queryResultName = queryName + "Result";
console.log(`[${fileName}] Renaming '${queryName}' to '${queryResultName}'`);
const j = api.jscodeshift;
return j(file.source)
.find(j.Identifier)
.filter(p => p.node.name.indexOf(queryName + "_") !== -1 || p.node.name.endsWith(queryName))
.forEach(path => {
j(path).replaceWith(j.identifier(path.node.name.replace(queryName, queryResultName)));
})
.toSource();
}
const options = {
sourceType: "module",
allowImportExportEverywhere: true,
allowReturnOutsideFunction: true,
plugins: ["typescript"]
};
const parser = {
parse: function(source) {
return babylon.parse(source, options);
}
};
export { parser, transformer as default };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment