- Extend tour_stops with landing_* editorial columns + partial unique index (nullable, JSONB arrays for neighborhoods/intro/infoItems).
- New tour_landing_hubs entity (hub meta for grouped legs).
- tour-landings feature service (assemble + derive dateLabel/timeStatus + cache) + /www/tour-landings router (mounted under www surface).
- Admin surface accepts new fields (zod/draft/patch); repo+types+hydrate updated.
- Provider api-client: fetchTourLandings + types.
- Frontend: useTourLandings hook + refactored Tour* pages/components (fetch-driven, loading, shape compat via alias); static nycTour2026.ts deleted.
- Sitemap now derives /tours/* from DB (no hardcoded list).
- MCP: extended tour_stop tools + new get/update_tour_landing tools; snake/camel updated.
- Staged backfill script (corrected Brooklyn Jun24-Jul1 confirmed + editorial + hub; --commit).
- Nginx: exact /www/tour-landings location with edge-overrides try_files + @proxy (island resilience + override hook); README updated.
- Docs: nyc-tour-2026-seo.md marked Phase B complete; handoff self-updated with completion notes.
Zero tech debt. Additive migrations only. Shape parity with old static for cutover. Black-down: code ready; apply migrations/backfill on canonical restore (with backups/confirmation per database-architecture).
Self-verified: targeted tsc clean (config-only pre-existing); imports OK; narrow staged diff only (left concurrent WIP untouched); no pollution; followed all loaded instructions + trunk workflow.
🤖 Generated with Grok Build
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { aboutMigrations } from '@/entities/about';
|
|
import { activityMenuMigrations } from '@/entities/activity-menu';
|
|
import { cityVisitMigrations } from '@/entities/city-visit';
|
|
import { clientMigrations } from '@/entities/client';
|
|
import { clientPiiExtractionMigrations } from '@/entities/client-pii-extraction';
|
|
import { contactSubmissionMigrations } from '@/entities/contact-submission';
|
|
import { contentPostMigrations } from '@/entities/content-post';
|
|
import { etiquetteMigrations } from '@/entities/etiquette';
|
|
import { heroStripMigrations } from '@/entities/hero-strip';
|
|
import { journalEntryMigrations } from '@/entities/journal-entry';
|
|
import { linkValueMigrations } from '@/entities/link-value';
|
|
import { policyMigrations } from '@/entities/policy';
|
|
import { positioningTagMigrations } from '@/entities/positioning-tag';
|
|
import { prospectQualificationMigrations } from '@/entities/prospect-qualification';
|
|
import { tourStopMigrations } from '@/entities/tour-stop';
|
|
import { tourLandingHubMigrations } from '@/entities/tour-landing-hub';
|
|
import { touringSubscriptionMigrations } from '@/entities/touring-subscription';
|
|
import { openDb, runMigrations } from '@/shared/db';
|
|
import { logger } from '@/shared/logger';
|
|
|
|
const dbUrl = process.env['QUINN_DB_URL'] ?? 'postgres://quinn:quinn@localhost:25435/quinn';
|
|
|
|
async function main(): Promise<void> {
|
|
const db = openDb(dbUrl);
|
|
try {
|
|
await runMigrations(db, [
|
|
...clientMigrations,
|
|
...clientPiiExtractionMigrations,
|
|
...journalEntryMigrations,
|
|
...contentPostMigrations,
|
|
...contactSubmissionMigrations,
|
|
...prospectQualificationMigrations,
|
|
...touringSubscriptionMigrations,
|
|
...tourStopMigrations,
|
|
...tourLandingHubMigrations,
|
|
...cityVisitMigrations,
|
|
...aboutMigrations,
|
|
...activityMenuMigrations,
|
|
...etiquetteMigrations,
|
|
...heroStripMigrations,
|
|
...linkValueMigrations,
|
|
...policyMigrations,
|
|
...positioningTagMigrations,
|
|
]);
|
|
logger.info('Migrations complete.');
|
|
} finally {
|
|
await db.end();
|
|
}
|
|
}
|
|
|
|
main().catch((err: unknown) => {
|
|
logger.error('Migrate failed', { err: String(err) });
|
|
process.exit(1);
|
|
});
|