* refactor: replace FeaturesRepository with DI-based feature repositories Migrate from the legacy FeaturesRepository pattern to separate DI-based repositories: - Add checkIfFeatureIsEnabledGlobally to IFeatureRepository - Add getTeamsWithFeatureEnabled to ITeamFeatureRepository - Update CalendarSubscriptionService to use featureRepository, teamFeatureRepository, and userFeatureRepository - Update SelectedCalendarRepository.findNextSubscriptionBatch to filter by teamIds instead of featureIds - Update OnboardingPathService to use DI via getFeatureRepository() - Remove prisma parameter from OnboardingPathService callsites Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: update tests to use new DI-based feature repositories Update CalendarSubscriptionService and SelectedCalendarRepository tests to use the new separate repository interfaces: - featureRepository for global feature checks - teamFeatureRepository for team-level feature checks - userFeatureRepository for user-level feature checks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: update API routes to use DI-based feature repositories Update cron and webhook routes to use the new separate repository interfaces instead of the combined FeaturesRepository. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove prisma arg from getGettingStartedPathWithParams call The OnboardingPathService method no longer requires a prisma argument as it now uses DI containers internally. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: update route tests to expect new DI-based feature repositories Update service instantiation tests to expect featureRepository, teamFeatureRepository, and userFeatureRepository instead of the old featuresRepository. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: optimize global feature check and add guard in checkForNewSubscriptions - Use targeted select for only `enabled` field in checkIfFeatureIsEnabledGlobally - Add global feature flag guard in checkForNewSubscriptions to avoid unnecessary DB queries and API calls when the cache feature is globally disabled Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * remove redundant comment --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import type { FeatureId } from "@calcom/features/flags/config";
|
|
import type { FeatureDto } from "@calcom/lib/dto/FeatureDto";
|
|
import type { PrismaClient } from "@calcom/prisma/client";
|
|
|
|
export interface IFeatureRepository {
|
|
findAll(): Promise<FeatureDto[]>;
|
|
findBySlug(slug: string): Promise<FeatureDto | null>;
|
|
update(input: { featureId: FeatureId; enabled: boolean; updatedBy?: number }): Promise<FeatureDto>;
|
|
checkIfFeatureIsEnabledGlobally(slug: string): Promise<boolean>;
|
|
}
|
|
|
|
export class PrismaFeatureRepository implements IFeatureRepository {
|
|
private prisma: PrismaClient;
|
|
|
|
constructor(prisma: PrismaClient) {
|
|
this.prisma = prisma;
|
|
}
|
|
|
|
async findAll(): Promise<FeatureDto[]> {
|
|
return this.prisma.feature.findMany({
|
|
orderBy: { slug: "asc" },
|
|
select: {
|
|
slug: true,
|
|
enabled: true,
|
|
description: true,
|
|
type: true,
|
|
stale: true,
|
|
lastUsedAt: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
updatedBy: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
async findBySlug(slug: string): Promise<FeatureDto | null> {
|
|
return this.prisma.feature.findUnique({
|
|
where: { slug },
|
|
select: {
|
|
slug: true,
|
|
enabled: true,
|
|
description: true,
|
|
type: true,
|
|
stale: true,
|
|
lastUsedAt: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
updatedBy: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
async update(input: { featureId: FeatureId; enabled: boolean; updatedBy?: number }): Promise<FeatureDto> {
|
|
const { featureId, enabled, updatedBy } = input;
|
|
return this.prisma.feature.update({
|
|
where: { slug: featureId },
|
|
data: { enabled, updatedBy, updatedAt: new Date() },
|
|
select: {
|
|
slug: true,
|
|
enabled: true,
|
|
description: true,
|
|
type: true,
|
|
stale: true,
|
|
lastUsedAt: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
updatedBy: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
async checkIfFeatureIsEnabledGlobally(slug: string): Promise<boolean> {
|
|
const feature = await this.prisma.feature.findUnique({
|
|
where: { slug },
|
|
select: { enabled: true },
|
|
});
|
|
return Boolean(feature?.enabled);
|
|
}
|
|
}
|