Closed11

Cloudflare D1 > Tutorials > Build a Comments API

kwnkwn

create-cloudflareとwranglerはコマンド実行時にインストールできるので事前のインストール不要

kwnkwn

Prerequisites

プロジェクトを作成する。
ドキュメントではプロジェクト名を「d1-example」としているが、ExamplesがTutorialsと別で存在するため、明確に分けるために「d1-tutorials-comments-api」にした。

npx wrangler init d1-tutorials-comments-api


Get startedとコマンド違うなーと思ってたら警告が出てcreate-cloudflareに促された。
「y」を選択。

Using npm as package manager.
▲ [WARNING] The `init` command is no longer supported. Please use `npm create cloudflare@2 -- d1-tutorials-comments-api` instead.

  The `init` command will be removed in a future version.


Running `npm create cloudflare@2 -- d1-tutorials-comments-api`...
Need to install the following packages:
  create-cloudflare@2.1.1
Ok to proceed? (y) y


どのような種類のアプリケーションを作りたいか聞かれる。
ドキュメントでは「"Hello World" script」を選ぶように書いてあるが「"Hello World" Worker」の間違いだと思う。

What type of application do you want to create?
● "Hello World" Worker


TypeScriptを使うか聞かれる。
「Yes」を選択。

Do you want to use TypeScript?
Yes / No


Gitを使うか聞かれる。
「Yes」を選択。

Do you want to use git for version control?
Yes / No


デプロイするか聞かれる。
「No」を選択。

Do you want to deploy your application?
Yes / No
kwnkwn

1. Install Hono

プロジェクトのディレクトリに移動し、フレームワークのHonoをインストールする。

npm install hono


インストール後のpackage.jsonは以下の通り。

package.json
{
  "name": "d1-tutorials-comments-api",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "deploy": "wrangler deploy",
    "start": "wrangler dev"
  },
  "devDependencies": {
    "wrangler": "^3.0.0"
  },
  "dependencies": {
    "hono": "^3.4.3"
  }
}
kwnkwn

2. Initialize your Hono application

Honoの初期化とエンドポイントの定義を書く。

src/worker.js
import { Hono } from 'hono'

const app = new Hono()

app.get('/api/posts/:slug/comments', async c => {
  // Do something and return an HTTP response
  // Optionally, do something with `c.req.param("slug")`
})

app.post('/api/posts/:slug/comments', async c => {
  // Do something and return an HTTP response
  // Optionally, do something with `c.req.param("slug")`
})

export default app
kwnkwn

3. Create a database

データベースを作成する。名前は「d1-tutorials-comments-api-db」としておく。

npx wrangler d1 create d1-tutorials-comments-api-db


データベースを作成した時のコマンド実行結果に以下のような情報が出力されているので、それをwrangler.tomlに追加する。

wrangler.toml
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "d1-tutorials-comments-api-db"
database_id = "<unique-ID-for-your-database>"
kwnkwn

4. Interact with D1

コマンドでのSQL実行方法の紹介がされている。

npx wrangler d1 execute d1-tutorials-comments-api-db --command "SELECT name FROM sqlite_schema WHERE type ='table'"


schemas/schema.sqlを作成する。

schemas/schema.sql
DROP TABLE IF EXISTS comments;
CREATE TABLE IF NOT EXISTS comments (
  id integer PRIMARY KEY AUTOINCREMENT,
  author text NOT NULL,
  body text NOT NULL,
  post_slug text NOT NULL
);
CREATE INDEX idx_comments_post_slug ON comments (post_slug);
INSERT INTO COMMENTS (author, body, post_slug) VALUES ('Kristian', 'Great post!', 'hello-world');


SQLファイルを実行する。

npx wrangler d1 execute d1-tutorials-comments-api-db --file schemas/schema.sql
kwnkwn

5. Execute SQL

GETリクエストの処理を書く。

src/worker.js
app.get('/api/posts/:slug/comments', async c => {
  const { slug } = c.req.param()
  const { results } = await c.env.DB.prepare(`
    select * from comments where post_slug = ?
  `).bind(slug).all()
  return c.json(results)
})
kwnkwn

6. Insert data

POSTリクエストの処理を書く。

src/worker.js
app.post('/api/posts/:slug/comments', async c => {
  const { slug } = c.req.param()
  const { author, body } = await c.req.json()

  if (!author) return c.text("Missing author value for new comment")
  if (!body) return c.text("Missing body value for new comment")

  const { success } = await c.env.DB.prepare(`
    insert into comments (author, body, post_slug) values (?, ?, ?)
  `).bind(author, body, slug).run()

  if (success) {
    c.status(201)
    return c.text("Created")
  } else {
    c.status(500)
    return c.text("Something went wrong")
  }
})
kwnkwn

7. Deploy your Hono application

認証情報を確認する。
Cloudflareにログインできてない場合はここでログインするらしい。

npx wrangler whoami


Workerをデプロイする。

npx wrangler deploy


GETリクエストしてみるとSELECT文の実行結果が返ってくる。デフォルトだと<YOUR_SUBDOMAIN>にはメールアドレスのローカルパートが入っている。

curl https://d1-tutorials-comments-api.<YOUR_SUBDOMAIN>.workers.dev/api/posts/hello-world/comments
[{"id":1,"author":"Kristian","body":"Great post!","post_slug":"hello-world"}]


POSTリクエストをしてみる。

curl -X POST -H "Content-Type: application/json" -d '{"author": "author-test", "body": "body-test"}' https://d1-tutorials-comments-api.kwn1125dev.workers.dev/api/posts/post_slug-test/comments


SELECT文を実行して確認すると、先ほどのPOSTリクエストの結果が反映されている。

npx wrangler d1 execute d1-tutorials-comments-api-db --command='SELECT * FROM comments'

┌────┬─────────────┬─────────────┬────────────────┐
│ id │ author      │ body        │ post_slug      │
├────┼─────────────┼─────────────┼────────────────┤
│ 1  │ Kristian    │ Great post! │ hello-world    │
├────┼─────────────┼─────────────┼────────────────┤
│ 2  │ author-test │ body-test   │ post_slug-test │
└────┴─────────────┴─────────────┴────────────────┘
kwnkwn

8. Test with an optional frontend

フロントエンドから使うならCORSのミドルウェアを追加しましょうということが書かれている。
今回はやらないのでドキュメントにあるコードだけ書いておいて終わる。

src/worker.js
import { Hono } from 'hono';
import { cors } from 'hono/cors';

const app = new Hono();
app.use('/api/*', cors());
このスクラップは2023/08/20にクローズされました