Graphics Codegen v 2の新機能


This article was published on 2021-08-03 by @ The Guild Blog


GraphQL Code Generator 約5年間、それは多くの開発者の開発者の経験を改善しています.
すべてのギルドのプロジェクトのように、すべてのこれらの年の間に、ライブラリは継続的にコミュニティと我々のクライアントからの経験とフィードバックに基づいて進化しました-毎日CodeGenはよりよくてよりよくなるので、あなたのフィードバックを来て、あなたの依存関係を最新にしておいてください).
しかし、今、それは大きなリリースのための時間です!
我々は最近再訪問し、CodeGenのいくつかの部分を改善することを決め、我々はツールの新しいバージョンをリリースしていることを発表して満足しているv2 )!
このリリースでは、すべての信頼性と生成されたコードの読みやすさを改善し、新しい機能を追加すると、新しいプラグイン/プリセットは、どのように我々のフロントエンド上のコードを生成革命になる可能性があります!

なぜv2 ?
今までのところ、GraphSQL CodeGenは、(主要な)壊れている変更の必要なしで進化しました、しかし、いくつかの小さな破れた変化を必要としたより良い、より簡単なCodegen経験のためにしたかった2、3のものがありました.
我々は現在、すべてのESMサポートを追加するに取り組んでいますThe Guild 'sツール.
残念なことに、Codegenでは、我々はまだいませんyou can track the progress here , プラグイン、プリセット、スキーマ、ドキュメントが正しくロードされていることを確認する必要があるからです.しかし、それはすぐに来ている!
しかし、依存関係として使用する他のツール graphql-tools (v8) already supports ESM , そして、ノード10のサポートを落としたので、我々はそれに合わせています.
我々は、2009年の最新バージョンに更新しました graphql-tools ( v 8 ) graphql-config ( v 4 )いくつかのバグ修正を取得します.

読みやすい生成型
数年前、我々はcodegenの出力を使用するように変更Pick スキーマ型に基づく操作型を構築するには、次の手順に従います.
// Base types generated based on the schema, from `typescript` plugin:
type Query = {
  user: User
}

type User = {
  id: Scalars['ID']
  name: Scalars['String']
}

// Types generate based on operations, from `typescript-plugins`:

type MyQuery = {
  user: Pick<User, 'id' | 'name'>
}
いくつかの時間後、我々は追加preResolveTypes 実験フラグとして、生成された型を直接生成する型の型を生成するために、次のようにします.
type MyQuery = {
  user: {
    id: string
    name: string
  }
}
我々は、v 2のv 2を発表して満足しているtypescript-operations 現在使用preResolveTypes: true デフォルトでは、生成されたすべての型が読みやすくなります.

As a user of Codegen this is not a breaking change (aside that the generated code is slightly different), and all your types are still fully compatible with v1 of the tool. You can set preResolveTypes: false if you prefer to keep the old behavior.



型精度
より読みやすいタイプに加えて、我々はまた、生成された型の精度を向上させた.
数ヶ月前. chrbala 発見a bug in the typescript-operations plugin , ネストされた複雑なフラグメントを使用した場合、生成された型が不正である原因となりました.
このバグは、私たちがフラグメントタイプを& TypeScriptの演算子で、この演算子は入れ子になったサブタイプの深いマージを適用しません.それで、複数の断片を使うときMyFirstFragment & MySecondArgument ), 入れ子になったフィールドは、マージされる代わりに上書きされます.
n1ru4l 拾ったfixed the bug そして、これらの種類のケースのより良い取扱いのための支持を加えました.
新しい設定フラグ(inlineFragmentTypes: inline ) 現在のデフォルトで使用され、より正確なタイプを生成する、変更を破ることなく導入!
断片型を結合する代わりに、それらはマージされて、インライン化されます.
export type FeedQuery = { __typename?: 'Query' } & {
-  currentUser?: Maybe<{ __typename?: 'User' } & Pick<User, 'login'>>;
-  feed?: Maybe<Array<Maybe<{ __typename?: 'Entry' } & FeedEntryFragment>>>;
+  currentUser?: Maybe<{ __typename?: 'User'; login: string }>;
+  feed?: Maybe<
+    Array<
+      Maybe<{
+        __typename?: 'Entry';
+        id: number;
+        commentCount: number;
+        score: number;
+        createdAt: number;
+        repository: {
+          __typename?: 'Repository';
+          full_name: string;
+          html_url: string;
+          description?: Maybe<string>;
+          stargazers_count: number;
+          open_issues_count?: Maybe<number>;
+          owner?: Maybe<{ __typename?: 'User'; avatar_url: string }>;
+        };
+        vote: { __typename?: 'Vote'; vote_value: number };
+        postedBy: { __typename?: 'User'; html_url: string; login: string };
+      }>
+    >
+  >;
};
心配しない、フラグメントの種類はまだ別々にエクスポートされます!

All your types are still fully compatible with v1 of the tool. You can set inlineFragmentTypes: combine if you still prefer to keep the old behavior.



廃止の除去
また、コードベースからいくつかの廃止を削除するために、メジャーバージョンの必要性を使用しました.
typescript-resolversインtypescript-resolvers , 我々は、生成された署名を持っていたIResolvers and IDirectiveResolvers (2年前に廃止された)v2 このプラグインのプロキシタイプを削除します.
また、noSchemaStitching フラグはtrue デフォルトでは、生成されたレゾルバ署名はより簡単で、ほとんどのプロジェクトのニーズにマッチします.

If you are using Schema Stitching, you can set noSchemaStitching: false to keep the old behavior.


typescript-compatibilityThe typescript-compatibility プラグインは、V 0からCodeGenのV 1に移行することをより簡単にするためにつくられて、数年の間活発に開発されませんでした.
このリリースでは、我々はもはやサポートまたは維持typescript-compatibility プラグイン.あなたがまだそれを使っているならば、新しいタイプ形式に移行することを考えてください.

操作のための新しいタイプスクリプトプラグイン!
数時間前、我々は near-operation-file プリセット、GraphSQLクライアントコードを生成する.graphql 操作ファイル.
一ヶ月前. Maël Nison 我々と連絡をとったa new concept 実際のGraphSQL操作文字列と生成された型スクリプトの型に一致します.各GraphSQL操作の不器用なインポート文を追加する必要はありません.
操作を以下のように書くことができました.
import { gql } from './gql'

const { GetTweets, CreateTweet } = gql(`#graphql
  query GetTweets {
    Tweets {
      id
    }
  }

  mutation CreateTweet {
    CreateTweet(body: "Hello") {
      id
    }
  }
`)
彼の倉庫のREADMEにはlist of limitations . GraphSQLツールの中のいくつかの上流のバグとそれに従って改善されたGraphical Codegenを修正しました.
いくつかの調整で. n1ru4l 管理turn that amazing idea into a plugin and a preset それはtypescript-operation and TypedDocumentNode , また、GraphSQLクエリ文字列に魔法のようにマッチするタイプスクリプト型を生成することもできますgraphql-tools , だから今、GraphSQLツールのローダはより良いです!

では、どういう意味ですか?
今日、GraphSQL CodeGenはコードベースをスキャンし、あなたのコンポーネント(または.graphql それから、型とラップを生成しますTypedDocumentNode あなたに.これらのいずれかを1つのファイルには、どこからアプリケーション内または次のインポートから生成されます.graphql 使用する場合near-operation-file-preset .
フォルダ構造near-operation-file-preset )
Project
- src
  - UserQuery.graphql
  - UserQuer.graphql.tsx
この新しいプラグイン+プリセットを使用すると、インラインの入力を生成することができますgql ドキュメントのインポート文を手動で指定することなく、関数を使用します.
すべてを行う必要がインポートされますgql 関数とウォッチモードでcodegenを実行します.
import { gql, FragmentType } from '@app/gql'

// TweetFragment is a fully typed document node
const TweetFragment = gql(/* GraphQL */ `
  fragment TweetFragment on Tweet {
    id
    body
  }
`)

const TweetsQueryWithFragment = gql(/* GraphQL */ `
  query TweetsWithFragmentQuery {
    Tweets {
      id
      ...TweetFragment
    }
  }
`)

const TweetComponent = (props: {
  tweet: FragmentType<typeof TweetFragment>
}) => {
  return <Tweet>{props.tweet.body}</Tweet>
}
コンテキストを切り替える必要がないように.graphql アンド.ts(x) ファイルと私たちのリポジトリ内の以下のファイルをnear-operation-file プリセット!
あなたは見つけることができますthe complete documentation, examples and API reference in codegen website .
We also have an example PR for a migration from near-operation-file to the gql-tag-operations-preset .
フロントエンドでCodeGenを使う方法を考えてみたい.
あなたのフィードバックに基づいて、我々は将来的にフロントエンドでCodeGenを使用することを推奨された方法を作りたいかもしれません.

Huge thanks to Maël Nison, who conceptualized the foundation for this preset over here. Please keep pushing the boundaries!



次は何ですか.
我々は冒頭で言ったように、我々は継続的にCodeGenを改善し続けるので、このリリースではないが、最後の起動です.ここでは、我々が現在取り組んでいることに関するいくつかのスニークピークです.

ESMサポート
ESMのサポートはすぐに来ている(そしておそらく別のメジャーバージョンになるでしょう)

SDLリゾルバ開発フローの改善
我々はより良い方法をリンクして実験しているtypeDefs を返します.typescript-resolvers 新しいものと同じようにgql-tag-operations プラグイン.
このプリセットの目標の一つは、定義され実装されるすべてのレゾルバが実際に実装されることを確認することです.
import { typeDefs } from 'tsgql'

const sdl = typeDefs(/* GraphQL */ `
  type Query {
    foo: String!
  }
`)

export const resolvers: typeof sdl = {
  Query: {
    // If this resolver would not be defined it will raise a TypeScript error.
    foo: () => 'test'
  }
}
You can find more info here

フラグメント型マスキング
今日、リレーフレームワーク開発フローは断片を通して加えられる操作結果オブジェクトからプロパティを隠しているのを許します.これらのプロパティは、フラグメントを消費するコンポーネント内でのみアクセスできます.
import { gql, FragmentProperty } from '@app/gql'

// TweetFragment is a fully typed document node
const TweetFragment = gql(/* GraphQL */ `
  fragment TweetFragment on Tweet {
    id
    body
  }
`)

const TweetsQueryWithFragment = gql(/* GraphQL */ `
  query TweetsWithFragmentQuery {
    Tweets {
      id
      ...TweetFragment
    }
  }
`)

const AppComponent = () => {
  const { data } = useQuery({ query: TweetsQueryWithFragment })

  // accessing this here is a TypeScript error.
  data.Tweets[0].body

  return (
    <>
      {data.Tweets.map((tweet) => (
        <TweetComponent key={tweet.id} tweet={tweet} />
      ))}
    </>
  )
}

const TweetComponent = (props: {
  tweet: FragmentProperty<typeof TweetFragment>
}) => {
  // accessing props.tweet.body here is legit.
  return <Tweet>{props.tweet.body}</Tweet>
}
これにより、各コンポーネントがアクセス可能なデータを受け取るだけで、スケーラブルなコンポーネントを構築することができます.また、ツリー内のコンポーネントは、明示的に要求されなかったデータにアクセスできません.
したがって、コンポーネントを削除すると、驚くべき動作にはなりません.

何が行方不明ですか?
他の何かが不足しているか、または改善することができると思いますか?このページのチャットを通して我々に手を伸ばしてくださいGitHub discussion またはGraphQL Discord .