fix: MariaDB compatibility, Docker build, and StatsCounter props

- Replace serial() with int().autoincrement() for MariaDB compatibility
- Expose DB port 3306 in docker-compose for local dev tooling
- Remove drizzle/ COPY from Dockerfile (using push, not migrations)
- Fix StatsCounter props mismatch on home page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 13:17:51 -05:00
co-authored by Claude Opus 4.6
parent d192062793
commit 3b6159e6d0
4 changed files with 35 additions and 35 deletions
+27 -27
View File
@@ -1,13 +1,13 @@
import {
mysqlTable, varchar, int, text, boolean, timestamp, json,
mysqlEnum, uniqueIndex, index, serial
mysqlEnum, uniqueIndex, index
} from 'drizzle-orm/mysql-core';
import { relations } from 'drizzle-orm';
// ── Auth ──────────────────────────────────────────
export const users = mysqlTable('users', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
email: varchar({ length: 255 }).notNull().unique(),
passwordHash: varchar('password_hash', { length: 255 }).notNull(),
name: varchar({ length: 255 }).notNull(),
@@ -27,13 +27,13 @@ export const sessions = mysqlTable('sessions', {
// ── Pets ──────────────────────────────────────────
export const intakeSources = mysqlTable('intake_sources', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
name: varchar({ length: 255 }).notNull(),
active: boolean().notNull().default(true)
});
export const vets = mysqlTable('vets', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
name: varchar({ length: 255 }).notNull(),
clinic: varchar({ length: 255 }),
phone: varchar({ length: 50 }),
@@ -45,7 +45,7 @@ export const vets = mysqlTable('vets', {
});
export const pets = mysqlTable('pets', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
name: varchar({ length: 255 }).notNull(),
slug: varchar({ length: 255 }).notNull().unique(),
species: mysqlEnum(['dog', 'cat', 'other']).notNull().default('dog'),
@@ -91,7 +91,7 @@ export const pets = mysqlTable('pets', {
]);
export const petPhotos = mysqlTable('pet_photos', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
petId: int('pet_id').notNull().references(() => pets.id, { onDelete: 'cascade' }),
url: varchar({ length: 500 }).notNull(),
alt: varchar({ length: 255 }),
@@ -101,7 +101,7 @@ export const petPhotos = mysqlTable('pet_photos', {
});
export const petMedical = mysqlTable('pet_medical', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
petId: int('pet_id').notNull().references(() => pets.id, { onDelete: 'cascade' }),
type: mysqlEnum([
'vaccine', 'surgery', 'checkup', 'medication', 'deworming',
@@ -117,7 +117,7 @@ export const petMedical = mysqlTable('pet_medical', {
});
export const fosterAssignments = mysqlTable('foster_assignments', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
petId: int('pet_id').notNull().references(() => pets.id, { onDelete: 'cascade' }),
userId: int('user_id').notNull().references(() => users.id),
startDate: timestamp('start_date').notNull().defaultNow(),
@@ -128,7 +128,7 @@ export const fosterAssignments = mysqlTable('foster_assignments', {
});
export const mentors = mysqlTable('mentors', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
userId: int('user_id').notNull().references(() => users.id).unique(),
bio: text(),
active: boolean().notNull().default(true),
@@ -136,7 +136,7 @@ export const mentors = mysqlTable('mentors', {
});
export const petMentors = mysqlTable('pet_mentors', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
petId: int('pet_id').notNull().references(() => pets.id, { onDelete: 'cascade' }),
mentorId: int('mentor_id').notNull().references(() => mentors.id, { onDelete: 'cascade' }),
assignedAt: timestamp('assigned_at').notNull().defaultNow()
@@ -145,7 +145,7 @@ export const petMentors = mysqlTable('pet_mentors', {
// ── Applications ──────────────────────────────────
export const applications = mysqlTable('applications', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
type: mysqlEnum(['adoption', 'foster', 'volunteer', 'surrender']).notNull(),
status: mysqlEnum(['pending', 'reviewing', 'approved', 'denied', 'withdrawn']).notNull().default('pending'),
applicantName: varchar('applicant_name', { length: 255 }).notNull(),
@@ -161,7 +161,7 @@ export const applications = mysqlTable('applications', {
});
export const applicationHomevisitNotes = mysqlTable('application_homevisit_notes', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
applicationId: int('application_id').notNull().references(() => applications.id, { onDelete: 'cascade' }),
userId: int('user_id').notNull().references(() => users.id),
notes: text().notNull(),
@@ -172,7 +172,7 @@ export const applicationHomevisitNotes = mysqlTable('application_homevisit_notes
// ── Finance ───────────────────────────────────────
export const sponsors = mysqlTable('sponsors', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
name: varchar({ length: 255 }).notNull(),
tier: mysqlEnum(['top_dog', 'wagging_tails', 'wet_noses']).notNull().default('wet_noses'),
logoUrl: varchar('logo_url', { length: 500 }),
@@ -184,7 +184,7 @@ export const sponsors = mysqlTable('sponsors', {
});
export const donations = mysqlTable('donations', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
donorName: varchar('donor_name', { length: 255 }),
donorEmail: varchar('donor_email', { length: 255 }),
amount: int().notNull(),
@@ -202,7 +202,7 @@ export const donations = mysqlTable('donations', {
});
export const expenses = mysqlTable('expenses', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
description: varchar({ length: 255 }).notNull(),
amount: int().notNull(),
category: varchar({ length: 100 }),
@@ -217,7 +217,7 @@ export const expenses = mysqlTable('expenses', {
// ── Content ───────────────────────────────────────
export const events = mysqlTable('events', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
title: varchar({ length: 255 }).notNull(),
description: text(),
location: varchar({ length: 255 }),
@@ -230,7 +230,7 @@ export const events = mysqlTable('events', {
});
export const happyTails = mysqlTable('happy_tails', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
petId: int('pet_id').references(() => pets.id),
title: varchar({ length: 255 }).notNull(),
story: text().notNull(),
@@ -244,7 +244,7 @@ export const happyTails = mysqlTable('happy_tails', {
});
export const contentBlocks = mysqlTable('content_blocks', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
page: varchar({ length: 100 }).notNull(),
sectionKey: varchar('section_key', { length: 100 }).notNull(),
content: json().notNull(),
@@ -254,7 +254,7 @@ export const contentBlocks = mysqlTable('content_blocks', {
]);
export const newsletterSubscribers = mysqlTable('newsletter_subscribers', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
email: varchar({ length: 255 }).notNull().unique(),
name: varchar({ length: 255 }),
subscribedAt: timestamp('subscribed_at').notNull().defaultNow(),
@@ -262,7 +262,7 @@ export const newsletterSubscribers = mysqlTable('newsletter_subscribers', {
});
export const contactMessages = mysqlTable('contact_messages', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
name: varchar({ length: 255 }).notNull(),
email: varchar({ length: 255 }).notNull(),
subject: varchar({ length: 255 }),
@@ -274,7 +274,7 @@ export const contactMessages = mysqlTable('contact_messages', {
// ── Foster Portal ─────────────────────────────────
export const fosterSubmissions = mysqlTable('foster_submissions', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
userId: int('user_id').notNull().references(() => users.id),
petId: int('pet_id').notNull().references(() => pets.id, { onDelete: 'cascade' }),
type: mysqlEnum(['note', 'photo', 'update']).notNull().default('update'),
@@ -287,7 +287,7 @@ export const fosterSubmissions = mysqlTable('foster_submissions', {
});
export const supplyRequests = mysqlTable('supply_requests', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
userId: int('user_id').notNull().references(() => users.id),
petId: int('pet_id').references(() => pets.id),
items: text().notNull(),
@@ -302,21 +302,21 @@ export const supplyRequests = mysqlTable('supply_requests', {
// ── Config & System ───────────────────────────────
export const siteSettings = mysqlTable('site_settings', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
key: varchar({ length: 100 }).notNull().unique(),
value: text().notNull(),
updatedAt: timestamp('updated_at').notNull().defaultNow().onUpdateNow()
});
export const orgConfig = mysqlTable('org_config', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
key: varchar({ length: 100 }).notNull().unique(),
value: json().notNull(),
updatedAt: timestamp('updated_at').notNull().defaultNow().onUpdateNow()
});
export const auditLog = mysqlTable('audit_log', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
userId: int('user_id').references(() => users.id),
action: varchar({ length: 100 }).notNull(),
entity: varchar({ length: 100 }),
@@ -330,7 +330,7 @@ export const auditLog = mysqlTable('audit_log', {
]);
export const pageViews = mysqlTable('page_views', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
path: varchar({ length: 500 }).notNull(),
petId: int('pet_id').references(() => pets.id),
ipAddress: varchar('ip_address', { length: 45 }),
@@ -344,7 +344,7 @@ export const pageViews = mysqlTable('page_views', {
]);
export const aiJobs = mysqlTable('ai_jobs', {
id: serial().primaryKey(),
id: int().autoincrement().primaryKey(),
type: varchar({ length: 50 }).notNull(),
input: json().notNull(),
status: mysqlEnum(['pending', 'processing', 'completed', 'failed']).notNull().default('pending'),
+6 -7
View File
@@ -64,13 +64,12 @@
</section>
<!-- Stats Counter -->
<StatsCounter
totalRescued={data.stats.totalRescued}
totalAdopted={data.stats.totalAdopted}
currentFosters={data.stats.currentFosters}
availableNow={data.stats.availableNow}
yearsRescuing={data.stats.yearsRescuing}
/>
<StatsCounter stats={[
{ label: 'Pets Rescued', value: data.stats.totalRescued },
{ label: 'Pets Adopted', value: data.stats.totalAdopted },
{ label: 'Available Now', value: data.stats.availableNow },
{ label: 'Active Fosters', value: data.stats.currentFosters }
]} />
<!-- Featured Pets Section -->
<section class="py-16 md:py-24">