hasura

Stars and mentions

Last 30 days, Oct 4 – Nov 2

GitHub stars18
mentions2
01234Oct 4Oct 18Nov 2
UTC days · repositories hasura owns2 repositories

Package downloads

Cumulative recorded downloads · since 2025-10-20

npm1.6M
0397.3K794.7K1.2M1.6MOct 4Oct 18Nov 2
Oct 18npm: 5/6 packages observed

Across 6 known packages in repositories hasura owns. Cumulative totals include recorded downloads before the selected range. Missing observations leave gaps; totals may be incomplete.

Top repositories

hasura’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside hasura’s account where hasura opened or reviewed pull requests in the past 365 days.

Who noticed hasura

Everyone who starred or forked hasura’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

2posts
Nov 30 posts
  1. Claude君のアホ!確認しなかった私もわるいんだけど! Hasuraの証明書CAで見つかったバグについて、社内GitHubに報告しておいてーのつもりでバグ報告お願いしたら、 Hasura本家に報告してた.... 幸いHasuraコントリビューターが親切に対応してくれたので事なきを得たけども graphql-engine#10901

    3 likes · 224 views
  2. Code generator開発記(Part 1) ! この記事は2023年6月19日に執筆されたものです。 こんにちは。Inflabのフロントエンドエンジニア、Lucasです。 フロントエンド開発をしていると、code generatorという言葉を耳にしたことがあると思います。Code generatorとは、サーバー側で宣言され、クライアントとの取り決めとなるデータ型をもとに、クライアントで使えるコードを自動生成するプログラムのことです。特にフロントエンドエンジニアの立場から見ると、APIの変更を追跡し、type-safeな開発をしたいときに、こうした自動化ツールは大きなメリットをもたらします。 Inflabでも、本格的にレガシーシステムの改善を進めるようになってから、APIの型を扱う必要が出てきました。1台のサーバーで動いていたInflearnがAPIサーバーとクライアントに分かれはじめ、APIを通じて機能を実装しなければならない場面が増えたためです。 本記事では、code generatorを自分たちで開発することになった理由についてお話しします。次回の記事では、実装方法と導入後に何が変わったのかを共有する予定です。 1. RESTful APIと向き合う プロダクトを作っていると多くの悩みに直面しますが、その中でもAPIリクエストまわりをどう管理するかには、いつも頭を悩ませます。 まずどのライブラリを使うかに始まり、コードをどこにどう配置すればAPIの変化に簡単かつ柔軟に対応できるかといった、正解のない選択が求められます。加えて、時間が経つにつれて増えていくAPI endpointの管理も、悩みの種の一つになりがちです。 コードベースでの悩み 特に、今や業界標準と言えるTypeScriptを使う場合は、APIの戻り値の型をどう管理するかという悩みがもう一つ加わります。 TypeScriptの特性上、APIの戻り値の型を指定しないままでは使えないので、必ず宣言する必要があります。そこでフロントエンドエンジニアは、通常2つの方法のどちらかを選ぶことになります。1つはすべてのリクエストの戻り値の型をanyで宣言する方法、もう1つはドキュメントに記載された戻り値を見て型を手動で管理する方法です。 経験上、型をanyにせず手動で管理すると、問題が次々に発生していました。 プロジェクト初期は型をこまめに更新する プロジェクトが終盤に近づくにつれ、さまざまな理由(忙しい、急ぎのバグ修正など)で、型をコンパイルが失敗しない程度に適当に管理する リリース後に保守が進むにつれ、新しい型が量産されたり、index signature、union、intersectionなどが乱用されたりして、runtimeの安定性が徐々に低下する 最終的に型宣言そのものがレガシーとなり、誰も気にしなくなる もちろんすべてのプロジェクトで起こることではありませんが、おおむね上のような流れをたどった場合、APIとクライアント間のインターフェースの役割を担う型は有名無実化してしまいます。 つまり、APIとクライアントの間の役割、責任、協調を信頼できなくなるということです。プロダクトのために最も密接に協力すべき2つのオブジェクトが、互いを信頼できなくなってしまうのです。 フロントエンドエンジニア同士の不毛な議論 型を手動で管理するとなると、人や連携するチームごとに、管理方法の考え方ややり方が異なることがあります。そのため、型管理の一貫性を保つには、少なくとも連携するチーム同士で、ひいてはフロントエンドチーム全体で合意する必要があります。 チーム全体で合意できたとしても、その合意が盤石とは限りません。もし誰かが新しい管理方法を提案したら、また長くて退屈な議論を一からやり直すべきでしょうか? もちろん、こうした技術的な議論そのものが悪いわけではありませんが、個人的にはこの種の議論は正解がなく、消耗するだけだと考えています。この問題を解決する自動化ツールがあれば、議論そのものが不要になるからです。 もしこうした問題をツールで解決できれば、その時間をほかの議論に使えます。たとえばプロダクトの使いやすさ、コードをより良く書く方法、デプロイ時間を短縮する方法といった「ほかの議論」のほうが、プロダクトそのものの生産性に、より大きな影響を与えられます。 フロントエンドエンジニアとバックエンドエンジニアの水掛け論 通常、RESTful APIを提供するサーバーを構築すると、ほとんどの場合ドキュメントツールとしてSwaggerを使うことになります。面白いことに、Swaggerを使うと高い確率でフロントエンドエンジニアとバックエンドエンジニアの間にA-chicken-and-egg-problem(鶏が先か卵が先か)が発生します。 たとえば、API開発者も人間なので、当然ながら構築されたAPIとSwaggerで提供されるドキュメント上の仕様が異なるケースが起こりえます。また、フロントエンドエンジニアもそれぞれ仕事のスタイルが違うので、Swaggerで提供されるドキュメントを見ずに開発するケースも出てきます。 こうなると、「どうせ見ないのにドキュメントを更新して何になるのか」という考えと、「どうせ合っていないのに、なぜドキュメントを見るのか」という考えを互いに持つようになります。あとになって「どうしてこうなったのだろう?」と頭を抱えますが、この問題の明確な原因は結局分からないままのことが多いです。 結局、フロントエンドエンジニアはAPIが返す値を自分で確認しながら型を書くことになります。いちばん確実な方法のように思えますが、いくつか問題が生じます。 1つは、プロパティの値がnullやundefinedになりうるという問題です。たとえば次のようなレスポンスがある場合、 { "user": { "name": "user name" } } もしuserプロパティがnullになりうるなら、以下のようなコードで問題が発生する可能性があります。 user.name.split(' '); // Uncaught TypeError: Cannot read properties of null (reading 'name') もう1つは、プロパティに異なる型の値が入りうるという問題です。同じく、たとえば以下のようなレスポンスがある場合、 { "user": { "age": 20 } } もしageプロパティがnumberまたはboolean型になりうるなら、以下のようなコードで問題が発生する可能性があります。 user.age > 0; // ageが20の場合はtrue // ageがfalseの場合はfalse こうなると、実際にruntimeでエラーが発生するまでAPIの変更に気づけない可能性が出てきます。もちろんTypeScriptがruntimeの安定性を完全に保証するわけではありませんが、最低限の安全装置が緩んでしまうのです。 RESTful APIは間違いなく良いコンセプトだと思います。ただ、いつものように問題は人にあります。そこで、この問題から人の手をできるだけ取り除くことを試みました。 2. 検討した解決策 以前使ったことのある技術の中から、今のチームに適用できそうな解決策をいくつか検討しましたが、どれも採用には至りませんでした。 GraphQL 個人的には、GraphQLがこの問題を解決する最もエレガントかつ確実な方法だと考えていました。以前のチームでGraphQLを使ってBFF(Backend For Frontend)サーバーを構築・運用した経験があり、サイドプロジェクトでも積極的に使っていたので、なじみのない技術でもありませんでした。 CTOのHyangLoに恐る恐る導入について相談してみましたが、結局却下されました。正確には、社内サービスで使うのは問題ないものの、外部に公開するサービスには導入できそうにないという回答でした。その理由はいくつかあり、以下のとおりでした。 GraphQLを使うと、DBのモデリングがリクエストの結果を通じて大きく露出してしまう。 GraphQLはORMに過度に依存する。 どの程度までモニタリングできるのか、現在使っているモニタリングツールがGraphQLをきちんとサポートしているのかが分からない。 BFFはサービスレイヤーを増やすため、チームの規模を考えると管理の負担になりうる。 GraphQLの経験者がバックエンドチーム、フロントエンドチームにそれぞれ1人ずつしかいない。学習コストがやや高そうなうえ、経験者が少ないことが導入の障壁になりかねない。 ビジネスの状況が急に変わることもありうるのに、開発チームがGraphQLへの移行のせいでスピードを合わせられなくなるおそれがある。 技術的な理由には個人的に腑に落ちない点もありましたが、それ以外は十分に納得できる理由でした。しかもInflabはここ最近スピード感を持って動いていたので、新しい技術スタックの導入が足かせになることは避けなければなりませんでした。 特に、レガシーAPIを段階的に改善しなければならない状況では、GraphQLの単一エンドポイントがデメリットになる可能性が高いと感じました。エンドポイントがURLで分かれていればURLごとにAPIのtarget groupを切り替えながら改善できますが、エンドポイントが1つだとこうした戦略は取れないからです。 Client side GraphQL Client side GraphQLも検討対象に含めましたが、結局自ら見送りました。クライアントコードに含まれるGraphQL schemaがAPIのインターフェースとして機能することはできても、resolverでAPIを呼び出す必要があるため、根本的な問題の解決策にはならないと判断したからです。 gRPC gRPCもGraphQLと同じ観点から検討しましたが、これを使ってAPIを実装することになるバックエンドエンジニアにとっては、GraphQLよりもさらになじみのない方法だとすぐに気づきました。同じセル(Inflab内の小規模なチーム単位)のバックエンドエンジニアと話し合ったところ、GraphQLほど前向きな反応は得られなかったからです。プロダクトの安定性も大事ですが、だからといって忙しいバックエンドチームになじみのない技術を勧めるわけにはいきませんでした。 3. コミュニティからヒントを得る GraphQLコミュニティには、The Guildというオープンソース開発者の集団があります。The GuildはGraphQL関連の強力なOSSを数多くメンテナンスしており、その一つがCode generatorです。 GraphQLを使っていたときに大いに助けられたライブラリだったので、OpenAPI Specificationを対象にした似たようなライブラリがあるかもしれないと考えました。案の定、openapi-generatorというライブラリがすぐに見つかりました。 ライブラリをインストールして試してみるまでに、それほど時間はかかりませんでした。openapi-generatorを導入したベストプラクティスを紹介する記事が非常に多く、簡単に使えたからです。いろいろなオプションを見れば見るほど、本当によくできたライブラリだと思うようになりました。 4. 車輪の再発明を決断する 個人的には、車輪の再発明はかなり避けるほうです。しかし今回は少し事情が違いました。openapi-generatorを試す中で、不満な点が見つかったからです。 1. 生成物への不満 まず一番気になったのは、生成結果が過剰で煩雑すぎることです。もちろんオプションでいろいろ調整することはできるでしょうが、満足のいく形になるとは思えませんでした。何より、GraphQL code generatorのようにAPIを呼び出すhooksまで生成されることを期待していたのですが、調べた限りではそういった機能はないようでした。 以下のようなGraphQLスキーマがあるとすると、 schema { query: Query } type Query { me: User! } enum Role { USER ADMIN } type User { id: ID! username: String! email: String! role: Role! } query findUser { me { ...UserFields } } fragment UserFields on User { id username role } GraphQL code generatorを使えば、通常は以下のようなコードが生成されるので、とても手軽に使えます。 import { useQuery, UseQueryOptions } from '@tanstack/react-query'; export type Maybe<T> = T | null; export type InputMaybe<T> = Maybe<T>; export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] }; export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> }; export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> }; export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never; }; export type Incremental<T> = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; function fetcher<TData, TVariables>( endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables, ) { return async (): Promise<TData> => { const res = await fetch(endpoint, { method: 'POST', ...requestInit, body: JSON.stringify({ query, variables }), }); const json = await res.json(); if (json.errors) { const { message } = json.errors[0]; throw new Error(message); } return json.data; }; } /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; String: { input: string; output: string }; Boolean: { input: boolean; output: boolean }; Int: { input: number; output: number }; Float: { input: number; output: number }; }; export type Query = { __typename?: 'Query'; me: User; }; export enum Role { User = 'USER', Admin = 'ADMIN', } export type User = { __typename?: 'User'; id: Scalars['ID']['output']; username: Scalars['String']['output']; email: Scalars['String']['output']; role: Role; }; export type FindUserQueryVariables = Exact<{ [key: string]: never }>; export type FindUserQuery = { __typename?: 'Query'; me: { __typename?: 'User'; id: string; username: string; role: Role }; }; export type UserFieldsFragment = { __typename?: 'User'; id: string; username: string; role: Role }; export const UserFieldsFragmentDoc = ` fragment UserFields on User { id username role } `; export const FindUserDocument = ` query findUser { me { ...UserFields } } ${UserFieldsFragmentDoc}`; export const useFindUserQuery = <TData = FindUserQuery, TError = unknown>( dataSource: { endpoint: string; fetchParams?: RequestInit }, variables?: FindUserQueryVariables, options?: UseQueryOptions<FindUserQuery, TError, TData>, ) => useQuery<FindUserQuery, TError, TData>( variables === undefined ? ['findUser'] : ['findUser', variables], fetcher<FindUserQuery, FindUserQueryVariables>( dataSource.endpoint, dataSource.fetchParams || {}, FindUserDocument, variables, ), options, ); import { useFindUserQuery } from './schema.ts'; function User() { const { data } = useFindUserQuery(); return <p>{data?.username}</p>; } 自動生成されたhooksを使う手軽さと安心感を知っていたので、OpenAPI specificationを使う場合でも、同じような結果を得たいと考えました。 2. Inflab独自の要件 私たちのチーム独自の要件が必ず出てくると予想していました。たとえばセルごとにエラー処理の方法が異なったり、生成物を1つのファイルにまとめたい、構造を変えたい、生成される型の名前を変えたいといった厄介な要望が出てきたりするはずだと考えていました。 これはmustacheとcustom templateで緩和することはできましたが、この問題を完全に解決できるとは思えませんでした。 かなり長い期間悩み続け、さまざまな状況を総合的に考えた結果、一度自分たちで作ってみようと決心しました。こうしてcode generatorへの旅が始まりました。 5. 目標 Code generatorを作る前に立てた目標は以下のとおりです。もちろん最初のバージョンですべてを実装することはできないでしょうが、最終的にv1には以下の機能がすべて含まれていてほしいと考えていました。 ファイルまたはネットワークリクエストでOpenAPI specification JSONを直接パースし、望む形の結果をファイルとして生成できること。 フロントエンドエンジニアが、APIのschemaの変化にできるだけ手間なく対応できること。 フロントエンドエンジニアが、生成物として出力したいAPIを選択できること。 APIで宣言したresponseをJSON validatorで検証できるtype guardが自動生成されること。 バックエンドエンジニアが、フロントエンドの手間を気にせずAPIを作れること。 バックエンドエンジニアが宣言したSwaggerと実際のAPI responseの形が一致しているかを、integration testで検証できること。 特に最後の機能は、GraphQLとは違ってSwaggerで宣言したschemaがresponse typeの整合性を保証してくれないため、どうしても必要だと考えました。Type guardもAPIのリクエスト結果と直接の関係はありませんが、フロントエンドでAPI schemaごとにいちいちtype guardを作る手間を省きたかったのです。 詳しい実装方法と導入後の話は、続く記事でご紹介したいと思います。

Trending awards, every completed day and week
Gold
311st place finishes
Silver
82nd place finishes
Bronze
43rd place finishes
Awarded repositories
2Owned by hasura now

Repositories

Ordered by gold, then silver, then bronze.

  1. imad-appBest: 1st by forks, 2,242 forks3172
  2. graphql-engineBest: 2nd by stars, 783 stars012

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.