diff --git a/.env.sample b/.env.sample index c44f56d..3784206 100644 --- a/.env.sample +++ b/.env.sample @@ -7,7 +7,7 @@ SERVER_PORT=4000 # optional, server port (alias: PORT, PUBLIC_SERVER_URL.port) ( PUBLIC_X_ANON_KEY=... X_API_KEY=... -DATABASE_URL=file:local.db +DATABASE_URL=file:../../local.db BETTER_AUTH_SECRET=... BETTER_AUTH_URL=http://localhost:4000 diff --git a/docs/developer_readme.md b/docs/developer_readme.md index 34bb0ec..e6f03a3 100644 --- a/docs/developer_readme.md +++ b/docs/developer_readme.md @@ -10,8 +10,8 @@ bun install --frozen-lockfile ## 開発 ```bash -# データベースを作成するには、packages/server に移動してから以下のコマンドを実行してください。 -bunx drizzle-kit push +# データベースを作成するには、 `.env` で `DATABASE_URL` を設定し、以下のコマンドを実行してください。 +bun db push ``` ```bash diff --git a/package.json b/package.json index 422cd76..940ce6b 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "scripts": { "dev": "bun --filter=@packages/{web,server} dev", "dev:mock": "bun --filter=@packages/{web,server} dev:mock", + "db": "cd packages/server; bun --env-file=../../.env drizzle-kit", "storybook": "concurrently 'cd packages/server; bun dev' 'cd packages/web; bun run storybook'", "build": "cd packages/web && bun run build", "check": "bunx biome check .", diff --git a/packages/server/drizzle.config.ts b/packages/server/drizzle.config.ts index 165d2a6..af42008 100644 --- a/packages/server/drizzle.config.ts +++ b/packages/server/drizzle.config.ts @@ -1,10 +1,11 @@ import { defineConfig } from "drizzle-kit"; +import { env } from "./lib/env.ts"; export default defineConfig({ out: "./drizzle", schema: "./db/schema.ts", dialect: "sqlite", dbCredentials: { - url: process.env.DATABASE_URL ?? "file:local.db", + url: env.DATABASE_URL, }, }); diff --git a/packages/server/lib/auth.ts b/packages/server/lib/auth.ts index 3f0a01b..d6bcbe8 100644 --- a/packages/server/lib/auth.ts +++ b/packages/server/lib/auth.ts @@ -3,6 +3,7 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle"; import Elysia from "elysia"; import { db } from "../db/index.ts"; import * as schema from "../db/schema.ts"; +import { env } from "../lib/env.ts"; export const auth = betterAuth({ database: drizzleAdapter(db, { @@ -11,11 +12,11 @@ export const auth = betterAuth({ }), socialProviders: { google: { - clientId: process.env.GOOGLE_CLIENT_ID as string, - clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, + clientId: env.GOOGLE_CLIENT_ID, + clientSecret: env.GOOGLE_CLIENT_SECRET, }, }, - trustedOrigins: [process.env.PUBLIC_WEB_URL ?? "http://localhost:3000"], + trustedOrigins: [env.PUBLIC_WEB_URL], }); const betterAuthMacro = new Elysia({ name: "better-auth" }) diff --git a/packages/server/lib/env.ts b/packages/server/lib/env.ts new file mode 100644 index 0000000..e4f3181 --- /dev/null +++ b/packages/server/lib/env.ts @@ -0,0 +1,14 @@ +import * as e from "./utils/environment.ts"; + +export const env = { + DATABASE_URL: e.string("DATABASE_URL"), + PUBLIC_WEB_URL: e.string("PUBLIC_WEB_URL"), + GOOGLE_CLIENT_ID: e.string("GOOGLE_CLIENT_ID"), + GOOGLE_CLIENT_SECRET: e.string("GOOGLE_CLIENT_SECRET"), + + SERVER_PORT: e.string_optional("SERVER_PORT"), + PORT: e.string_optional("PORT"), + PUBLIC_SERVER_URL: e.string_optional("PUBLIC_SERVER_URL"), + + PUBLIC_MOCK_DATA: e.boolean("PUBLIC_MOCK_DATA"), +}; diff --git a/packages/server/lib/utils/environment.ts b/packages/server/lib/utils/environment.ts new file mode 100644 index 0000000..3c8c636 --- /dev/null +++ b/packages/server/lib/utils/environment.ts @@ -0,0 +1,21 @@ +import { panic } from "./panic.ts"; + +export function string(name: string) { + return ( + string_optional(name) ?? panic(`Environment variable ${name} not found`) + ); +} +export function string_optional(name: string): string | undefined { + return process.env[name]; +} +export function boolean(name: string, fallback?: boolean): boolean { + const val = string_optional(name); + if (val === "1" || val === "true") { + return true; + } + if (val === "0" || val === "false") { + return false; + } + if (fallback !== undefined) return fallback; + panic(`Environment variable ${name} not found`); +} diff --git a/packages/server/lib/utils/panic.ts b/packages/server/lib/utils/panic.ts new file mode 100644 index 0000000..e9cf828 --- /dev/null +++ b/packages/server/lib/utils/panic.ts @@ -0,0 +1,3 @@ +export function panic(message: string): never { + throw new Error(message); +} diff --git a/packages/server/serve.ts b/packages/server/serve.ts index 943f8b6..17b789a 100644 --- a/packages/server/serve.ts +++ b/packages/server/serve.ts @@ -1,17 +1,15 @@ import { app } from "./app.ts"; +import { env } from "./lib/env.ts"; const port = - process.env.SERVER_PORT ?? - process.env.PORT ?? - parsePublicServerURL() ?? - "4000"; + env.SERVER_PORT ?? env.PORT ?? parsePort(env.PUBLIC_SERVER_URL) ?? "4000"; app.listen(port, () => console.log(`Server started at http://localhost:${port}`), ); -function parsePublicServerURL() { - if (!process.env.PUBLIC_SERVER_URL) return undefined; - const url = new URL(process.env.PUBLIC_SERVER_URL); +function parsePort(urlstr: string | undefined) { + if (!urlstr) return undefined; + const url = new URL(urlstr); return url.port; }