Refactor: Extract duplicated CMS collection patterns into shared utilities - #121
Conversation
- Created shared validation utilities (normalizeUrl, normalizeEmail, extractTags, extractFeatureList, serializeValue) - Created upsert factory to eliminate 50-100 line duplication across collections - Created shared access control and field definitions - Updated 7 collection files (Solutions, Repositories, HomepageFeatures, TeamMembers, Leads, NewsletterSubscribers, SiteSettings) - All tests passing, linter clean Co-authored-by: marcelo-m7 <117441129+marcelo-m7@users.noreply.github.com>
Co-authored-by: marcelo-m7 <117441129+marcelo-m7@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (supabaseId) { | ||
| // Insert with existing ID | ||
| const placeholders = buildPlaceholders(2); | ||
| query = ` | ||
| insert into public.${tableName} (id, ${insertFields}) | ||
| values ($1::uuid, ${placeholders}) | ||
| on conflict (${conflictFieldWithId}) do update set | ||
| ${updateFields}, | ||
| updated_at=now() | ||
| returning id`; | ||
| params = [supabaseId, ...fieldValues]; | ||
| } else { | ||
| // Insert without ID | ||
| const placeholders = buildPlaceholders(1); | ||
| const conflictField = conflictFieldWithoutId || conflictFieldWithId; | ||
| query = ` | ||
| insert into public.${tableName} (${insertFields}) | ||
| values (${placeholders}) | ||
| on conflict (${conflictField}) do update set | ||
| ${updateFields}, | ||
| updated_at=now() | ||
| returning id`; |
There was a problem hiding this comment.
Avoid referencing missing updated_at columns in upserts
The new createUpsertHook always appends updated_at=now() to the ON CONFLICT … DO UPDATE clause. Several collections that now use this factory (e.g. Leads, NewsletterSubscribers) write to tables that only define created_at and have no updated_at column in the migrations. Running their hooks will therefore raise column "updated_at" of relation … does not exist, preventing new leads/subscribers from syncing and blocking the Supabase ID backfill. Consider making the timestamp update conditional or configurable per table.
Useful? React with 👍 / 👎.
CMS collection files contained ~400 lines of duplicated code across database operations, validation, and access control patterns.
Changes
New Utilities
cms/src/utilities/validation.tsnormalizeUrl(),normalizeEmail()- Previously duplicated in 3 and 2 files respectivelyextractTags(),extractFeatureList(),serializeValue()- Common data extraction patternscms/src/utilities/upsert-factory.tscreateUpsertHook()- Factory replacing 50-100 lines of boilerplate per collectioncms/src/utilities/collection-helpers.tspublicReadAuthWrite,adminOnlyAccesssupabaseIdField,activeFieldUpdated Collections
Refactored Solutions, Repositories, HomepageFeatures, TeamMembers, Leads, NewsletterSubscribers, and SiteSettings to use shared utilities.
Before:
After:
Impact
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.