diff --git a/packages/db/package.json b/packages/db/package.json index 471b0276..d9eca228 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -76,7 +76,8 @@ "db:push-dump-to-new-db": "tsx src/scripts/push-dump-to-new-db.ts", "db:restore-lesson-section-from-dump": "tsx src/scripts/restore-lesson-section-from-dump.ts", "db:restore-organizationmember-from-dump": "tsx src/scripts/restore-organizationmember-from-dump.ts", - "db:disable-v1-content-grouping-from-dump": "tsx src/scripts/disable-v1-content-grouping-from-dump.ts" + "db:disable-v1-content-grouping-from-dump": "tsx src/scripts/disable-v1-content-grouping-from-dump.ts", + "db:fix-landing-courses": "tsx src/scripts/fix-landing-page-courses-links.ts" }, "dependencies": { "@better-auth/sso": "^1.4.18", diff --git a/packages/db/src/scripts/fix-landing-page-courses-links.ts b/packages/db/src/scripts/fix-landing-page-courses-links.ts new file mode 100644 index 00000000..a938eb45 --- /dev/null +++ b/packages/db/src/scripts/fix-landing-page-courses-links.ts @@ -0,0 +1,115 @@ +import { eq, isNotNull } from 'drizzle-orm'; +import { db } from '../drizzle'; +import { organization } from '../schema'; + +function replacePrograms(label: string): string { + return label.replace(/programs/gi, (match) => (match[0] === match[0].toUpperCase() ? 'Courses' : 'courses')); +} + +function fixAction( + action: Record | undefined, + changes: string[] +): Record | undefined { + if (!action || typeof action !== 'object') return action; + + const fixed = { ...action }; + + if (fixed.href === '#courses') { + fixed.href = '/courses'; + changes.push('hero action href #courses → /courses'); + } + + if (typeof fixed.label === 'string' && /programs/i.test(fixed.label)) { + const updated = replacePrograms(fixed.label); + changes.push(`hero action label "${fixed.label}" → "${updated}"`); + fixed.label = updated; + } + + return fixed; +} + +async function fixLandingPageCoursesLinks() { + const dryRun = process.argv.includes('--dry-run'); + + if (dryRun) { + console.log('DRY RUN — no changes will be written.\n'); + } + + try { + const rows = await db + .select({ id: organization.id, siteName: organization.siteName, landingpage: organization.landingpage }) + .from(organization) + .where(isNotNull(organization.landingpage)); + + let updatedCount = 0; + + for (const row of rows) { + const lp = row.landingpage as Record | null; + + if (!lp || typeof lp !== 'object') continue; + + const changes: string[] = []; + const fixed = { ...lp }; + + // Fix hero actions + const hero = fixed.hero as Record | undefined; + if (hero && typeof hero === 'object') { + const fixedHero = { ...hero }; + + fixedHero.primaryAction = fixAction(fixedHero.primaryAction as Record | undefined, changes); + fixedHero.secondaryAction = fixAction( + fixedHero.secondaryAction as Record | undefined, + changes + ); + + fixed.hero = fixedHero; + } + + // Fix navItems + const navItems = fixed.navItems as Array> | undefined; + if (Array.isArray(navItems)) { + const fixedNavItems = navItems.map((item) => { + const fixedItem = { ...item }; + + if (fixedItem.href === '#courses') { + fixedItem.href = '/courses'; + changes.push(`navItem href #courses → /courses (label: "${fixedItem.label}")`); + } + + if (typeof fixedItem.label === 'string' && /programs/i.test(fixedItem.label)) { + const updated = replacePrograms(fixedItem.label); + changes.push(`navItem label "${fixedItem.label}" → "${updated}"`); + fixedItem.label = updated; + } + + return fixedItem; + }); + + fixed.navItems = fixedNavItems; + } + + if (changes.length === 0) continue; + + if (!dryRun) { + await db.update(organization).set({ landingpage: fixed }).where(eq(organization.id, row.id)); + } + + console.log(`${dryRun ? '[dry-run] Would update' : 'Updated'} org "${row.siteName}" (${row.id}):`); + for (const change of changes) { + console.log(` - ${change}`); + } + + updatedCount++; + } + + console.log( + `\n${dryRun ? 'Dry run complete' : 'Done'}. ${updatedCount} of ${rows.length} orgs ${dryRun ? 'would be' : ''} updated.` + ); + process.exit(0); + } catch (error) { + console.error('fix-landing-page-courses-links failed:', error); + process.exit(1); + } +} + +fixLandingPageCoursesLinks();