Skip to content

refactor(db): boolean mode for 0|1 flag columns#130

Merged
hyldmo merged 2 commits into
mainfrom
hyldmo/boolean-mode-flags
May 11, 2026
Merged

refactor(db): boolean mode for 0|1 flag columns#130
hyldmo merged 2 commits into
mainfrom
hyldmo/boolean-mode-flags

Conversation

@hyldmo
Copy link
Copy Markdown
Owner

@hyldmo hyldmo commented May 11, 2026

Summary

Follow-up to #129. Switches every 0|1 integer flag in the schema to Drizzle's integer(..., { mode: 'boolean' }):

  • recipes.isPublic
  • ingredientUnits.isDefault
  • usdaPortions.isVolume
  • workoutLogs.failureFlag
  • userSettings.batchLookups
  • userSettings.modelFallback

The on-disk representation is unchanged (still INTEGER 0/1) — this is purely a TS-layer codec. Drizzle reads 0false and 1true and serializes the other way around.

Why: with these as plain number, {flag && <X/>} in JSX leaked the literal 0 (the bug fixed for isPublic in #129). With boolean, the same expression short-circuits to false and React renders nothing. Catches the whole class instead of one site at a time.

Call sites updated:

  • Writes pass true/false directly — no more flag ? 1 : 0 rituals.
  • Reads drop their Boolean(...) wrappers since the column already returns boolean.
  • SetRow.failureFlag prop retyped number | nullboolean | null; failureFlag === 1failureFlag === true.
  • parseIngredientList signature retyped for isDefault.

Migration

The generated migration is a no-op (SELECT 1). Drizzle wants to recreate five tables to refresh the schema string, but the actual SQLite column type is unchanged, so production data needs no rewrite. The journal entry is preserved so future migrations stay in order.

Test plan

  • yarn check passes
  • Recipe list renders globe icon on public recipes and nothing on private ones
  • Settings toggles (batch lookups, model fallback) save and round-trip correctly
  • Workout set logging persists failure flag; "F" badge shows on failed sets
  • Ingredient unit "default" picker still works (only one default per ingredient)

🤖 Generated with Claude Code

Switches `isPublic`, `isDefault`, `isVolume`, `failureFlag`, `batchLookups`,
and `modelFallback` to `integer(..., { mode: 'boolean' })`. The on-disk
representation stays as INTEGER 0/1 — this is purely a TS-layer codec.

Side effect: `{flag && <X/>}` short-circuits to `false` (which React skips)
instead of rendering the literal `0`. Prevents the whole class of bugs that
hit `recipe.isPublic` in #129.

Call sites updated: writes pass true/false directly (no more `? 1 : 0`),
reads compare against booleans, and the API layer drops its `Boolean(...)`
coercion wrappers since the column already returns boolean.

The generated migration is a no-op (`SELECT 1`) — Drizzle wants to recreate
five tables to refresh the schema string, but the actual SQLite column type
is unchanged, so production data needs no rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 11, 2026

Preview deployment

URL https://hyldmo-boolean-mode-flags.macromaxxing.pages.dev
Branch hyldmo/boolean-mode-flags
Commit c6f9275

Zod schemas (`z.boolean()` / `z.boolean().optional()`) already narrow these
inputs to `boolean | undefined` before they reach the handlers, so the `!!`
and `=== true` coercions added in c3abc1b were noise.

- workouts/addSet: `failureFlag: !!input.failureFlag` → pass through
- ingredients/createUnit: same for `isDefault`
- ingredients/updateUnit: drop the explicit `isDefault` override; just spread
  `updates` (the inner `if (updates.isDefault)` already clears siblings)
- WorkoutSessionPage optimistic update: pass `variables.failureFlag` directly
- SetRow: `failureFlag === true` → `failureFlag` (null/undefined fall through
  as falsy, which is what JSX wants anyway)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyldmo hyldmo merged commit 4f4696b into main May 11, 2026
3 checks passed
@hyldmo hyldmo deleted the hyldmo/boolean-mode-flags branch May 11, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant