Initial commit
This commit is contained in:
221
scripts/setup-d1-drizzle.sh
Normal file
221
scripts/setup-d1-drizzle.sh
Normal file
@@ -0,0 +1,221 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# better-auth + D1 + Drizzle ORM Setup Script
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
#
|
||||
# This script automates the setup of better-auth with Cloudflare D1
|
||||
# and Drizzle ORM.
|
||||
#
|
||||
# CRITICAL: better-auth requires Drizzle ORM or Kysely for D1.
|
||||
# There is NO direct d1Adapter()!
|
||||
#
|
||||
# Usage:
|
||||
# chmod +x setup-d1-drizzle.sh
|
||||
# ./setup-d1-drizzle.sh my-app-name
|
||||
#
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if app name provided
|
||||
if [ -z "$1" ]; then
|
||||
echo -e "${RED}Error: Please provide an app name${NC}"
|
||||
echo "Usage: ./setup-d1-drizzle.sh my-app-name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_NAME=$1
|
||||
DB_NAME="${APP_NAME}-db"
|
||||
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}better-auth + D1 + Drizzle Setup${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo -e "App Name: ${GREEN}$APP_NAME${NC}"
|
||||
echo -e "Database: ${GREEN}$DB_NAME${NC}"
|
||||
echo ""
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 1: Install dependencies
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[1/8]${NC} Installing dependencies..."
|
||||
npm install better-auth drizzle-orm drizzle-kit @cloudflare/workers-types hono
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 2: Create D1 database
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[2/8]${NC} Creating D1 database..."
|
||||
wrangler d1 create $DB_NAME
|
||||
|
||||
echo -e "${GREEN}✓${NC} Database created!"
|
||||
echo -e "${YELLOW}⚠${NC} Copy the database_id from the output above and update wrangler.toml"
|
||||
echo ""
|
||||
read -p "Press Enter after updating wrangler.toml..."
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 3: Create directory structure
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[3/8]${NC} Creating directory structure..."
|
||||
mkdir -p src/db
|
||||
mkdir -p drizzle
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 4: Create database schema
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[4/8]${NC} Creating database schema..."
|
||||
cat > src/db/schema.ts << 'EOF'
|
||||
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
export const user = sqliteTable("user", {
|
||||
id: text().primaryKey(),
|
||||
name: text().notNull(),
|
||||
email: text().notNull().unique(),
|
||||
emailVerified: integer({ mode: "boolean" }).notNull().default(false),
|
||||
image: text(),
|
||||
createdAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
updatedAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
});
|
||||
|
||||
export const session = sqliteTable("session", {
|
||||
id: text().primaryKey(),
|
||||
userId: text()
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
token: text().notNull(),
|
||||
expiresAt: integer({ mode: "timestamp" }).notNull(),
|
||||
ipAddress: text(),
|
||||
userAgent: text(),
|
||||
createdAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
updatedAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
});
|
||||
|
||||
export const account = sqliteTable("account", {
|
||||
id: text().primaryKey(),
|
||||
userId: text()
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: "cascade" }),
|
||||
accountId: text().notNull(),
|
||||
providerId: text().notNull(),
|
||||
accessToken: text(),
|
||||
refreshToken: text(),
|
||||
accessTokenExpiresAt: integer({ mode: "timestamp" }),
|
||||
refreshTokenExpiresAt: integer({ mode: "timestamp" }),
|
||||
scope: text(),
|
||||
idToken: text(),
|
||||
password: text(),
|
||||
createdAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
updatedAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
});
|
||||
|
||||
export const verification = sqliteTable("verification", {
|
||||
id: text().primaryKey(),
|
||||
identifier: text().notNull(),
|
||||
value: text().notNull(),
|
||||
expiresAt: integer({ mode: "timestamp" }).notNull(),
|
||||
createdAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
updatedAt: integer({ mode: "timestamp" })
|
||||
.notNull()
|
||||
.default(sql`(unixepoch())`),
|
||||
});
|
||||
EOF
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 5: Create Drizzle config
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[5/8]${NC} Creating Drizzle config..."
|
||||
cat > drizzle.config.ts << 'EOF'
|
||||
import type { Config } from "drizzle-kit";
|
||||
|
||||
export default {
|
||||
out: "./drizzle",
|
||||
schema: "./src/db/schema.ts",
|
||||
dialect: "sqlite",
|
||||
driver: "d1-http",
|
||||
dbCredentials: {
|
||||
databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
|
||||
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
|
||||
token: process.env.CLOUDFLARE_TOKEN!,
|
||||
},
|
||||
} satisfies Config;
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}✓${NC} Config created"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠${NC} Create a .env file with:"
|
||||
echo " CLOUDFLARE_ACCOUNT_ID=your-account-id"
|
||||
echo " CLOUDFLARE_DATABASE_ID=your-database-id"
|
||||
echo " CLOUDFLARE_TOKEN=your-api-token"
|
||||
echo ""
|
||||
read -p "Press Enter after creating .env..."
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 6: Generate migrations
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[6/8]${NC} Generating migrations..."
|
||||
npx drizzle-kit generate
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 7: Apply migrations
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[7/8]${NC} Applying migrations..."
|
||||
echo -e "Applying to ${GREEN}local${NC} D1..."
|
||||
wrangler d1 migrations apply $DB_NAME --local
|
||||
|
||||
read -p "Apply to remote D1 too? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "Applying to ${GREEN}remote${NC} D1..."
|
||||
wrangler d1 migrations apply $DB_NAME --remote
|
||||
fi
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Step 8: Set secrets
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
echo -e "${YELLOW}[8/8]${NC} Setting secrets..."
|
||||
echo ""
|
||||
echo -e "${BLUE}Generating BETTER_AUTH_SECRET...${NC}"
|
||||
SECRET=$(openssl rand -base64 32)
|
||||
echo "$SECRET" | wrangler secret put BETTER_AUTH_SECRET
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Setup complete!${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}Next Steps${NC}"
|
||||
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo "1. Add OAuth client IDs and secrets (if needed):"
|
||||
echo " wrangler secret put GOOGLE_CLIENT_ID"
|
||||
echo " wrangler secret put GOOGLE_CLIENT_SECRET"
|
||||
echo ""
|
||||
echo "2. Test locally:"
|
||||
echo " npm run dev"
|
||||
echo ""
|
||||
echo "3. Deploy:"
|
||||
echo " wrangler deploy"
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠ IMPORTANT:${NC} Update your wrangler.toml with the database_id from Step 2"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user