feat: Add support for indexes on tables, mirroring the existing unique constraints implementation#830
Conversation
…e constraints implementation
🦋 Changeset detectedLatest commit: bba6a2b The changes in this PR will be included in the next version bump. This PR includes changesets to release 23 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughThis pull request introduces model index support across the Baseplate project builder. It adds a new Prisma model index generator, extends the model schema to include an indexes array, creates a new entity type for model indexes, implements backend support to generate Prisma indexes, and provides a complete UI layer for creating and editing model indexes. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as Web UI
participant Form as React Hook Form
participant Schema as Zod Schema
participant Model as Model State
User->>UI: Opens Model Index Dialog
UI->>Form: Initialize with existing/empty index
User->>UI: Selects fields from available model fields
UI->>Schema: Validate field selection (min 1)
Schema-->>Form: Validation result
alt Create New Index
User->>UI: Click Save
Form->>Schema: Validate and normalize
Schema-->>Form: Valid index object with generated ID
Form->>Model: Append new index to model.indexes
else Edit Existing Index
User->>UI: Click Save
Form->>Schema: Validate and normalize
Schema-->>Form: Valid index object with existing ID
Form->>Model: Replace existing index in model.indexes
end
Model-->>UI: Update badges and sections
User->>UI: Sees updated index count in badges
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
packages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/badges/model-field-badges.tsx (1)
40-47: Variable shadowing:idxshadows the component prop.The filter callback parameter
idxshadows the component'sidxprop. Consider renaming to avoid confusion:♻️ Suggested rename for clarity
const indexes = useWatch({ control, name: 'model.indexes', compute: (idxs) => idxs - ?.filter((idx) => idx.fields.some((f) => f.fieldRef === field.id)) - .map((idx) => idx.id) ?? [], + ?.filter((index) => index.fields.some((f) => f.fieldRef === field.id)) + .map((index) => index.id) ?? [], });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/badges/model-field-badges.tsx around lines 40 - 47, The compute callback for useWatch is shadowing the component prop idx; rename the callback parameter used in the filter/map (currently "idx") to something unique like "index" or "modelIndex" to avoid confusion with the component prop "idx"; update both the filter and map callbacks to use the new name (e.g., index.fields.some(...); .map((index) => index.id)) while keeping references to control, name: 'model.indexes', compute and field.id unchanged.packages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/model-field-form.tsx (1)
66-68: Variable shadowing:idxshadows the component prop.Similar to the unique constraints filter pattern, the callback parameter
idxshadows the component'sidxprop (line 45):♻️ Suggested rename for consistency
- const ownIndexes = indexes.filter((idx) => - idx.fields.some((f) => f.fieldRef === watchedField.id), + const ownIndexes = indexes.filter((index) => + index.fields.some((f) => f.fieldRef === watchedField.id), );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/model-field-form.tsx around lines 66 - 68, The callback parameter `idx` in the filter used to compute `ownIndexes` shadows the component prop `idx`; rename the callback parameter (for example to `index` or `idxItem`) in the expression that uses `indexes.filter((...) => ...)` so it no longer conflicts with the prop, and update any references inside that callback (e.g., `index.fields.some((f) => f.fieldRef === watchedField.id)`) to match the new name for consistency with the unique constraints filter pattern and to avoid shadowing the `idx` prop.packages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/indexes/model-index-form.tsx (1)
61-64: Consider adding a confirmation step before deleting an index.The delete action immediately removes the index without user confirmation. While this is consistent with the dialog context (user can cancel the dialog), adding a brief confirmation could prevent accidental deletions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/indexes/model-index-form.tsx around lines 61 - 64, onDelete currently removes the index immediately (it calls onModelChange with modelValue.filter(...)) — add a confirmation step before performing the deletion: prompt the user (using the app’s existing confirm/Modal utility or fallback to window.confirm) asking to confirm deletion of the index referenced by indexId (or include index label if available), and only call onModelChange(modelValue.filter((idx) => idx.id !== indexId)) and onSubmitSuccess() when the user confirms; if they cancel, do nothing. Use the onDelete function in model-index-form.tsx as the insertion point and preserve existing calls to onModelChange and onSubmitSuccess.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/badges/model-field-badges.tsx:
- Around line 40-47: The compute callback for useWatch is shadowing the
component prop idx; rename the callback parameter used in the filter/map
(currently "idx") to something unique like "index" or "modelIndex" to avoid
confusion with the component prop "idx"; update both the filter and map
callbacks to use the new name (e.g., index.fields.some(...); .map((index) =>
index.id)) while keeping references to control, name: 'model.indexes', compute
and field.id unchanged.
In
`@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/indexes/model-index-form.tsx:
- Around line 61-64: onDelete currently removes the index immediately (it calls
onModelChange with modelValue.filter(...)) — add a confirmation step before
performing the deletion: prompt the user (using the app’s existing confirm/Modal
utility or fallback to window.confirm) asking to confirm deletion of the index
referenced by indexId (or include index label if available), and only call
onModelChange(modelValue.filter((idx) => idx.id !== indexId)) and
onSubmitSuccess() when the user confirms; if they cancel, do nothing. Use the
onDelete function in model-index-form.tsx as the insertion point and preserve
existing calls to onModelChange and onSubmitSuccess.
In
`@packages/project-builder-web/src/routes/data/models/edit`.$key/-components/fields/model-field-form.tsx:
- Around line 66-68: The callback parameter `idx` in the filter used to compute
`ownIndexes` shadows the component prop `idx`; rename the callback parameter
(for example to `index` or `idxItem`) in the expression that uses
`indexes.filter((...) => ...)` so it no longer conflicts with the prop, and
update any references inside that callback (e.g., `index.fields.some((f) =>
f.fieldRef === watchedField.id)`) to match the new name for consistency with the
unique constraints filter pattern and to avoid shadowing the `idx` prop.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2127a744-14c5-4f5f-b22f-b06023c64744
📒 Files selected for processing (12)
.changeset/add-model-indexes.mdpackages/fastify-generators/src/generators/prisma/prisma-model-index/prisma-model-index.generator.tspackages/project-builder-lib/src/schema/models/models.tspackages/project-builder-lib/src/schema/models/types.tspackages/project-builder-server/src/compiler/backend/models.tspackages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/badges/model-field-badges.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/indexes/model-index-badge.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/indexes/model-index-dialog.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/indexes/model-index-form.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/-components/fields/model-field-form.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/-components/model-indexes-section.tsxpackages/project-builder-web/src/routes/data/models/edit.$key/index.tsx
…e constraints implementation
Summary by CodeRabbit
Release Notes