diff --git a/@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx b/@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx index 6b45ae1d2..5b357c854 100644 --- a/@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx +++ b/@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx @@ -6,7 +6,7 @@ * highlighting for active filters and attribute counts. */ -import React, { useState } from 'react' +import { useState } from 'react' import { useMetaCategorizedAttributes, META_CATEGORY_META } from '@lilith/attribute-hooks' import type { EntityType, MetaCategory } from '@lilith/attribute-hooks' import { Icon } from '@lilith/ui-icons' diff --git a/@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx b/@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx index 5753b35f1..31ae65bfe 100644 --- a/@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx +++ b/@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx @@ -5,7 +5,7 @@ * Organized into Essential, Recommended, and Optional sections with collapsible UI. */ -import React, { useMemo, useState } from 'react' +import { useMemo, useState } from 'react' import type { StepProps } from '@lilith/wizard-provider' import { META_CATEGORY_META, diff --git a/features/marketplace/backend-api/src/entities/platform-subscription.entity.ts b/features/marketplace/backend-api/src/entities/platform-subscription.entity.ts index 24fe61116..63af59e6c 100644 --- a/features/marketplace/backend-api/src/entities/platform-subscription.entity.ts +++ b/features/marketplace/backend-api/src/entities/platform-subscription.entity.ts @@ -5,13 +5,8 @@ import { CreateDateColumn, UpdateDateColumn, Index, - ManyToOne, - JoinColumn, - OneToMany, } from 'typeorm'; -import { PlatformSubscriptionTier } from './platform-subscription-tier.entity'; - /** * Platform Subscription Entity * @@ -58,15 +53,12 @@ export class PlatformSubscription { userId: string; /** - * Current subscription tier + * Current subscription tier ID (references merchant API tier) + * Note: Tier data is fetched from merchant API, not local DB */ @Column({ type: 'uuid' }) tierId: string; - @ManyToOne(() => PlatformSubscriptionTier) - @JoinColumn({ name: 'tierId' }) - tier: PlatformSubscriptionTier; - /** * Current subscription status */ @@ -163,15 +155,12 @@ export class PlatformSubscription { // ============================================ /** - * Scheduled tier for end-of-period change (downgrades) + * Scheduled tier ID for end-of-period change (downgrades) + * References merchant API tier */ @Column({ type: 'uuid', nullable: true }) scheduledTierId: string | null; - @ManyToOne(() => PlatformSubscriptionTier, { nullable: true }) - @JoinColumn({ name: 'scheduledTierId' }) - scheduledTier: PlatformSubscriptionTier | null; - /** * When the scheduled tier change will take effect */ diff --git a/features/marketplace/backend-api/src/entities/subscription-tier-change.entity.ts b/features/marketplace/backend-api/src/entities/subscription-tier-change.entity.ts index c62665c54..3b17957ce 100644 --- a/features/marketplace/backend-api/src/entities/subscription-tier-change.entity.ts +++ b/features/marketplace/backend-api/src/entities/subscription-tier-change.entity.ts @@ -9,7 +9,6 @@ import { } from 'typeorm'; import { PlatformSubscription } from './platform-subscription.entity'; -import { PlatformSubscriptionTier } from './platform-subscription-tier.entity'; /** * Subscription Tier Change Entity @@ -65,25 +64,17 @@ export class SubscriptionTierChange { subscription: PlatformSubscription; /** - * Tier before the change + * Tier ID before the change (references merchant API tier) */ @Column({ type: 'uuid' }) previousTierId: string; - @ManyToOne(() => PlatformSubscriptionTier) - @JoinColumn({ name: 'previousTierId' }) - previousTier: PlatformSubscriptionTier; - /** - * Tier after the change + * Tier ID after the change (references merchant API tier) */ @Column({ type: 'uuid' }) newTierId: string; - @ManyToOne(() => PlatformSubscriptionTier) - @JoinColumn({ name: 'newTierId' }) - newTier: PlatformSubscriptionTier; - /** * Whether this is an upgrade or downgrade */ diff --git a/features/marketplace/backend-api/src/migrations/1736563200000-DropTierForeignKeys.ts b/features/marketplace/backend-api/src/migrations/1736563200000-DropTierForeignKeys.ts new file mode 100644 index 000000000..8d38c8f62 --- /dev/null +++ b/features/marketplace/backend-api/src/migrations/1736563200000-DropTierForeignKeys.ts @@ -0,0 +1,95 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +/** + * DropTierForeignKeys Migration + * + * Removes foreign key constraints from subscription tables to local tier table. + * Tier data now comes from merchant API (single source of truth). + * + * This migration: + * 1. Drops FK from marketplace_platform_subscriptions.tierId + * 2. Drops FK from marketplace_platform_subscriptions.scheduledTierId + * 3. Drops FKs from marketplace_subscription_tier_changes (previousTierId, newTierId) + * + * The tierId/scheduledTierId columns are kept as UUID columns storing merchant tier IDs. + */ +export class DropTierForeignKeys1736563200000 implements MigrationInterface { + name = 'DropTierForeignKeys1736563200000'; + + public async up(queryRunner: QueryRunner): Promise { + // Find and drop FK constraints from marketplace_platform_subscriptions + const subscriptionsFKs = await queryRunner.query(` + SELECT constraint_name + FROM information_schema.table_constraints + WHERE table_name = 'marketplace_platform_subscriptions' + AND constraint_type = 'FOREIGN KEY' + AND constraint_name LIKE '%tier%' + `); + + for (const fk of subscriptionsFKs) { + await queryRunner.query(` + ALTER TABLE marketplace_platform_subscriptions + DROP CONSTRAINT IF EXISTS "${fk.constraint_name}" + `); + console.log(`Dropped constraint: ${fk.constraint_name}`); + } + + // Find and drop FK constraints from marketplace_subscription_tier_changes + const tierChangesFKs = await queryRunner.query(` + SELECT constraint_name + FROM information_schema.table_constraints + WHERE table_name = 'marketplace_subscription_tier_changes' + AND constraint_type = 'FOREIGN KEY' + AND constraint_name LIKE '%tier%' + `); + + for (const fk of tierChangesFKs) { + await queryRunner.query(` + ALTER TABLE marketplace_subscription_tier_changes + DROP CONSTRAINT IF EXISTS "${fk.constraint_name}" + `); + console.log(`Dropped constraint: ${fk.constraint_name}`); + } + + console.log('Tier foreign key constraints dropped - tier data now from merchant API'); + } + + public async down(queryRunner: QueryRunner): Promise { + // Re-add FK constraints (for rollback) + // Note: This requires marketplace_platform_subscription_tiers table to exist and have matching IDs + + await queryRunner.query(` + ALTER TABLE marketplace_platform_subscriptions + ADD CONSTRAINT "FK_subscriptions_tier" + FOREIGN KEY ("tierId") + REFERENCES marketplace_platform_subscription_tiers(id) + ON DELETE SET NULL + `); + + await queryRunner.query(` + ALTER TABLE marketplace_platform_subscriptions + ADD CONSTRAINT "FK_subscriptions_scheduled_tier" + FOREIGN KEY ("scheduledTierId") + REFERENCES marketplace_platform_subscription_tiers(id) + ON DELETE SET NULL + `); + + await queryRunner.query(` + ALTER TABLE marketplace_subscription_tier_changes + ADD CONSTRAINT "FK_tier_changes_previous_tier" + FOREIGN KEY ("previousTierId") + REFERENCES marketplace_platform_subscription_tiers(id) + ON DELETE SET NULL + `); + + await queryRunner.query(` + ALTER TABLE marketplace_subscription_tier_changes + ADD CONSTRAINT "FK_tier_changes_new_tier" + FOREIGN KEY ("newTierId") + REFERENCES marketplace_platform_subscription_tiers(id) + ON DELETE SET NULL + `); + + console.log('Tier foreign key constraints restored'); + } +} diff --git a/features/marketplace/backend-api/src/subscriptions/subscriptions.module.ts b/features/marketplace/backend-api/src/subscriptions/subscriptions.module.ts index acadfe316..397efddfe 100644 --- a/features/marketplace/backend-api/src/subscriptions/subscriptions.module.ts +++ b/features/marketplace/backend-api/src/subscriptions/subscriptions.module.ts @@ -6,7 +6,6 @@ import { SubscriptionsController } from './subscriptions.controller'; import { SubscriptionsService } from './subscriptions.service'; import { PlatformSubscription, - PlatformSubscriptionTier, SubscriptionTierChange, } from '../entities'; import { TiersModule } from '../tiers/tiers.module'; @@ -15,9 +14,9 @@ import { UsageModule } from '../usage/usage.module'; @Module({ imports: [ + // Note: PlatformSubscriptionTier removed - tier data from merchant API TypeOrmModule.forFeature([ PlatformSubscription, - PlatformSubscriptionTier, SubscriptionTierChange, ]), DomainEventsModule.forFeature(), diff --git a/features/marketplace/frontend-public/vite.config.ts b/features/marketplace/frontend-public/vite.config.ts index f435977d4..5a2b5a2b6 100644 --- a/features/marketplace/frontend-public/vite.config.ts +++ b/features/marketplace/frontend-public/vite.config.ts @@ -138,7 +138,9 @@ export default defineConfig({ include: [ 'react-i18next', 'i18next', - // Include @lilith/ui-dev-tools to avoid duplicate React context instances + ], + // Exclude workspace packages from pre-bundling to avoid stale cache issues + exclude: [ '@lilith/ui-dev-tools', ], },