Open12

Astro DBを試す

西畑一馬西畑一馬

Astro DBがリリースされたので試してみる。

https://astro.build/db/

まずはAstro Studioでアカウント作成。

https://studio.astro.build/

次にプロジェクト作成、作成方法が聞かれるので

ひとまず「Create from Template」を選んでみる。
次にどのテンプレートにするかが聞かれる

テンプレートは「Blank Project」を選んでみる。

GitHubのレポジトリの権限を要求される。

ので権限を与えました、このタイミングではリポジトリの作成は不要なので適当なリポジトリへのアクセス権限を割りあてて「swing-astro-db」というリポジトリをAstro Studioから作成しました。

これでプロジェクト作成は終了

西畑一馬西畑一馬

作成したリポジトリをクローンして設定をする。

git clone git@github.com:KazumaNishihata/swing-astro-db.git
cd swing-astro-db
npm install
npm run dev

DB作成

DBの設定はdb/config.tsに記述。

https://docs.astro.build/en/guides/astro-db/#tables

まずはシンプルに著者情報(author)と本文(body)をもつCommentテーブルを作成

db/config.ts
import { defineDb, defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    author: column.text(),
    body: column.text(),
  }
})

export default defineDb({
  tables: { Comment },
})

db/seed.tsにはデフォルトデータを入れておく。
(最初試したときは型情報が.astro/db-types.d.tsに反映されるまで時間がかかったので必要に応じてアプリの再起動など必要かも)

db/seed.ts
import { db, Comment } from 'astro:db';

export default async function() {
  await db.insert(Comment).values([
    { id:1, author: 'author1', body: 'comment1' },
    { id:2, author: 'author2', body: 'comment2' },
  ])
}

テーブルの取得

src/pages/index.astroでこの情報を読み込んでみる。

DBアクセスはDrizzle ORMを利用する
以下のようにしてコメントの取得と表示ができる

src/pages/index.astro
---
import { db, Comment } from 'astro:db';
const comments = await db.select().from(Comment);
---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
		<h2>Comments</h2>
		<ul>
			{
				comments.map(({ author, body }) => (
					<li>
						<strong>{author}</strong>
						{body}
					</li>
				))
			}
		</ul>
	</body>
</html>
西畑一馬西畑一馬

情報の追加

POST情報を扱うにはレンダリングをSSRに変更する必要がある。
astro.config.mjsoutput: "server",を追記

astro.config.mjs
import db from '@astrojs/db';
import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({
	integrations: [db()],
+	output: "server",
});

src/pages/index.astroに以下を追加すると入力フォームが追加されてコメントを追記していくことができます。

src/pages/index.astro
---
import { db, Comment } from 'astro:db';

if (Astro.request.method === 'POST') {
  const formData = await Astro.request.formData();
  const author = formData.get('author');
  const body = formData.get('body');
  if (typeof author === 'string' && typeof body === 'string') {
    await db.insert(Comment).values({ author, body });
  }
}

const comments = await db.select().from(Comment);
---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
		<h2>Comments</h2>
		<ul>
			{
				comments.map(({ author, body }) => (
					<li>
						<strong>{author}</strong>
						{body}
					</li>
				))
			}
		</ul>
		<form method="POST">
			<label for="author">Author</label>
			<input id="author" name="author" />
			<label for="body">body</label>
			<input id="body" name="body" />
			<button>Submit</button>
		</form>
	</body>
</html>
西畑一馬西畑一馬

この状態で一度GitHubにpush。そうするとAstro stuido上にもテーブルが作成さている。
連携が簡単だ

西畑一馬西畑一馬

一度CloudeFlareにリリースして動作するか確認してみる。

https://docs.astro.build/en/guides/deploy/cloudflare/

以下のコマンドでCloudeflare用のadapterを追加

npx astro add cloudflare

astro.config.mjsの設定を変更してGit Push

astro.config.mjs
import db from '@astrojs/db';
import { defineConfig } from 'astro/config';
+import cloudflare from "@astrojs/cloudflare";

// https://astro.build/config
export default defineConfig({
	integrations: [db()],
	output: "server",
+	adapter: cloudflare(),
});

Cloudeflareでは新たにプロジェクトを作成しておきます。

これでデプロイしてもうまく動かず

西畑一馬西畑一馬

以下でAstro Studioとの連携が手詰まり。

astro db loginでログインは成功するが astro db link で連携しようとすると認証エラーでログインしろと言われる。

% astro db login
Opening the following URL in your browser...
https://stardate.astro.build/auth/cli/login?returnTo=http%3A%2F%2Flocalhost%3A60021
If something goes wrong, copy-and-paste the URL into your browser.
✔ Successfully logged in!

% astro db link
? Link "~/Desktop/astro/swing-astro-db" with Astro Studio? › (Y/n)Unauthorized

  Are you logged in?
  Run astro db login to authenticate and then try linking again.
西畑一馬西畑一馬

astro db link で連携できないエラーは @astrojs/dbのバージョンを0.7.2->0.8.2にアップデートしたら解決

% npx astro add db
✔ Resolving packages...

  Astro will run the following command:
  If you skip this step, you can always run it yourself later

 ╭─────────────────────────────────╮
 │ npm install @astrojs/db@^0.8.2  │
 ╰─────────────────────────────────╯

✔ Continue? … yes
✔ Installing dependencies...

   success  Configuration up-to-date.
西畑一馬西畑一馬

ローカルでビルドを試すがエラーに

package.jsonのbuildコマンドに--remoteオプションを付けて

package.json
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
+    "build": "astro build --remote",
    "preview": "astro preview",
    "astro": "astro"
  },

ビルドを実行

% npm run build

> studio-template-empty@0.0.1 build
> astro build --remote

21:25:47 [WARN] [@astrojs/cloudflare] The current configuration does not support image optimization. To allow your project to build with the original, unoptimized images, the image service has been automatically switched to the 'noop' option. See https://docs.astro.build/en/reference/configuration-reference/#imageservice
21:25:47 [vite] Re-optimizing dependencies because vite config has changed
21:25:47 [astro:db] database: remote
21:25:47 [build] output: "server"
21:25:47 [build] directory: /swing-astro-db/dist/
21:25:47 [build] adapter: @astrojs/cloudflare
21:25:47 [build] Collecting build info...
21:25:47 [build] ✓ Completed in 2.84s.
21:25:47 [build] Building server entrypoints...
21:25:48 [vite] ✓ built in 588ms
21:25:48 [build] ✓ Completed in 619ms.
21:25:48
 finalizing server assets

21:25:48 [build] Rearranging server assets...
✘ [ERROR] Could not resolve "node:fs"

    node_modules/vite/dist/node/index.js:6:41:
      6import { existsSync, readFileSync } from 'node:fs';
        ╵                                          ~~~~~~~~~

  The package "node:fs" wasn't found on the file system but is built into node. Are you trying to
  bundle for node? You can use "platform: 'node'" to do that, which will remove this error.

✘ [ERROR] Could not resolve "node:fs/promises"

    node_modules/vite/dist/node/index.js:8:7:
      8 │ import 'node:fs/promises';
        ╵        ~~~~~~~~~~~~~~~~~~

以下の修正がリリースされたら多分なおるヤツ(後で気づいたけど3/14の日付だったのでこの日マージされたかとおもったけど1年前の3/14だったので関係なかった)

https://github.com/withastro/astro/issues/6535

西畑一馬西畑一馬

1晩寝かしたら@astrojs/dbastroの新しいバージョンがリリースされてたのでアップデート

% npm outdated
Package      Current  Wanted  Latest  Location                  Depended by
@astrojs/db    0.8.2   0.8.5   0.8.5  node_modules/@astrojs/db  swing-astro-db
astro          4.5.3   4.5.4   4.5.4  node_modules/astro        swing-astro-db
wrangler      3.34.0  3.34.2  3.34.2  node_modules/wrangler     swing-astro-db

そうするとビルド通りました。

% npm run build

> studio-template-empty@0.0.1 build
> astro build --remote

✔ Connected to remote database.

プロダクト的に不安定そうなのでハマったら1晩寝かすのがよさそう

西畑一馬西畑一馬

ビルドできてたのでwranglerを利用してローカルで確認

% npx wrangler pages dev ./dist --compatibility-date=2024-03-15
✨ Compiled Worker successfully
 ⛅️ wrangler 3.34.2
-------------------
[wrangler:inf] Ready on http://localhost:8788

起動はできたけど http://localhost:8788にアクセスするとエラーになる。
認証がうまく行ってない、nodeアダプターで試しても同様になるのでなにか設定が足りてないのだと思う

[ERROR] 10:27:20 [ERROR] Error: Failed to execute query.

  Query: select "id", "author", "body" from "Comment"
  Full error: 401 Unauthorized
      at null.<anonymous>
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:62:76024)
      at aa (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:62:75774)
      at async n.map.sql
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:62:75892)
      at async Xo.all
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:62:21173)
      at null.<anonymous> (async
  file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/.wrangler/tmp/dev-QA61zE/gtrnlvneoy4.js:6699:13)
      at async pi
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:25:278)
      at async lp
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:24:113)
      at async Sc
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:41:2599)
      at async Response.status
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:83:11884)
      at async Wg
  (file:///Users/nishihatakazuma/Desktop/astro/swing-astro-db/dist/_worker.js:83:3268)

[wrangler:inf] GET / 500 Internal Server Error (320ms)