From 0cab1522cf09c3e8cdf1624e4038df648babc781 Mon Sep 17 00:00:00 2001 From: Flea Flicker Date: Thu, 21 May 2026 22:54:01 +0000 Subject: [PATCH 01/11] fix(deps): update pnpm-lock.yaml for better-auth ^1.5.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ERR_PNPM_OUTDATED_LOCKFILE — specifiers in lockfile did not match packages/db/package.json after better-auth upgrade. Co-Authored-By: Claude Opus 4.7 --- pnpm-lock.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d3451b..a108283 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: version: 0.7.6(hono@4.12.18)(zod@4.4.3) better-auth: specifier: ^1.5.6 - version: 1.6.10(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)) + version: 1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)) drizzle-orm: specifier: ^0.38.4 version: 0.38.4(kysely@0.28.17)(postgres@3.4.9) @@ -84,6 +84,9 @@ importers: packages/db: dependencies: + better-auth: + specifier: ^1.5.6 + version: 1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)) drizzle-orm: specifier: ^0.38.4 version: 0.38.4(kysely@0.28.17)(postgres@3.4.9) @@ -3927,7 +3930,7 @@ snapshots: balanced-match@4.0.4: {} - better-auth@1.6.10(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)): + better-auth@1.6.10(drizzle-kit@0.30.6)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9))(vitest@3.2.4(@types/node@22.19.18)(tsx@4.21.0)): dependencies: '@better-auth/core': 1.6.10(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.3))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/drizzle-adapter': 1.6.10(@better-auth/core@1.6.10(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.4.3))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.38.4(kysely@0.28.17)(postgres@3.4.9)) @@ -3947,6 +3950,7 @@ snapshots: nanostores: 1.3.0 zod: 4.4.3 optionalDependencies: + drizzle-kit: 0.30.6 drizzle-orm: 0.38.4(kysely@0.28.17)(postgres@3.4.9) vitest: 3.2.4(@types/node@22.19.18)(tsx@4.21.0) transitivePeerDependencies: From 2b78fcf731e7f80c77f5bed6242027539eef589b Mon Sep 17 00:00:00 2001 From: Flea Flicker Date: Fri, 22 May 2026 02:16:49 +0000 Subject: [PATCH 02/11] fix(ci): build all service images + upgrade Node 22 + pin packageManager (GRO-1522) - Upgrade CI jobs (lint-typecheck, test, build) to Node 22 - Dockerfile uses node:22-alpine for base and runner stages - Root package.json gets packageManager field for corepack pin - Docker build already targets all 4 stages (api/migrate/seed/reset) Co-Authored-By: Paperclip --- .github/workflows/ci.yml | 6 +++--- Dockerfile | 4 ++-- package.json | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3881905..0fb65b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: pnpm - name: Install dependencies @@ -49,7 +49,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: pnpm - name: Install dependencies @@ -71,7 +71,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 22 cache: pnpm - name: Install dependencies diff --git a/Dockerfile b/Dockerfile index 662ad85..ada297f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20-alpine AS base +FROM node:22-alpine AS base RUN corepack enable && corepack prepare pnpm@9.15.4 --activate WORKDIR /app @@ -12,7 +12,7 @@ RUN mkdir -p /home/node/.cache/node/corepack COPY apps/api/ apps/api/ RUN pnpm --filter @groombook/api build -FROM node:20-alpine AS runner +FROM node:22-alpine AS runner RUN corepack enable && corepack prepare pnpm@9.15.4 --activate WORKDIR /app ENV NODE_ENV=production diff --git a/package.json b/package.json index d2e71b5..871b4bd 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,6 @@ "version": "0.0.1", "private": true, "type": "module", + "packageManager": "pnpm@9.15.4", "license": "AGPL-3.0-only" } From 59893908e29fee91a850b0a5a7cf161a9a506520 Mon Sep 17 00:00:00 2001 From: Flea Flicker Date: Fri, 22 May 2026 02:23:05 +0000 Subject: [PATCH 03/11] fix: resolve pre-existing TypeScript errors for CI compliance - petsExtendedFields.test.ts: import and/eq/exists/or from db/index.js (avoids mock scope collision with TypeScript closures) - petsExtendedFields.test.ts: add non-null assertion on petRows[0] in makeDeleteChainable (petRows always has at least one element) - factories.ts buildPet: add missing extended pet fields to defaults (coatType, temperamentScore, temperamentFlags, medicalAlerts, preferredCuts) so the inferred PetRow type is satisfied Co-Authored-By: Paperclip --- apps/api/src/__tests__/petsExtendedFields.test.ts | 3 ++- apps/api/src/db/factories.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/api/src/__tests__/petsExtendedFields.test.ts b/apps/api/src/__tests__/petsExtendedFields.test.ts index a013d88..e07850e 100644 --- a/apps/api/src/__tests__/petsExtendedFields.test.ts +++ b/apps/api/src/__tests__/petsExtendedFields.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { Hono } from "hono"; import type { AppEnv, StaffRow } from "../middleware/rbac.js"; import { petsRouter } from "../routes/pets.js"; +import { and, eq, exists, or } from "../db/index.js"; // ─── Mock staff fixtures ────────────────────────────────────────────────────── @@ -134,7 +135,7 @@ function makeDeleteChainable(): unknown { } if (prop === "returning") { return () => { - const row = petRows[0]; + const row = petRows[0]!; deletedId = row.id as string; return [row]; }; diff --git a/apps/api/src/db/factories.ts b/apps/api/src/db/factories.ts index 9f801e2..da36fe6 100644 --- a/apps/api/src/db/factories.ts +++ b/apps/api/src/db/factories.ts @@ -103,6 +103,11 @@ export function buildPet(overrides: Partial & { clientId: string }): Pet photoKey: null, photoUploadedAt: null, image: null, + coatType: null, + temperamentScore: null, + temperamentFlags: [], + medicalAlerts: [], + preferredCuts: [], createdAt: new Date("2025-01-01T00:00:00Z"), updatedAt: new Date("2025-01-01T00:00:00Z"), }; From ce9fcfb362dade3bd457e0861a95dc70bca45c40 Mon Sep 17 00:00:00 2001 From: Flea Flicker Date: Fri, 22 May 2026 02:36:18 +0000 Subject: [PATCH 04/11] fix: resolve pre-existing test and TypeScript errors for CI compliance - Fix CLIENT_ID/PET_ID in petsExtendedFields.test.ts to valid UUIDs so createPetSchema validation (z.string().uuid()) passes in tests - Replace top-level imports of and/eq/exists/or with vi.fn() stubs in petsExtendedFields.test.ts mock to avoid vi.mock hoisting ReferenceError - Add impersonationAuditLogs proxy + insert() chain to portal.test.ts mock to fix audit-log write failures - Add 5 missing extended fields to buildPet factory defaults - Add non-null assertion on petRows[0] in makeDeleteChainable Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/__tests__/petsExtendedFields.test.ts | 13 ++++++------- apps/api/src/__tests__/portal.test.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/api/src/__tests__/petsExtendedFields.test.ts b/apps/api/src/__tests__/petsExtendedFields.test.ts index e07850e..33e0698 100644 --- a/apps/api/src/__tests__/petsExtendedFields.test.ts +++ b/apps/api/src/__tests__/petsExtendedFields.test.ts @@ -2,7 +2,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { Hono } from "hono"; import type { AppEnv, StaffRow } from "../middleware/rbac.js"; import { petsRouter } from "../routes/pets.js"; -import { and, eq, exists, or } from "../db/index.js"; // ─── Mock staff fixtures ────────────────────────────────────────────────────── @@ -22,8 +21,8 @@ const MANAGER: StaffRow = { // ─── Mutable mock state ─────────────────────────────────────────────────────── -const CLIENT_ID = "client-uuid-extended"; -const PET_ID = "pet-uuid-extended"; +const CLIENT_ID = "550e8400-e29b-41d4-a716-446655440001"; +const PET_ID = "660e8400-e29b-41d4-a716-446655440002"; let petRows: Record[] = []; let appointmentRows: Record[] = []; @@ -164,10 +163,10 @@ vi.mock("../db", () => { }), pets, appointments, - and, - eq, - exists, - or, + and: vi.fn(), + eq: vi.fn(), + exists: vi.fn(), + or: vi.fn(), }; }); diff --git a/apps/api/src/__tests__/portal.test.ts b/apps/api/src/__tests__/portal.test.ts index 2388943..bbeacbd 100644 --- a/apps/api/src/__tests__/portal.test.ts +++ b/apps/api/src/__tests__/portal.test.ts @@ -67,6 +67,11 @@ vi.mock("../db", () => { { get: (t, p) => (p === "_name" ? "impersonationSessions" : { table: "impersonationSessions", column: p }) } ); + const impersonationAuditLogs = new Proxy( + { _name: "impersonationAuditLogs" }, + { get: (t, p) => (p === "_name" ? "impersonationAuditLogs" : { table: "impersonationAuditLogs", column: p }) } + ); + const appointments = new Proxy( { _name: "appointments" }, { get: (t, p) => (p === "_name" ? "appointments" : { table: "appointments", column: p }) } @@ -99,8 +104,12 @@ vi.mock("../db", () => { }), }), }), + insert: () => ({ + values: () => ({ returning: () => [{}] }), + }), }), impersonationSessions, + impersonationAuditLogs, appointments, eq: vi.fn(), and: vi.fn(), From da913d600fa8b76dc4082db1f35a66ad3a60c9ef Mon Sep 17 00:00:00 2001 From: The Dogfather <20+gb_dogfather@noreply.git.farh.net> Date: Fri, 22 May 2026 02:56:20 +0000 Subject: [PATCH 05/11] fix(ci): add Gitea CI workflow with all 4 image targets + Node 22 (GRO-1522) Co-Authored-By: Paperclip --- .gitea/workflows/ci.yml | 139 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 .gitea/workflows/ci.yml diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..e16d7e5 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,139 @@ +name: CI + +on: + push: + branches: [main, dev] + pull_request: + branches: [main, dev] + workflow_dispatch: + inputs: + ref: + description: "Branch or ref to run CI against" + required: false + default: "main" + +jobs: + lint-typecheck: + name: Lint & Typecheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: '9.15.4' + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Typecheck + run: pnpm typecheck + + - name: Lint + run: pnpm lint + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: '9.15.4' + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run tests + run: pnpm test + + docker: + name: Build & Push Docker Images + runs-on: ubuntu-latest + needs: [lint-typecheck, test] + steps: + - uses: actions/checkout@v4 + + - name: Generate image tag + id: version + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + TAG="pr-${{ github.event.pull_request.number }}-${GITHUB_SHA::7}" + else + TAG="$(date -u +%Y.%m.%d)-${GITHUB_SHA::7}" + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "Image tag: $TAG" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: git.farh.net + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Build and push API image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: runner + push: true + tags: | + git.farh.net/groombook/api:${{ steps.version.outputs.tag }} + ${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/api:latest' || '' }} + cache-from: type=registry,ref=git.farh.net/groombook/cache:api + cache-to: type=registry,ref=git.farh.net/groombook/cache:api,mode=max + + - name: Build and push Migrate image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: migrate + push: true + tags: | + git.farh.net/groombook/migrate:${{ steps.version.outputs.tag }} + ${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/migrate:latest' || '' }} + cache-from: type=registry,ref=git.farh.net/groombook/cache:migrate + cache-to: type=registry,ref=git.farh.net/groombook/cache:migrate,mode=max + + - name: Build and push Seed image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: seed + push: true + tags: | + git.farh.net/groombook/seed:${{ steps.version.outputs.tag }} + ${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/seed:latest' || '' }} + cache-from: type=registry,ref=git.farh.net/groombook/cache:seed + cache-to: type=registry,ref=git.farh.net/groombook/cache:seed,mode=max + + - name: Build and push Reset image + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + target: reset + push: true + tags: | + git.farh.net/groombook/reset:${{ steps.version.outputs.tag }} + ${{ github.ref == 'refs/heads/main' && 'git.farh.net/groombook/reset:latest' || '' }} + cache-from: type=registry,ref=git.farh.net/groombook/cache:reset + cache-to: type=registry,ref=git.farh.net/groombook/cache:reset,mode=max From 3bec5d095ae52fad8219e96a311b61330b6f9910 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Fri, 22 May 2026 03:02:20 +0000 Subject: [PATCH 06/11] fix(db): remove duplicate petSizeCategoryEnum/coatTypeEnum declarations (GRO-1522) The schema file had two sets of these enum declarations with different values. The first (stale) set broke all tests importing @groombook/db via the vitest alias, causing CI to fail and blocking the docker build job. Co-Authored-By: Paperclip --- packages/db/src/schema.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts index bb3c8f6..313ba0c 100644 --- a/packages/db/src/schema.ts +++ b/packages/db/src/schema.ts @@ -48,22 +48,6 @@ export const clientStatusEnum = pgEnum("client_status", [ "disabled", ]); -export const petSizeCategoryEnum = pgEnum("pet_size_category", [ - "small", - "medium", - "large", - "xlarge", -]); - -export const coatTypeEnum = pgEnum("coat_type", [ - "smooth", - "double", - "wire", - "curly", - "long", - "hairless", -]); - // ─── Better-Auth Tables ────────────────────────────────────────────────────── export const user = pgTable("user", { From d7d98791c7b01bfe48fa3ce4541d42f9a236bc79 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Fri, 22 May 2026 03:04:12 +0000 Subject: [PATCH 07/11] fix(ci): use monorepo-filtered commands in Gitea CI (GRO-1522) The root pnpm scripts typecheck/lint/test the stale src/ directory. Use pnpm --filter @groombook/api to target the correct apps/api/ path, matching the GitHub Actions CI configuration. Co-Authored-By: Paperclip --- .gitea/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index e16d7e5..df10baa 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -32,10 +32,10 @@ jobs: run: pnpm install --frozen-lockfile - name: Typecheck - run: pnpm typecheck + run: pnpm --filter @groombook/api typecheck - name: Lint - run: pnpm lint + run: pnpm --filter @groombook/api lint test: name: Test @@ -56,7 +56,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Run tests - run: pnpm test + run: pnpm --filter @groombook/api test docker: name: Build & Push Docker Images From 4086b6f5c0ec9e32f0df0b3b8549993d75acf729 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Fri, 22 May 2026 03:09:00 +0000 Subject: [PATCH 08/11] fix: remove duplicate bufferRules table and duplicate properties blocking Docker build CI Run 942 Docker build fails on TS2451 (duplicate bufferRules at lines 190 & 653 of schema.ts), TS1117 (duplicate defaultBufferMinutes in services table, duplicate coatType/petSizeCategory in factories.ts), and TS2322 (null vs number for defaultBufferMinutes in factories.ts). Keep the newer, more complete bufferRules declaration (with comments and index) and the .notNull().default(0) variant of defaultBufferMinutes. Co-Authored-By: Claude Opus 4.6 --- packages/db/src/factories.ts | 4 +--- packages/db/src/schema.ts | 23 ----------------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/packages/db/src/factories.ts b/packages/db/src/factories.ts index cac71f7..2ecad06 100644 --- a/packages/db/src/factories.ts +++ b/packages/db/src/factories.ts @@ -105,8 +105,6 @@ export function buildPet(overrides: Partial & { clientId: string }): Pet photoKey: null, photoUploadedAt: null, image: null, - coatType: null, - petSizeCategory: null, createdAt: new Date("2025-01-01T00:00:00Z"), updatedAt: new Date("2025-01-01T00:00:00Z"), }; @@ -121,7 +119,7 @@ export function buildService(overrides: Partial = {}): ServiceRow { description: "A grooming service", basePriceCents: 6500, durationMinutes: 60, - defaultBufferMinutes: null, + defaultBufferMinutes: 0, active: true, createdAt: new Date("2025-01-01T00:00:00Z"), updatedAt: new Date("2025-01-01T00:00:00Z"), diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts index 313ba0c..de0ab29 100644 --- a/packages/db/src/schema.ts +++ b/packages/db/src/schema.ts @@ -180,35 +180,12 @@ export const services = pgTable("services", { description: text("description"), basePriceCents: integer("base_price_cents").notNull(), durationMinutes: integer("duration_minutes").notNull(), - defaultBufferMinutes: integer("default_buffer_minutes"), active: boolean("active").notNull().default(true), defaultBufferMinutes: integer("default_buffer_minutes").notNull().default(0), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }); -export const bufferRules = pgTable( - "buffer_rules", - { - id: uuid("id").primaryKey().defaultRandom(), - serviceId: uuid("service_id") - .notNull() - .references(() => services.id, { onDelete: "cascade" }), - sizeCategory: petSizeCategoryEnum("size_category"), - coatType: coatTypeEnum("coat_type"), - bufferMinutes: integer("buffer_minutes").notNull(), - createdAt: timestamp("created_at").notNull().defaultNow(), - updatedAt: timestamp("updated_at").notNull().defaultNow(), - }, - (t) => [ - unique("uq_buffer_rules_service_size_coat").on( - t.serviceId, - t.sizeCategory, - t.coatType - ), - ] -); - export const staff = pgTable("staff", { id: uuid("id").primaryKey().defaultRandom(), name: text("name").notNull(), From 46f134a294a5eaa5485fdfd9367d467cacd96b1b Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Fri, 22 May 2026 03:11:03 +0000 Subject: [PATCH 09/11] fix: use root pnpm build instead of --filter for api in Dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnpm --filter @groombook/api doesn't match the workspace root package because pnpm-workspace.yaml only includes packages/*. The root package.json already has a build script that compiles src/ → dist/, which is what the Dockerfile copies. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6914964..2612a2c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ COPY src/ src/ COPY tsconfig.json ./ RUN pnpm --filter @groombook/types build && \ pnpm --filter @groombook/db build && \ - pnpm --filter @groombook/api build + pnpm build # Runtime FROM node:22-alpine AS runner From 9462915a66f632ca601f211ed67af37b89ca6963 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Fri, 22 May 2026 03:17:13 +0000 Subject: [PATCH 10/11] fix: align root src/ enum values with packages/db schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root src/routes/ used stale enum values (xlarge→extra_large, smooth→silky, missing short/medium/silky from coatType) and sizeCategory→petSizeCategory field name mismatch with the pets table column. Co-Authored-By: Claude Opus 4.6 --- src/routes/book.ts | 4 ++-- src/routes/buffer-rules.ts | 4 ++-- src/routes/pets.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/routes/book.ts b/src/routes/book.ts index 828c11c..c380439 100644 --- a/src/routes/book.ts +++ b/src/routes/book.ts @@ -193,8 +193,8 @@ bookRouter.post( name: body.petName, species: body.petSpecies, breed: body.petBreed ?? null, - coatType: (body.petCoatType ?? null) as "smooth" | "double" | "wire" | "curly" | "long" | "hairless" | null, - petSizeCategory: (body.petSizeCategory ?? null) as "small" | "medium" | "large" | "xlarge" | null, + coatType: (body.petCoatType ?? null) as "short" | "medium" | "long" | "double" | "wire" | "silky" | "curly" | "hairless" | null, + petSizeCategory: (body.petSizeCategory ?? null) as "small" | "medium" | "large" | "extra_large" | null, }) .returning(); const pet = petInserted[0]; diff --git a/src/routes/buffer-rules.ts b/src/routes/buffer-rules.ts index fb3ff2b..72a98a7 100644 --- a/src/routes/buffer-rules.ts +++ b/src/routes/buffer-rules.ts @@ -19,8 +19,8 @@ bufferRulesRouter.use("*", requireRole("manager")); const createBufferRuleSchema = z.object({ serviceId: z.string().uuid(), - sizeCategory: z.enum(["small", "medium", "large", "xlarge"]).optional(), - coatType: z.enum(["smooth", "double", "wire", "curly", "long", "hairless"]).optional(), + sizeCategory: z.enum(["small", "medium", "large", "extra_large"]).optional(), + coatType: z.enum(["short", "medium", "long", "double", "wire", "silky", "curly", "hairless"]).optional(), bufferMinutes: z.number().int().positive(), }); diff --git a/src/routes/pets.ts b/src/routes/pets.ts index 9642450..039e8a5 100644 --- a/src/routes/pets.ts +++ b/src/routes/pets.ts @@ -24,8 +24,8 @@ const createPetSchema = z.object({ shampooPreference: z.string().max(500).optional(), specialCareNotes: z.string().max(2000).optional(), customFields: z.record(z.string(), z.string()).optional(), - sizeCategory: z.enum(["small", "medium", "large", "xlarge"]).optional(), - coatType: z.enum(["smooth", "double", "wire", "curly", "long", "hairless"]).optional(), + petSizeCategory: z.enum(["small", "medium", "large", "extra_large"]).optional(), + coatType: z.enum(["short", "medium", "long", "double", "wire", "silky", "curly", "hairless"]).optional(), }); const updatePetSchema = createPetSchema.partial().omit({ clientId: true }); From 40422a14f010fa9df6d72931a26f1b3d1ffca530 Mon Sep 17 00:00:00 2001 From: Flea Flicker Date: Fri, 22 May 2026 12:33:17 +0000 Subject: [PATCH 11/11] fix(seed): use --filter @groombook/db to invoke seed/migrate/reset scripts The seed/migrate/reset Dockerfile targets specified `pnpm db:migrate` etc., but those scripts are defined in packages/db/package.json, not at the workspace root. pnpm workspace filtering is required to route the command to the correct package. - migrate: pnpm --filter @groombook/db migrate - seed: pnpm --filter @groombook/db seed - reset: pnpm --filter @groombook/db reset Co-Authored-By: Paperclip --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2612a2c..ac523cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,12 +42,12 @@ CMD ["node", "dist/index.js"] # Migrate stage — runs drizzle-kit migrate against the database FROM builder AS migrate -CMD ["pnpm", "db:migrate"] +CMD ["pnpm", "--filter", "@groombook/db", "migrate"] # Seed stage — populates the database with test data FROM builder AS seed -CMD ["pnpm", "db:seed"] +CMD ["pnpm", "--filter", "@groombook/db", "seed"] # Reset stage — drops all tables, re-runs migrations, and re-seeds FROM builder AS reset -CMD ["pnpm", "db:reset"] +CMD ["pnpm", "--filter", "@groombook/db", "reset"]