Prismaを使用してGraphQL APIを構築し、Silicon CloudのApp Platformにデプロイする方法

著者たちは、「寄付に書く」プログラムの一環として、COVID-19救済基金とテック教育基金を寄付の対象として選びました。

導入

GraphQLは、スキーマ定義言語とクエリ言語からなるAPIのためのクエリ言語であり、APIの消費者が柔軟なクエリをサポートするために必要なデータのみを取得することができます。GraphQLを使用することで、開発者は複数のクライアント(例:iOS、Android、Webアプリのバリエーション)の異なるニーズを満たしながらAPIを進化させることができます。また、GraphQLスキーマはAPIに静的な型安全性を追加するだけでなく、APIのドキュメントとしても機能します。

Prismaには、3つの主要なツールを備えたオープンソースのデータベースツールキットがあります。

  • Prisma Client: Auto-generated and type-safe query builder for Node.js & TypeScript.
  • Prisma Migrate: Declarative data modeling & migration system.
  • Prisma Studio: GUI to view and edit data in your database.

プリズマは、複雑なデータベースのワークフロー(スキーマの移行や複雑なSQLクエリの作成など)に時間を費やすのではなく、付加価値のある機能の実装に重点を置きたいアプリケーション開発者にとって、データベースの取り扱いを容易にします。

このチュートリアルでは、GraphQLとPrismaを組み合わせて使用します。それぞれの責任がお互いを補完しています。GraphQLは、フロントエンドやモバイルアプリなどのクライアントで使用するためのデータへの柔軟なインターフェースを提供します。GraphQLは特定のデータベースに依存しません。ここで、Prismaがデータベースとのやり取りを処理し、データを格納します。

デジタルオーシャンのApp Platformは、インフラストラクチャの心配をせずにクラウド上でアプリケーションをデプロイし、データベースを準備するシームレスな方法を提供します。これにより、クラウド上でアプリケーションを実行する際の運用オーバーヘッドが削減されます。特に、日々のバックアップと自動フェイルオーバーが可能な管理されたPostgreSQLデータベースの作成機能があります。App Platformには、ネイティブなNode.jsサポートがあり、デプロイの効率化が図られています。

あなたはNode.jsを使用してJavaScriptでブログアプリケーションのためのGraphQL APIを構築します。最初にApollo Serverを使用して、メモリ内データ構造をバックエンドとしたGraphQL APIを構築します。次に、Silicon Cloud App PlatformにAPIをデプロイします。最後に、Prismaを使用して、メモリ内ストレージを置き換え、データをPostgreSQLデータベースに永続化し、アプリケーションを再度デプロイします。

チュートリアルの最後には、Silicon CloudにデプロイされたNode.jsのGraphQL APIがあり、これはHTTP経由で送信されたGraphQLリクエストを処理し、PostgreSQLデータベースに対してCRUD操作を行います。

このプロジェクトのコードは、Silicon Cloud Communityのリポジトリで見つけることができます。

前提条件

このガイドを開始する前に、以下のものが必要です。

  • A GitHub account.
  • A Silicon Cloud account.
  • Git installed on your computer. You can follow the tutorial Contributing to Open Source: Getting Started with Git to install and set up Git on your computer.
  • Node.js version 14 or higher installed on your computer. You can follow the tutorial How to Install Node.js and Create a Local Development Environment to install and set up Node.js on your computer.
  • Docker installed on your computer (to run the PostgreSQL database locally).

このチュートリアルでは、JavaScript、Node.js、GraphQL、およびPostgreSQLに基本的な理解があると役立ちますが、厳密に必要ではありません。

ステップ1 — Node.jsプロジェクトの作成

このステップでは、npmを使用してNode.jsプロジェクトを準備し、依存関係であるapollo-serverとgraphqlをインストールします。このプロジェクトは、このチュートリアルの間に構築および展開するGraphQL APIの基盤となります。

最初に、プロジェクト用の新しいディレクトリを作成してください。

  1. mkdir prisma-graphql

 

次に、ディレクトリに移動して、空のnpmプロジェクトを初期化します。

  1. cd prisma-graphql
  2. npm init –yes

 

このコマンドは、npmプロジェクトの設定ファイルとして使用される最小限のpackage.jsonファイルを作成します。

以下の出力を受け取ります。

Output

Wrote to /Users/your_username/workspace/prisma-graphql/package.json: { “name”: “prisma-graphql”, “version”: “1.0.0”, “description”: “”, “main”: “index.js”, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1″ }, “keywords”: [], “author”: “”, “license”: “ISC” }

あなたは今、プロジェクトでTypeScriptを設定する準備ができています。

必要な依存関係をインストールしてください。

  1. npm install apollo-server graphql –save

 

このコマンドは、あなたのプロジェクトに依存関係として2つのパッケージをインストールします。

  • apollo-server is the HTTP library that you use to define how GraphQL requests are resolved and how to fetch data.
  • graphql is the library you’ll use to build the GraphQL schema.

プロジェクトを作成し、依存関係をインストールしました。次のステップでは、GraphQLスキーマを定義します。

ステップ2 — GraphQLのスキーマとリゾルバを定義する

このステップでは、GraphQLのスキーマとそれに対応するリゾルバを定義します。スキーマはAPIが処理できる操作を定義します。リゾルバは、インメモリのデータ構造を使用してリクエストの処理ロジックを定義します。次のステップでは、データベースクエリで置き換えることになります。

最初に、ソースファイルを格納する新しいディレクトリ「src」を作成してください。

  1. mkdir src

 

その後、スキーマ用のファイルを作成するために、次のコマンドを実行してください。

  1. nano src/schema.js

 

ファイルに次のコードを追加してください。

プリズマ GraphQL の「src/schema.js」を日本語で言い換えると、以下の通りです:
プリズマ-GraphQL内の「src/schema.js」
const { gql } = require('apollo-server')

const typeDefs = gql`
  type Post {
    content: String
    id: ID!
    published: Boolean!
    title: String!
  }

  type Query {
    feed: [Post!]!
    post(id: ID!): Post
  }

  type Mutation {
    createDraft(content: String, title: String!): Post!
    publish(id: ID!): Post
  }
`

GraphQLスキーマは、gqlタグ付きテンプレートを使用して定義します。スキーマは、APIに対して実行できるクエリの形状を定義するタイプ定義(typeDefs)の集合です。これにより、GraphQLスキーマの文字列がApolloが期待する形式に変換されます。

スキーマは三つのタイプを紹介します。

  • Post defines the type for a post in your blogging app and contains four fields where each field is followed by its type: for example, String.
  • Query defines the feed query which returns multiple posts as denoted by the square brackets and the post query which accepts a single argument and returns a single Post.
  • Mutation defines the createDraft mutation for creating a draft Post and the publish mutation which accepts an id and returns a Post.

すべてのGraphQL APIには、クエリタイプがあり、ミューテーションタイプがあるかどうかは個々に異なります。これらのタイプは通常のオブジェクトタイプと同じですが、GraphQLクエリのエントリーポイントを定義するために特別な役割を果たしています。

次に、typeDefs変数の下にposts配列をsrc/schema.jsファイルに追加してください。

プリズマ-グラフQL/src/schema.jsを日本語で表現すると、以下のようになります。ただし、1つのオプションのみ提供します:

プリズマ-GraphQL/src/schema.js

...
const posts = [
  {
    id: 1,
    title: 'Subscribe to GraphQL Weekly for community news ',
    content: 'https://graphqlweekly.com/',
    published: true,
  },
  {
    id: 2,
    title: 'Follow Silicon Cloud on Twitter',
    content: 'https://twitter.com/digitalocean',
    published: true,
  },
  {
    id: 3,
    title: 'What is GraphQL?',
    content: 'GraphQL is a query language for APIs',
    published: false,
  },
]

あなたは事前に定義された3つの投稿を持つ投稿配列を定義します。各投稿オブジェクトの構造は、スキーマで定義したPostタイプに一致しています。この配列はAPIによって提供される投稿を保持します。次のステップでは、データベースとPrisma Clientが導入された後に、この配列を置き換えることになります。

次に、まだ定義していないレゾルバーオブジェクトを定義します。先ほど定義したポスト配列の下に、以下のコードを追加してください。

プリズマ・グラフQLのschema.jsファイルを日本語で言い換えると、以下のようになります。
「プリズマ-グラフQLのsrc/schema.jsファイル」
...
const resolvers = {
  Query: {
    feed: (parent, args) => {
      return posts.filter((post) => post.published)
    },
    post: (parent, args) => {
      return posts.find((post) => post.id === Number(args.id))
    },
  },
  Mutation: {
    createDraft: (parent, args) => {
      posts.push({
        id: posts.length + 1,
        title: args.title,
        content: args.content,
        published: false,
      })
      return posts[posts.length - 1]
    },
    publish: (parent, args) => {
      const postToPublish = posts.find((post) => post.id === Number(args.id))
      postToPublish.published = true
      return postToPublish
    },
  },
  Post: {
    content: (parent) => parent.content,
    id: (parent) => parent.id,
    published: (parent) => parent.published,
    title: (parent) => parent.title,
  },
}

module.exports = {
  resolvers,
  typeDefs,
}

GraphQLスキーマと同じ構造でリゾルバを定義する必要があります。スキーマの型の各フィールドには、それに対応するリゾルバ関数があります。対応するリゾルバ関数の役割は、スキーマのそのフィールドに対するデータを返すことです。例えば、Query.feed()リゾルバは、投稿配列をフィルタリングして公開された投稿を返します。

解決関数には4つの引数が渡されます。

  • parent is the return value of the previous resolver in the resolver chain. For top-level resolvers, the parent is undefined, because no previous resolver is called. For example, when making a feed query, the query.feed() resolver will be called with parent’s value undefined and then the resolvers of Post will be called where parent is the object returned from the feed resolver.
  • args carries the parameters for the query. For example, the post query, will receive the id of the post to be fetched.
  • context is an object that gets passed through the resolver chain that each resolver can write to and read from, which allows the resolvers to share information.
  • info is an AST representation of the query or mutation. You can read more about the details in this Prisma series on GraphQL Basics.

これらのリゾルバには、文脈や情報は必要ありませんので、親(parent)と引数(args)のみが定義されています。

作業が終了したら、ファイルを保存して終了してください。

Note

注意:リゾルバが自身の名前と同じフィールドを返す場合、例えば Post の場合、Apollo Server はそれらを自動的に解決します。これは、明示的にそれらのリゾルバを定義する必要がないことを意味します。
– Post: {
– content: (parent) => parent.content,
– id: (parent) => parent.id,
– published: (parent) => parent.published,
– title: (parent) => parent.title,
– },

スキーマとリゾルバをエクスポートしておき、次のステップでApollo Serverを使用してサーバをインスタンス化するために利用します。

ステップ3 — GraphQLサーバーの作成

このステップでは、Apollo Serverを使用してGraphQLサーバーを作成し、ポートにバインドしてサーバーが接続を受け付けるようにします。

最初に、サーバー用のファイルを作成するために次のコマンドを実行してください。

  1. nano src/server.js

 

以下のコードをファイルに追加してください。

プリズマ-GraphQL/src/server.js。
const { ApolloServer } = require('apollo-server')
const { resolvers, typeDefs } = require('./schema')

const port = process.env.PORT || 8080

new ApolloServer({ resolvers, typeDefs }).listen({ port }, () =>
  console.log(`Server ready at: http://localhost:${port}`),
)

ここでは、前のステップからスキーマとリゾルバをサーバーにインスタンス化して渡します。

サーバがバインドするポートは、PORT環境変数から設定されます。もし設定されていない場合、デフォルトで8080ポートが使われます。App Platformが自動的に設定するため、デプロイ後にサーバが接続を受け入れられるよう、PORT環境変数が確実に設定されます。

ファイルを保存して終了してください。

あなたのGraphQL APIは実行準備が整っています。次のコマンドでサーバーを起動してください。

  1. node src/server.js

 

次の出力を受け取ります。

Output

Server ready at: http://localhost:8080

パッケージのpackage.jsonファイルにスタートスクリプトを追加することは、エントリーポイントが明確になるために良いプラクティスとされています。これにより、App Platformはデプロイ後にサーバーを起動することができます。

まず、CTRL+Cを押してサーバーを停止します。次に、スタートスクリプトを追加するために、package.jsonファイルを開いてください。

  1. nano package.json

 

package.jsonの「scripts」オブジェクトに、ハイライトされたテキストを追加してください。

パッケージ.json
{
  "name": "prisma-graphql",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node ./src/server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "apollo-server": "^3.11.1",
    "graphql": "^16.6.0"
  }
}

ファイルを保存して終了してください。

以下のコマンドを使用して、サーバーを起動することができます。

  1. npm start

 

以下の出力を受け取ります。

Output

> prisma-graphql@1.0.0 start > node ./src/server.js Server ready at: http://localhost:8080

GraphQL APIをテストするために、出力からURLを開き、Apollo GraphQL Studioに移動します。ホームページで「Query Your Server」ボタンをクリックして、IDEと対話します。

Apollo GraphQL Studio

Apollo GraphQL Studioは、クエリやミューテーションを送信してAPIをテストできるIDEです。

例えば、公開された投稿のみを返すフィードクエリをテストする場合、IDEの左側に以下のクエリを入力し、実行ボタンを押してクエリを送信してください。

query {
  feed {
    id
    title
    content
    published
  }
}

レスポンスには、「GraphQL Weeklyを購読する」というタイトルとそのURL、そして「Silicon CloudをTwitterでフォローする」というタイトルとそのURLが表示されます。

GraphQL Feed Query

以前のクエリの上のバーの+ボタンをクリックして、新しいタブを作成してください。次に、createDraftミューテーションをテストするために、以下のミューテーションを入力してください。

mutation {
  createDraft(title: "Deploying a GraphQL API to Silicon Cloud") {
    id
    title
    content
    published
  }
}

「プレイボタンを使用して変異を送信した後、応答として、タイトルフィールドの一部として、GraphQL APIをSilicon Cloudにデプロイするという内容が含まれるレスポンスを受け取ります。」

GraphQL Create Draft Mutation

Note

注意:createDraftの後ろの中括弧({})内のフィールドを返すか除外することで、返すフィールドを選択できます。例えば、idとtitleのみを返したい場合は、以下のようなmutationを送信できます:

mutation {
createDraft(title: “デジタルオーシャンにGraphQL APIをデプロイする”) {
id
title
}
}

あなたはGraphQLサーバーを作成し、テストを成功させました。次のステップでは、プロジェクトのためにGitHubリポジトリを作成します。

ステップ4 – GitHubリポジトリの作成

この手順では、プロジェクト用のGitHubリポジトリを作成し、変更をプッシュします。これにより、GitHubからApp Platformに自動的にGraphQL APIがデプロイされるようになります。

まず、CTRL+Cを押して開発サーバーを停止してください。その後、以下のコマンドを使用してprisma-graphqlフォルダからリポジトリを初期化してください。

  1. git init

 

次に、コードをリポジトリにコミットするために、以下の2つのコマンドを使用してください。

  1. git add src package-lock.json package.json
  2. git commit -m ‘Initial commit’

 

ローカルリポジトリへの変更がコミットされたら、GitHubで新しいリポジトリを作成して変更内容をプッシュします。

GitHubにアクセスして、新しいリポジトリを作成してください。一貫性のために、リポジトリの名前をprisma-graphqlとして、作成ボタンをクリックしてください。

レポジトリが作成された後は、以下のコマンドで変更をプッシュします。これには、デフォルトのローカルブランチをmainにリネームすることも含まれます。

  1. git remote add origin git@github.com:your_github_username/prisma-graphql.git
  2. git branch -M main
  3. git push –set-upstream origin main

 

GitHubへの変更の確定とプッシュが成功しました。次に、リポジトリをApp Platformに接続して、GraphQL APIをデプロイします。

ステップ5 — App Platformへの展開

この手順では、作成したGitHubリポジトリをSilicon Cloudに接続し、App Platformを設定して、GitHubに変更をプッシュするとGraphQL APIが自動的にデプロイされるようにします。

最初に、Silicon Cloud Cloud ConsoleのApp Platformページにアクセスし、”Create App”ボタンをクリックしてください。

デフォルトとして、GitHubというサービスプロバイダーの選択肢が表示されます。

GitHubアカウントにSilicon Cloudを設定していない場合は、「アクセスの管理」ボタンをクリックして、GitHubにリダイレクトされます。

Silicon Cloud Cloud console page for

あなたはすべてのリポジトリまたは特定のリポジトリを選択することができます。[インストール&承認]をクリックすると、Silicon Cloud アプリプラットフォームの作成ページにリダイレクトされます。

あなたの_Github_ユーザー名/prisma-graphql_のリポジトリを選択し、次に進んでください。オートデプロイはデフォルトで選択されており、再デプロイの一貫性を保つために選択したままにしておくことができます。

Choose Repository

リソースページで、適切なプランを選択するために「編集プラン」ボタンをクリックします。必要なプランサイズを持つ「ベーシックプラン」を選択してください(このチュートリアルでは、$5.00/月のベーシックプランを使用します)。

Screencapture of the

その後は、作成ページに戻るために「戻る」ボタンを押してください。

プロジェクト名の隣にあるペンアイコンを押すと、アプリの設定をカスタマイズすることができます。アプリケーション設定ページが開きます。

Application Settings

「Run Command」が「npm start」に設定されていることを確認してください。デフォルトでは、App PlatformはHTTPポートを「8080」と設定しますが、これはGraphQLサーバーのバインドポートとして設定されているポートと同じです。

構成のカスタマイズが完了したら、戻るボタンを押して設定ページに戻ります。そして、次へボタンを押して、環境変数のページに移動します。

現時点では、環境変数の追加設定は必要ありません。次のボタンをクリックしてください。

Screencapture displaying the Environment Variables default setup

「情報」ページでは、アプリの詳細と場所を調整することができます。アプリ情報を編集して、アプリをデプロイしたい地域を選択してください。保存ボタンを押してアプリの詳細を確認してください。その後、次へボタンをクリックしてください。

Screencapture of the Info page, displaying the selected location of the application

選択したオプションをすべてレビューページで確認することができます。その後、「リソースを作成」をクリックしてください。初期デプロイの進捗状況が表示されるアプリのページにリダイレクトされます。

ビルドが完了すると、アプリが展開された通知が届きます。

Screencapture displaying the deployment progress bar with a

アプリ名の下にあるURLから、デジタルオーシャンコンソールで展開されたGraphQL APIにアクセスできます。それは、ondigitalocean.appサブドメインを介してリンクされます。URLを開くと、GraphQL Playgroundがこのチュートリアルのステップ3と同じように開きます。

リポジトリをApp Platformに正常に接続し、GraphQL APIをデプロイしました。次に、アプリを進化させ、GraphQL APIのインメモリデータをデータベースで置き換えます。

ステップ6 – PostgreSQLを使用してPrismaをセットアップする

これまで、データを保存するためにインメモリの投稿配列を使用してGraphQL APIを構築しました。しかし、サーバーが再起動すると、データへのすべての変更が失われてしまいます。データが安全に永続化されるようにするために、投稿配列をPostgreSQLデータベースで置き換え、データにアクセスするためにPrismaを使用します。

このステップでは、Prisma CLIをインストールし、初期のPrismaスキーマ(Prismaセットアップのメイン構成ファイルで、データベーススキーマを含む)を作成し、Dockerを使用してローカルにPostgreSQLをセットアップし、Prismaと接続します。

次のコマンドを使用して、Prisma CLIのインストールを開始してください。

  1. npm install –save-dev prisma

 

Prisma CLIはデータベースのワークフローをサポートし、データベースマイグレーションの実行やPrismaクライアントの生成などに役立ちます。

次に、Dockerを使用してPostgreSQLデータベースをセットアップします。以下のコマンドを使用して新しいDocker Composeファイルを作成してください。

  1. nano docker-compose.yml

 

新しく作成したファイルに以下のコードを追加してください。

下記を日本語で自然に言い換え、一つのオプションを提示します:
「prisma-graphql/docker-compose.yml」
version: '3.8'
services:
  postgres:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_USER=test-user
      - POSTGRES_PASSWORD=test-password
    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - '5432:5432'
volumes:
  postgres:

このDocker Composeの設定ファイルは、公式のPostgreSQL Dockerイメージをあなたのマシンで起動する責任を持っています。POSTGRES_USERとPOSTGRES_PASSWORD環境変数は、管理者特権を持つスーパーユーザーの資格情報を設定します。これらの資格情報を使用して、Prismaをデータベースに接続します。test-userとtest-passwordをあなたのユーザーの資格情報で置き換えてください。

最後に、PostgreSQLがデータを保存するためのボリュームを定義し、5432ポートを自分のマシン上の同じポートにDockerコンテナにバインドします。

ファイルを保存して終了してください。

この設定が完了すれば、以下のコマンドでPostgreSQLデータベースサーバーを起動することができます。

  1. docker-compose up -d

 

読み込みには数分かかるかもしれません。

次のコマンドを使用して、データベースサーバーが実行中であることを確認できます。

  1. docker ps

 

このコマンドは、何か似たようなものを出力します。

Output

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 198f9431bf73 postgres:10.3 “docker-entrypoint.s…” 45 seconds ago Up 11 seconds 0.0.0.0:5432->5432/tcp prisma-graphql_postgres_1

PostgreSQLコンテナが実行中の場合、Prismaの設定を作成することができます。Prisma CLIから次のコマンドを実行してください。

  1. npx prisma init

 

ベストプラクティスとして、Prisma CLIのすべての呼び出しは、ローカルインストールを使用するためにnpxを前置する必要があります。

このような出力が表示されます。

Output

✔ Your Prisma schema was created at prisma/schema.prisma You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb. 3. Run prisma db pull to turn your database schema into a Prisma schema. 4. Run prisma generate to generate the Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started

コマンドを実行すると、Prisma CLIはプロジェクトフォルダーにdotenvファイル(.env)を生成し、データベースの接続URLを定義するためのファイルと、schema.prismaファイルを含む新しいネストされたprismaフォルダーを作成します。このschema.prismaファイルは、Prismaプロジェクトのメイン設定ファイルであり、データモデルを含めることができます。

プリズマがデータベースの場所を知っていることを確認するために、.envファイルを開いてください。

  1. nano .env

 

ユーザーの認証情報を使って、DATABASE_URLの環境変数を調整してください。

プリズマ-グラフQL/.env
DATABASE_URL="postgresql://test-user:test-password@localhost:5432/my-blog?schema=public"

Docker Compose ファイルで指定されたデータベースの認証情報は、test-user と test-password です。Docker Compose ファイルで認証情報を変更した場合は、この行を変更してファイル内の認証情報と一致させてください。接続 URL の形式については、Prisma ドキュメントを参照してください。

PostgreSQLを正常に起動し、Prismaスキーマを使用してPrismaを設定しました。次のステップでは、ブログのデータモデルを定義し、Prisma Migrateを使用してデータベーススキーマを作成します。

ステップ7 – Prisma Migrateを使ってデータモデルを定義する。

今回作成したPrismaスキーマファイルにて、データモデルを定義します。その後、Prismaマイグレーションによってデータモデルがデータベースにマッピングされ、データモデルに対応するテーブルを作成するためのSQLステートメントが生成され、送信されます。

ブログを作成しているので、このアプリケーションの主なエンティティはユーザーと投稿です。このステップでは、GraphQLスキーマの投稿タイプに似た構造の投稿モデルを定義します。後のステップでは、アプリを進化させてユーザーモデルを追加します。

Note

注:GraphQL APIは、データベースの抽象化レイヤーとして見ることができます。GraphQL APIを構築する際、GraphQLスキーマは通常、データベーススキーマに近い形になります。ただし、抽象化されたため、2つのスキーマの構造が必ずしも同じではなく、APIで公開するデータを制御することができます。一部のデータはAPIレイヤーにとって機密性があるか関係がないと考えられるためです。

Prismaは、アプリケーションデータの形状を定義するために独自のデータモデリング言語を使用します。

プロジェクトのフォルダ内のschema.prismaファイルをpackage.jsonがある場所から開いてください。

  1. nano prisma/schema.prisma

 

Note

注意:現在の作業ディレクトリを出力するために、pwdコマンドを使用してターミナルでどのフォルダにいるかを確認できます。また、lsコマンドを使用してファイルをリスト表示することで、ファイルシステムを操作しやすくすることができます。

以下のモデル定義を追加してください。 (Ikitai no moderu teigi o tsuika shite kudasai)

プリズマ-グラフキュエルのスキーマファイル、
prisma-graphql/prisma/schema.prisma
...
model Post {
  id        Int     @default(autoincrement()) @id
  title     String
  content   String?
  published Boolean @default(false)
}

複数のフィールドを持つ「Post」というモデルを定義します。このモデルはデータベースのテーブルにマッピングされ、フィールドは各個別の列を表します。

idフィールドには、次のフィールド属性があります。

  • @default(autoincrement()) sets an auto-incrementing default value for the column.
  • @id sets the column as the primary key for the table.

ファイルを保存して終了してください。 (Fairu o hozon shite shūryō shite kudasai.)

モデルが準備できたら、Prisma Migrateを使用して対応するテーブルをデータベースに作成できます。マイグレーションファイルの作成と実行は、マイグレーション開発コマンドを使って行います。

あなたのターミナルで、次のコマンドを実行してください。

  1. npx prisma migrate dev –name init –skip-generate

 

このコマンドは、新しいマイグレーションをファイルシステムに作成し、データベースに対して実行してデータベーススキーマを作成します。–name initフラグは、マイグレーションの名前を指定します(ファイルシステムに作成されるマイグレーションフォルダの名前に使用されます)。–skip-generateフラグは、Prisma Clientの生成をスキップします(これは次のステップで行われます)。

このコマンドは、次のようなものを出力します。

Output

Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Datasource “db”: PostgreSQL database “my-blog”, schema “public” at “localhost:5432” PostgreSQL database my-blog created at localhost:5432 Applying migration `20201201110111_init` The following migration(s) have been created and applied from new schema changes: migrations/ └─ 20201201110111_init/ └─ migration.sql Your database is now in sync with your schema.

あなたの Prisma / migrations ディレクトリは、現在 SQL マイグレーションファイルで満たされています。この方法により、データベーススキーマの変更を追跡し、本番環境で同じデータベーススキーマを作成することができます。

Note

注意:すでにPrisma Migrateをmy-blogデータベースで使用しており、prisma/migrationフォルダとデータベーススキーマの間に不整合がある場合、以下の出力でデータベースのリセットを促されます:
出力?「localhost:5432」のPostgreSQLデータベース「my-blog」をリセットする必要があります。すべてのデータが失われます。
続行しますか? › (y/N)

これを解決するには、yを入力してデータベースをリセットできます。ただし、これによりデータベース内のすべてのデータが失われることに注意してください。

現在、データベースのスキーマを作成しました。次のステップでは、Prisma Clientをインストールし、GraphQLのリゾルバーで使用します。

ステップ8 – GraphQLリゾルバでPrismaクライアントを使用する。

Prisma Clientは、Node.jsアプリケーションからデータベースへのプログラムによる読み書きを行うために使用できる自動生成されたタイプセーフなオブジェクトリレーショナルマッパー(ORM)です。このステップでは、プロジェクトにPrisma Clientをインストールします。

ターミナルで、Prismaクライアントのnpmパッケージをインストールしてください。

  1. npm install @prisma/client

 

Note

注意:Prismaクライアントは、Prismaスキーマに基づいてコードを生成し、node_modulesフォルダに自動的に補完機能を提供します。コードを生成するには、npx prisma generateコマンドを使用します。通常、これは新しいマイグレーションを作成して実行した後に行われます。ただし、最初のインストールでは、postinstallフックで自動的に生成されるため、この手順は必要ありません。

データベースとGraphQLスキーマを作成し、Prisma Clientをインストールした後、データベース内のデータを読み書きするためにGraphQLリゾルバでPrisma Clientを使用します。これは、これまでデータを保持するために使用してきた投稿の配列を置き換えることで行います。

以下のファイルを作成して開いてください。

  1. nano src/db.js

 

新しいファイルに以下の行を追加してください。

prisma-graphql/src/db.jsを日本語で直訳すると、次の通りです:プリズマ-グラフキューエル/ソース/データベース.ジェイエス.
const { PrismaClient } = require('@prisma/client')

module.exports = {
  prisma: new PrismaClient(),
}

このコードはPrisma Clientをインポートし、そのインスタンスを作成し、リゾルバで使用するインスタンスをエクスポートします。

今src/db.jsファイルを保存して閉じてください。

次に、prismaのインスタンスをsrc/schema.jsにインポートします。これを行うために、src/schema.jsを開いてください。

  1. nano src/schema.js

 

ファイルの先頭に `import prisma from ‘./db’` という行を追加してください。

prisma-graphql/src/schema.jsの内容を日本語でネイティブに言い換えると、以下のようになります。

「prisma-graphql/src/schema.jsファイルの中身」

const { prisma } = require('./db')
...

その後、ハイフン記号(-)でマークされている行を削除して、投稿の配列を削除します。

プリズマ-グラフクエル/ソースコード/スキーマ.js
...
-const posts = [
-  {
-    id: 1,
-    title: 'Subscribe to GraphQL Weekly for community news ',
-    content: 'https://graphqlweekly.com/',
-    published: true,
-  },
-  {
-    id: 2,
-    title: 'Follow Silicon Cloud on Twitter',
-    content: 'https://twitter.com/digitalocean',
-    published: true,
-  },
-  {
-    id: 3,
-    title: 'What is GraphQL?',
-    content: 'GraphQL is a query language for APIs',
-    published: false,
-  },
-]
...

次に、データベースから公開された投稿を取得するために、クエリリゾルバを更新します。まず、resolvers.Query内の既存の行を削除し、その後、ハイライトされた行を追加することにより、オブジェクトを更新してください。

プリズマ-GraphQL / src / schema.jsをパラフレーズ化すると以下のようになります:
...
const resolvers = {
  Query: {
    feed: (parent, args) => {
      return prisma.post.findMany({
        where: { published: true },
      })
    },
    post: (parent, args) => {
      return prisma.post.findUnique({
        where: { id: Number(args.id) },
      })
    },
  },
...

ここでは、2つのPrismaクライアントのクエリを使用します。

  • findMany fetches posts whose publish field is false.
  • findUnique fetches a single post whose id field equals the id GraphQL argument.

GraphQLの仕様によれば、ID型はStringと同じようにシリアライズされます。したがって、Prismaスキーマのidがintであるため、Numberに変換する必要があります。

次に、Mutationリゾルバを更新してデータベースに投稿を保存および更新します。まず、resolvers.MutationオブジェクトとNumber(args.id)のコードを削除し、その後、ハイライトされた行を追加します。

prisma-graphql/src/schema.jsを日本語で要約してください。選択肢は1つだけです。
プリズマグラフQLのソースファイルschema.jsです。
const resolvers = {
  ...
  Mutation: {
    createDraft: (parent, args) => {
      return prisma.post.create({
        data: {
          title: args.title,
          content: args.content,
        },
      })
    },
    publish: (parent, args) => {
      return prisma.post.update({
        where: {
          id: Number(args.id),
        },
        data: {
          published: true,
        },
      })
    },
  },
}

2つのPrisma Clientクエリを使用しています。

  • create to create a Post record.
  • update to update the published field of the Post record whose id matches the one in the query argument.

最後に、resolvers.Postオブジェクトを削除してください。

prisma-graphql/src/schema.jsの内容を日本語で自然な表現で言い換えると以下の通りです:

「prisma-graphql/src/schema.jsファイルの中身」

...
-Post: {
-  content: (parent) => parent.content,
-  id: (parent) => parent.id,
-  published: (parent) => parent.published,
-  title: (parent) => parent.title,
-},
...

あなたのschema.jsは、以下のように記述する必要があります。

prisma-graphql/src/schema.jsを日本語で言い換えると「プリズマ-グラフQL/ソースコード/スキーマ.js」となります。
const { gql } = require('apollo-server')
const { prisma } = require('./db')

const typeDefs = gql`
  type Post {
    content: String
    id: ID!
    published: Boolean!
    title: String!
  }

  type Query {
    feed: [Post!]!
    post(id: ID!): Post
  }

  type Mutation {
    createDraft(content: String, title: String!): Post!
    publish(id: ID!): Post
  }
`

const resolvers = {
  Query: {
    feed: (parent, args) => {
      return prisma.post.findMany({
        where: { published: true },
      })
    },
    post: (parent, args) => {
      return prisma.post.findUnique({
        where: { id: Number(args.id) },
      })
    },
  },
  Mutation: {
    createDraft: (parent, args) => {
      return prisma.post.create({
        data: {
          title: args.title,
          content: args.content,
        },
      })
    },
    publish: (parent, args) => {
      return prisma.post.update({
        where: {
          id: Number(args.id),
        },
        data: {
          published: true,
        },
      })
    },
  },
}

module.exports = {
  resolvers,
  typeDefs,
}

ファイルを保存して閉じる。

プリズマクライアントを使用したリゾルバの更新が完了したので、以下のコマンドでサーバーを起動して、GraphQL APIとデータベース間のデータの流れをテストしてください。

  1. npm start

 

もう一度、以下の出力を受け取ります。 (Mō ichido, ika no shutsuryoku o uketorimasu.)

Output

Server ready at: http://localhost:8080

出力からアドレスを指定してApollo GraphQL Studioを開き、ステップ3で使用した同じクエリを使用してGraphQL APIをテストしてください。

今度は変更を確定させ、変更がApp Platformに展開できるようにします。CTRL+CでApolloサーバーを停止してください。

プロジェクトフォルダ内の.gitignoreファイルを確認して、node_modulesフォルダと.envファイルのコミットを避けてください。

  1. cat .gitignore

 

あなたの.gitignoreファイルにこれらの行が含まれていることを確認してください。

prisma-graphql/.gitignoreを日本語に書き換えると次のようになります:
prisma-graphql/.gitignore
node_modules
.env

もし一致しない場合、ファイルを更新してください。

ファイルを保存して閉じてください。

その後、以下の2つのコマンドを実行して変更内容をコミットしてください。

  1. git add .
  2. git commit -m ‘Add Prisma’

 

このような出力の応答を受け取ることになります。

Output

git commit -m ‘Add Prisma’ [main 1646d07] Add Prisma 9 files changed, 157 insertions(+), 39 deletions(-) create mode 100644 .gitignore create mode 100644 docker-compose.yml create mode 100644 prisma/migrations/20201201110111_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 src/db.js

GraphQLリゾルバーをPrisma Clientを使用して更新し、データベースへのクエリとミューテーションを実行しました。その後、すべての変更をリモートリポジトリにコミットしました。次に、App PlatformにPostgreSQLデータベースをアプリに追加します。

ステップ9 – アプリプラットフォームでPostgreSQLデータベースの作成と移行

このステップでは、App PlatformでアプリにPostgreSQLデータベースを追加します。そして、Prisma Migrateを使用してマイグレーションを実行し、デプロイされたデータベーススキーマをローカルのデータベースと一致させます。

最初に、アプリのプラットフォームコンソールにアクセスし、ステップ5で作成した「prisma-graphql」プロジェクトを選択してください。

次に、作成ボタンをクリックし、ドロップダウンメニューからデータベース作成/添付を選択してください。これにより、データベースの設定ページに移動します。

Screencapture displaying the Create/Attach Database option in the dropdown menu

デブデータベースを選択し、名前を指定して、作成と添付をクリックしてください。

プロジェクトビューにリダイレクトされ、データベースの作成進捗バーが表示されます。

Screencapture displaying the Creating Database Progress Bar

データベースを作成した後、ローカルマシンからSilicon Cloudの本番データベースに対してデータベースの移行を実行します。移行を実行するためには、ホストされたデータベースの接続文字列が必要です。

それを入手するには、設定タブのコンポーネントセクションにある「db」アイコンをクリックしてください。

Screencapture displaying the Database Component Settings

接続詳細の下で、[表示]を押し、次にドロップダウンメニューから[接続文字列]を選択してください。データベースのURLをコピーしてください。URLの構造は以下のようになります。

postgresql://db:some_password@unique_identifier.db.ondigitalocean.com:25060/db?sslmode=require

では、ターミナルで以下のコマンドを実行し、your_db_connection_stringを先ほどコピーしたURLに設定してください。

  1. DATABASE_URL=your_db_connection_string npx prisma migrate deploy

 

このコマンドは、Prisma Migrateを使用してライブデータベースに対してマイグレーションを実行します。

移行が成功した場合、以下の出力が届きます。

Output

PostgreSQL database db created at unique_identifier.db.ondigitalocean.com:25060 Prisma Migrate applied the following migration(s): migrations/ └─ 20201201110111_init/ └─ migration.sql

デジタルオーシャン上でのプロダクションデータベースの移行が成功しました。それは現在、Prismaのスキーマに合致しています。

Note

注意: もし以下のエラーメッセージを受け取った場合:
OutputError: P1001: `unique_identifier.db.ondigitalocean.com`:`25060` でデータベースサーバーに接続できません。

データベースダッシュボードに移動して、データベースがプロビジョニングされているか確認してください。データベースの信頼できるソースを更新または無効にする必要があるかもしれません。

以下のコマンドを使用して、Gitの変更をプッシュすることでアプリを展開することができます。

  1. git push

 

Note

注: アプリのプラットフォームは、実行時にDATABASE_URL環境変数をアプリケーションで利用できるようにします。Prismaクライアントは、Prismaスキーマのデータソースブロック内のenv(“DATABASE_URL”)とともに、その環境変数を使用します。

これにより、ビルドが自動的にトリガーされます。App Platformコンソールを開くと、デプロイの進行状況バーが表示されます。

Screencapture displaying the Deployment Progress Bar

展開に成功したら、「デプロイが完了しました」というメッセージを受け取ります。

デプロイされたGraphQL APIをデータベースでバックアップしました。ライブアプリを開いて、Apollo GraphQL Studioに移動します。ステップ3と同じクエリを使ってGraphQL APIをテストしてください。

最後のステップでは、ユーザーモデルを追加することでGraphQL APIを進化させます。

ステップ10- ユーザーモデルの追加

ブログのためのGraphQL APIには、Postという単一のエンティティが存在します。このステップでは、Prismaスキーマで新しいモデルを定義し、GraphQLスキーマを適応させることで、APIを発展させます。Postモデルに対して1対多の関係を持つUserモデルを導入し、投稿の著者を表現し、各ユーザーに複数の投稿を関連付けることができます。その後、GraphQLスキーマを発展させ、APIを介してユーザーの作成と投稿のユーザーへの関連付けを許可します。

最初に、Prismaスキーマを開いてください。

  1. nano prisma/schema.prisma

 

投稿モデルにauthorIdフィールドを追加し、ユーザーモデルを定義するために、以下の行を追加してください。

プリズマグラフQLのスキーマファイル(schema.prisma)
...
model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  author    User?   @relation(fields: [authorId], references: [id])
  authorId  Int?
}

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
  name  String
  posts Post[]
}

プリズマのスキーマに次のアイテムを追加しました。

  • Two relation fields: author and posts. Relation fields define connections between models at the Prisma level and do not exist in the database. These fields are used to generate the Prisma Client and to access relations with Prisma Client.
  • The authorId field, which is referenced by the @relation attribute. Prisma will create a foreign key in the database to connect Post and User.
  • The User model to represent users.

投稿モデルの作者フィールドは任意ですが、ユーザーに関連付けられていない投稿を作成することができます。

終わったら、ファイルを保存して終了してください。

次に、以下のコマンドを使って、ローカル環境で移行を作成し適用してください。

  1. npx prisma migrate dev –name “add-user”

 

移行が成功した場合、以下のメッセージが届きます。

Output

Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Datasource “db”: PostgreSQL database “my-blog”, schema “public” at “localhost:5432” Applying migration `20201201123056_add_user` The following migration(s) have been created and applied from new schema changes: migrations/ └─ 20201201123056_add_user/ └─ migration.sql Your database is now in sync with your schema. ✔ Generated Prisma Client (4.6.1 | library) to ./node_modules/@prisma/client in 53ms

コマンドは、新しいテーブルとフィールドを利用するためにPrisma Clientも生成します。

今、アプリケーションプラットフォーム上で本番データベースへの移行を実行し、データベーススキーマをローカルデータベースと同じにします。ターミナルで以下のコマンドを実行し、DATABASE_URLをアプリケーションプラットフォームの接続URLに設定してください。

  1. DATABASE_URL=your_db_connection_string npx prisma migrate deploy

 

以下の出力が提供されます。

Output

Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Datasource “db”: PostgreSQL database “db”, schema “public” at “unique_identifier.db.ondigitalocean.com:25060” 2 migrations found in prisma/migrations Applying migration `20201201123056_add_user` The following migration have been applied: migrations/ └─ 20201201123056_add_user/ └─ migration.sql All migrations have been successfully applied.

更新されたデータベーススキーマを活用するために、GraphQLスキーマとリゾルバを更新します。

src/schema.jsファイルを開く。

  1. nano src/schema.js

 

以下のように、typeDefsを更新して、ハイライトされた行を追加してください。

prisma-graphql/src/schema.jsを日本語に自然に言い換えると、以下のようになります:
「prisma-graphql/src/schema.jsのファイルです」
...
const typeDefs = gql`
  type User {
    email: String!
    id: ID!
    name: String
    posts: [Post!]!
  }

  type Post {
    content: String
    id: ID!
    published: Boolean!
    title: String!
    author: User
  }

  type Query {
    feed: [Post!]!
    post(id: ID!): Post
  }

  type Mutation {
    createUser(data: UserCreateInput!): User!
    createDraft(authorEmail: String, content: String, title: String!): Post!
    publish(id: ID!): Post
  }

  input UserCreateInput {
    email: String!
    name: String
    posts: [PostCreateWithoutAuthorInput!]
  }

  input PostCreateWithoutAuthorInput {
    content: String
    published: Boolean
    title: String!
  }
`
...

この更新されたコードでは、次の変更をGraphQLスキーマに追加します。

  • The User type, which returns an array of Post.
  • The author field to the Post type.
  • The createUser mutation, which expects the UserCreateInput as its input type.
  • The PostCreateWithoutAuthorInput input type used in the UserCreateInput input for creating posts as part of the createUser mutation.
  • The authorEmail optional argument to the createDraft mutation.

スキーマが更新されたので、スキーマに合致するようにリゾルバを更新します。

以下の強調された行を使って、リゾルバーオブジェクトを更新します。

プリズマ-GraphQL/src/schema.jsを日本語に自然に言い換えると、以下のようになります。
プリズマ-GraphQLのソースコード/src/schema.js
...
const resolvers = {
  Query: {
    feed: (parent, args) => {
      return prisma.post.findMany({
        where: { published: true },
      })
    },
    post: (parent, args) => {
      return prisma.post.findUnique({
        where: { id: Number(args.id) },
      })
    },
  },
  Mutation: {
    createDraft: (parent, args) => {
      return prisma.post.create({
        data: {
          title: args.title,
          content: args.content,
          published: false,
          author: args.authorEmail && {
            connect: { email: args.authorEmail },
          },
        },
      })
    },
    publish: (parent, args) => {
      return prisma.post.update({
        where: { id: Number(args.id) },
        data: {
          published: true,
        },
      })
    },
    createUser: (parent, args) => {
      return prisma.user.create({
        data: {
          email: args.data.email,
          name: args.data.name,
          posts: {
            create: args.data.posts,
          },
        },
      })
    },
  },
  User: {
    posts: (parent, args) => {
      return prisma.user
        .findUnique({
          where: { id: parent.id },
        })
        .posts()
    },
  },
  Post: {
    author: (parent, args) => {
      return prisma.post
        .findUnique({
          where: { id: parent.id },
        })
        .author()
    },
  },
}
...

今、createDraftミューテーションリゾルバは、渡された場合はauthorEmail引数を使用して、作成された下書きと既存のユーザーの関係を作成します。

新しいcreateUserミューテーションリゾルバーは、ネストされたライティングを使用してユーザーと関連する投稿を作成します。

ユーザーのポストや投稿者のリゾルバは、ユーザーまたは投稿がクエリされたときに、ポストと投稿者のフィールドをどのように解決するかを定義します。これらは、PrismaのFluent APIを使用して関連を取得します。

ファイルを保存して終了してください。

GraphQL APIをテストするためにサーバーを起動してください。

  1. npm start

 

以下のGraphQLミューテーションで、createUserリゾルバをテストを開始します。

mutation {
  createUser(data: { email: "natalia@prisma.io", name: "Natalia" }) {
    email
    id
  }
}

この変異により、ユーザーが作成されます。

次に、以下のミューテーションを使ってcreateDraftリゾルバをテストしてください。

mutation {
  createDraft(
    authorEmail: "natalia@prisma.io"
    title: "Deploying a GraphQL API to App Platform"
  ) {
    id
    title
    content
    published
    author {
      id
      name
    }
  }
}

クエリの戻り値が「投稿」の場合、いつでも著者を取得できます。この例では、「投稿の著者」リゾルバが呼び出されます。

テストが終了したら、サーバーを閉じてください。

変更内容をコミットし、APIをデプロイするためにプッシュしてください。

  1. git add .
  2. git commit -m “add user model”
  3. git push

 

アップデートが展開されるまで数分かかる場合があります。

Prisma Migrateを使って、データベースのスキーマを正常に進化させ、新しいモデルをGraphQL APIで公開しました。

結論

この記事では、Prismaを使用してGraphQL APIを作成し、Silicon CloudのApp Platformにデプロイしました。Apollo Serverを使用してGraphQLスキーマとリゾルバを定義しました。次に、GraphQLリゾルバでPrisma Clientを使用してPostgreSQLデータベースにデータを永続化し、クエリを実行しました。次のステップとして、個々のユーザーを取得するためのクエリと、既存のドラフトをユーザーに接続するためのミューテーションをGraphQL APIに拡張できます。

データベースのデータを探索したい場合は、Prisma Studioをご覧ください。また、Prismaのさまざまな側面について学び、prisma-examplesリポジトリのいくつかの実行可能な例プロジェクトを探索するために、Prismaのドキュメンテーションも訪れることができます。

このプロジェクトのコードは、Silicon Cloud コミュニティのリポジトリで見つけることができます。

コメントを残す 0

Your email address will not be published. Required fields are marked *