Files
classroomio/packages/db
20e34e29dd feat(exercise): add open-ended thumbs up/down question type (#780)
* feat(ui): add THUMBS question type renderer

- Add seven new renderer files under renderers/thumbs/:
  thumbs-correct.ts, take.svelte, edit.svelte, preview.svelte,
  thumbs-review-toggle.svelte, review.svelte, submission.svelte
- Register THUMBS in renderer-contract.ts with edit/take/preview/submission/review
- Export ThumbsEdit, ThumbsTake, ThumbsPreview, ThumbsSubmission,
  ThumbsReview from exercise-question/index.ts
- Add THUMBS_FIXTURE, four thumbs label keys, and Thumbs story
  in storybook exercise-question files
- Add THUMBS case to question-type-modes.svelte submission builder

Co-authored-by: Rotimi Best <[email protected]>

* feat(question-types): add THUMBS contracts, scoring, and seed

Introduce the THUMBS question type (id 14) with boolean answer data,
codec, auto-grading, Zod validation, DB seed/schema docs, and binary
normalize support shared with TRUE_FALSE. Dashboard wiring is deferred.

Co-authored-by: Rotimi Best <[email protected]>

* feat(dashboard): wire THUMBS question type into exercise UI

Connect THUMBS option sync in edit/view modes, labels, picker icon,
and locale strings so the existing contracts surface in the dashboard.

Co-authored-by: Rotimi Best <[email protected]>

* fix(ui): polish thumbs question UI and move premium upgrade icon

Widen thumbs Yes/No toggles, inherit selected icon color via custom class,
replace badge-based review correctness with solid fill states and bare
Check/X icons, add a success pill in preview, and place the premium
upgrade icon at the end of the question type select row.

Co-authored-by: Rotimi Best <[email protected]>

* fix(ui): align thumbs review colors with prototypes

Tune correct/incorrect selected states so review buttons use dark
emerald/red content colors on solid fills, matching the design comps.

Co-authored-by: Rotimi Best <[email protected]>

* fix(ui): address remaining PR review comments

Use a shared timestamp local in thumbs edit fallback options.
Move border-beam animation-delay after the animation shorthand.
Alias --spacing to --ui-spacing for tw-animate compatibility.

Co-authored-by: Rotimi Best <[email protected]>

* fix(db): sync question_type sequence before seeding new types

Avoid duplicate key errors when question_type_id_seq lags behind rows
inserted via restore or explicit ids (e.g. THUMBS on restored databases).

Co-authored-by: Rotimi Best <[email protected]>

* fix(exercise): resolve thumbs review label ICU crash

Remove {value} ICU placeholder from thumbs.review.correct_answer_label
since labels are resolved at map-build time without context. Append the
dynamic yes/no label in thumbs-review-toggle instead.

Also bind question points through the questionnaire store index to avoid
the Svelte non-reactive property binding warning in edit-mode.

Co-authored-by: Rotimi Best <[email protected]>

* docs(agent): add THUMBS guidance and sync question type docs

Add shared agent question-type guide helpers in @cio/question-types and
use them across the teacher prompt, add/update_questions tool schemas,
legacy ai-assistant schemas, and MCP exercise tools.

- Document when to use THUMBS (Yes/No sentiment) vs TRUE_FALSE (factual)
- Fix stale MCP question type ids and add THUMBS=14
- Exclude disabled MATCHING/HOTSPOT from enabled type lists

Co-authored-by: Rotimi Best <[email protected]>

* fix(thumbs): clarify auto-grading and add editable option labels

THUMBS is auto-graded like TRUE_FALSE; the difference is thumbs UI with
customizable Yes/No-style labels and the teacher selecting the correct
option. Render take/preview/review from question.options labels and add
label inputs in the thumbs edit renderer. Update agent and MCP docs to
stop implying THUMBS is manual or non-gradable.

Co-authored-by: Rotimi Best <[email protected]>

* chore(mcp): bump version to 0.0.10

Co-authored-by: Rotimi Best <[email protected]>

* fix(question-types): make THUMBS open-ended with no correct answer

THUMBS is a sentiment/poll question type, not an auto-graded binary like
TRUE_FALSE. Remove correct-answer UI, scoring, and validation; update agent
and MCP docs accordingly.

Co-authored-by: Rotimi Best <[email protected]>

* fix(dashboard): stop treating THUMBS as auto-graded in editor validation

Normalize thumbs questions on load/save, show an Open-ended badge instead
of Auto, and only enforce points/correct-answer rules on auto-gradable types.

Co-authored-by: Rotimi Best <[email protected]>

* revert(dashboard): remove unsolicited open-ended grading badge

THUMBS uses the existing Manual badge like other non-auto-gradable types.

Co-authored-by: Rotimi Best <[email protected]>

* fix(exercise): show question title validation errors in editor

Display mapped title errors beneath the question title input instead of
only highlighting the question card border. Pass the exercise entity to
mapZodErrorsToTranslations so messages resolve to validations.exercise.*
keys, and use a translated snackbar key for save validation failures.

Co-authored-by: Rotimi Best <[email protected]>

* fix(mcp): build workspace deps before MCP publish bundle

The MCP esbuild step imports @cio/question-types and @cio/utils dist
outputs. CI failed on a clean checkout because mcp:build only built the
MCP package itself. Build those dependencies first so 0.0.10 can publish.

Co-authored-by: Rotimi Best <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: Rotimi Best <[email protected]>
2026-07-31 14:59:38 +01:00
..
2026-05-19 04:32:32 +01:00
2025-11-01 15:49:29 +01:00
2026-04-27 11:40:38 +01:00

@cio/db

This package handles everything related to the database, schema, migrations and connection.

Stack

  1. Postgres - We use postgres for the database
  2. Drizzle ORM - For managing and querying the database
  3. Better Auth - For managing the auth tables (users, account, session).

Workflow

We used Supabase in the past for managing the supabase but have now moved on to use postgres directly and auth managed by our backend. This means the workflow is a mix of the Database First approach (Option 1) and the Codebase First approach (Option 2). Learn more about each approach from the drizzle migration docs.

Here is how I do it:

1. Local DB to Drizzle Schema TS file

I have a postgres tool where I can make changes to the db as I want. I am not so familiar with drizzle that much so I am sticking with this for now.

```bash
pnpm db pull # this does sql -> drizzle ts code
```

2. Drizzle Schema file to Prod SQL

Now when I am ready to deploy the feature, I can use option 2 which is makes the typescript schema the source of truth. This command will only run on CI on every merge on a condition that there was a change to the schema file packages/db/src/schema.ts

```bash
pnpm db push # this does drizzle ts code to prod db
```

OR

I can make changes directly to the schema file and run pnpm db push to push the changes to the source db.

Setting up a new DB on Railway

Once you setup a Postgres DB on Railway, you should copyt the DATABASE_PUBLIC_URL and paste into your .env. In the .env we expect DATABASE_URL:

```.env
DATABASE_URL=what-you-copied-from-railway
```

Commands

db:setup

Prepares the database so the application can run. Run this for new databases or after provisioning Postgres.

pnpm db:setup

It performs three steps in order:

  1. Schema sync – Runs drizzle-kit push to apply the TypeScript schema to the database (creates/updates tables, enums, etc.).
  2. PostgreSQL roles – Creates the authenticated and anon roles if missing (used by RLS policies).
  3. Essential seed data – Inserts required reference data: roles (ADMIN, TUTOR, STUDENT), submission statuses, and question types.

Optional: Add --seed (or -s) to run the full seed, including demo users, organizations, courses, and other example data.

Requires DATABASE_URL or PRIVATE_DATABASE_URL in the environment. The scripts load .env from this package directory, so bootstrap it once from the template:

cp .env.example .env   # then set DATABASE_URL for your DB

db:backfill-profile-email-verification

Repairs stale profile.is_email_verified rows where the auth user is already verified (user.email_verified = true) or has a linked OAuth/SSO account, but the profile flag was never synced. Use after the auth/profile verification mismatch fix, or when users are blocked by the verify-email modal while send-verification-email returns EMAIL_IS_ALREADY_VERIFIED.

Dry run (lists affected count and a sample; makes no changes):

pnpm db:backfill-profile-email-verification
# or from repo root:
pnpm --filter @cio/db db:backfill-profile-email-verification

Apply updates:

pnpm db:backfill-profile-email-verification -- --execute

The script prints how many profiles were updated and verifies zero mismatches remain.

Seeding

The seed script populates the database with demo data for local development. It is idempotent — running it multiple times is safe; existing records are skipped.

Run all seeds

pnpm seed
# or explicitly
pnpm seed --all

Run individual seeds

Pass one or more flags to run only specific steps:

pnpm seed --users --profiles
pnpm seed --organizations --organization-members --organization-plan
Flag What it seeds
--roles ADMIN, TUTOR, STUDENT roles
--submissions Submission statuses
--question-types Question types
--users Auth users (from users.json)
--profiles User profiles
--accounts User accounts
--organizations Demo organizations
--organization-members Org membership records
--organization-plan Organization plan records (enterprise + early adopter)
--groups Course groups
--group-members Group membership records
--courses Demo courses
--sections Course sections
--lessons Lessons
--exercises Exercises
--questions Questions
--templates Exercise templates

Demo accounts

Email Password Role Plan
[email protected] 123456 Admin Basic (free)
[email protected] 123456 Student Basic (free)
[email protected] 123456 Admin Enterprise
[email protected] 123456 Student Enterprise
[email protected] 123456 Admin Early Adopter
[email protected] 123456 Student Early Adopter

Mock user credentials are defined in users.json. The demo accounts above use the password 123456.