📜

Hono+D1で掲示板

2024/01/24に公開

挨拶

あけましておめでとうございます
taisan11です
今回は掲示板を作ったので紹介?解説?をしていきたいと思います
先に完成品がこちらです(多分こっち見た方が早い)
https://github.com/taisan11/hono-d1-kejiban
リポジトリ名は適当なので...

使ったもの

  • Hono
  • drizzleorm
  • cloudflare D1
  • cloudflare workers

機能

2024/1現在以下の機能が実装されています

  • スレッド一覧を閲覧(直近20個のみ)(GET)
  • スレッド内を閲覧(GET)
  • スレッド作成(POST)
  • レス投稿(POST)
    全てAPI形式となっていて、UIがありません

それぞれのコード

適当に紹介するだけです

DB

DB設計

import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
// スレッド
export const threads = sqliteTable("threads", {
	id: integer("id").primaryKey().notNull(), //スレッドID(タイムスタンプ)
	title: text("title").notNull(), //スレタイ
	createdAt: text("created_at").notNull(), //投稿日時
	ip_addr: text("ip_addr").notNull(), //投稿者IPアドレス
	isDelete: integer("isDelete", { mode: "boolean" }).notNull().default(false), // 削除フラグ
});
// レス
export const post = sqliteTable("post", {
	ex_id: integer("ex_id").primaryKey().notNull(), //投稿ID(非公開)(スレッドID+レス番号+乱数)
	id: integer("id").notNull().references(() => threads.id), //スレッドID(タイムスタンプ)
	res_id: integer("res_id").notNull(), //レス番号(0001~1000まで)
	name: text("name").notNull(), //投稿者名
	mail: text("mail"), //任意!!投稿者メールアドレス(キャップ可)
	message: text("message").notNull(), //投稿内容
	createdAt: text("created_at").notNull(), //投稿日時
	ip_addr: text("ip_addr").notNull(), //投稿者IPアドレス
	isDelete: integer("isDelete", { mode: "boolean" }).notNull().default(false), // 削除フラグ
});

スレッド一覧を閲覧

app.get("/api/threads", async (c) => {
	const db = drizzle(c.env.DB, { schema });
	const result = await db.select().from(threads).limit(10).execute();//ここで取得
	return c.json(result.map((record) => ({ [record.id]: record.title })));
});

map関数で必要なものだけをJsonで再生成

スレッド内を閲覧

app.get("/api/threads/:threadid", async (c) => {
	const threadidIn = c.req.param("threadid");
	const threadidDate = parseInt(threadidIn);

	const db = drizzle(c.env.DB);
	const result2 = await db.select().from(post).where(eq(post.id, threadidDate));
	return c.json(result2);
});

スレッドにresを追加するやつ(関数?)

関数にしてまとめたかったけど無理だった

//スレッドにレスを追加
console.debug(body.id);
let resulta = await db.query.post.findFirst({
	where: (post, { eq }) => eq(post.id, body.id),
	orderBy: (post, { desc }) => [desc(post.res_id)],
});
if (!resulta) {
	//@ts-ignore
	resulta = { res_id: 1 }; // resultaがundefinedの場合に新しいオブジェクトを代入
}
console.debug(resulta);
if (!resulta) {
	// レコードが存在しない場合の処理をここに書く
	return c.text("指定されたIDのレコードが存在しません");
}
const record = resulta; // 最初のレコードを取得
const ex_id = Number(`${record.res_id + 1}${body.id}${Math.floor(Math.random() * 88) + 10}`,);
const res_id = Number(`${record.res_id + 1}`);
const id = Number(`${body.id}`);
console.debug(body.mail);
//@ts-ignore
let kextuka;
if (!body.mail) {
	console.debug("mailないよ");
	kextuka = await db
		.insert(post)
		.values({
			ex_id: ex_id,
			id: id,
			res_id: res_id,
			name: body.name,
			message: body.message,
			createdAt: new Date().toISOString(),
			ip_addr: body.ip_addr,
			// user_id: body.user_id,
	})
	.execute();
} else {
	console.debug("mailあるよ");
	kextuka = await db
		.insert(post)
		.values({
			ex_id: ex_id,
			id: body.id,
			res_id: record.res_id + 1,
			name: body.name,
			mail: body.mail,
			message: body.message,
			createdAt: new Date().toISOString(),
			ip_addr: body.ip_addr,
			// user_id: body.user_id,
			).execute();
	})

スレッドにレスを追加するやつ

app.post("/api/post/:threadid", async (c) => {
	// dataの確認
	if (await dataConfirmation(c, true)) {
		return dataConfirmation(c, true);
	}
	const body = await c.req.json();
	const db = drizzle(c.env.DB, { schema });
	if (!body.id) {
		return c.text("すれIDがないよ");
	}
	//スレッドにレスを追加(省略)
	return c.text(String(kextuka.success));
});

ここ関数にしたかった...関数にしたらこんなに省略できるのに...
いつか考えよ

スレッド作るやつ

app.post("/api/newThread", async (c) => {
	if (await dataConfirmation(c, false)) {
		return dataConfirmation(c, false);
	}
	const body = await c.req.json();
	const db = drizzle(c.env.DB, { schema });
	if (!body.title) {
		return c.text("すれタイがないよ");
	}
	const date = new Date();
	const UnixTime = date.getTime();
	//スレッド一覧にスレッドを追加
	const result = await db
		.insert(threads)
		.values({
			id: UnixTime,
			title: body.title,
			createdAt: new Date().toISOString(),
			ip_addr: body.ip_addr,
		})
		.returning({ insertedId: threads.id })
		.execute();
	//スレッドにレスを追加(省略)(微妙に違うけどいいや)
	return c.json(result);
});

最後に

いつかUIも作ることを目標にします。
次回→やる予定(UI編)

Discussion