Cloudflare D1 > Tutorials > Build a Comments API
2023年8月20日時点でのCloudflare D1のTutorialsのBuild a Comments APIをやる
- Cloudflareのアカウントは作成済み
- npm v9.4.2
- Node.js v18.14.0
- create-cloudflare v2.1.1
- wrangler v3.5.1
create-cloudflareとwranglerはコマンド実行時にインストールできるので事前のインストール不要
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
1. Install Hono
プロジェクトのディレクトリに移動し、フレームワークのHonoをインストールする。
npm install hono
インストール後の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"
}
}
2. Initialize your Hono application
Honoの初期化とエンドポイントの定義を書く。
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
3. Create a database
データベースを作成する。名前は「d1-tutorials-comments-api-db」としておく。
npx wrangler d1 create d1-tutorials-comments-api-db
データベースを作成した時のコマンド実行結果に以下のような情報が出力されているので、それを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>"
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を作成する。
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
5. Execute SQL
GETリクエストの処理を書く。
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)
})
6. Insert data
POSTリクエストの処理を書く。
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")
}
})
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 │
└────┴─────────────┴─────────────┴────────────────┘
8. Test with an optional frontend
フロントエンドから使うならCORSのミドルウェアを追加しましょうということが書かれている。
今回はやらないのでドキュメントにあるコードだけ書いておいて終わる。
import { Hono } from 'hono';
import { cors } from 'hono/cors';
const app = new Hono();
app.use('/api/*', cors());