11 } from '@proton/payments';
13 import type { Addon, SubscriptionModel } from '../interfaces';
15 type AddonOrName = Addon | ADDON_NAMES | PLANS;
17 function isAddonType(addonOrName: AddonOrName, addonPrefix: string): boolean {
18 let addonName: ADDON_NAMES | PLANS;
19 if (typeof addonOrName === 'string') {
20 addonName = addonOrName;
22 addonName = addonOrName.Name;
25 return addonName.startsWith(addonPrefix);
28 export const isScribeAddon: AddonGuard = (addonOrName): boolean => {
29 return isAddonType(addonOrName, SCRIBE_ADDON_PREFIX);
32 export function hasScribeAddon(subscriptionOrPlanIds: SubscriptionModel | FreeSubscription | undefined): boolean {
33 const subscription = subscriptionOrPlanIds;
35 if (!subscription || isFreeSubscription(subscription)) {
39 const plans = subscription.Plans;
40 return plans.some((plan) => isScribeAddon(plan.Name));
43 export type AddonGuard = (addonOrName: AddonOrName) => boolean;
45 const ORG_SIZE_ADDONS = [
46 ADDON_NAMES.MEMBER_VPN_BUSINESS,
47 ADDON_NAMES.MEMBER_VPN_PRO,
48 ADDON_NAMES.MEMBER_PASS_BUSINESS,
49 ADDON_NAMES.MEMBER_PASS_PRO,
52 const DRIVE_ORG_SIZE_ADDONS = [ADDON_NAMES.MEMBER_DRIVE_PRO, ADDON_NAMES.MEMBER_DRIVE_BUSINESS];
54 export const isDriveOrgSizeAddon: AddonGuard = (addonOrName): boolean => {
55 return DRIVE_ORG_SIZE_ADDONS.some((name) => addonOrName === name);
58 export const isOrgSizeAddon: AddonGuard = (addonOrName): boolean => {
59 return ORG_SIZE_ADDONS.some((name) => addonOrName === name);
62 export const isMemberAddon: AddonGuard = (addonOrName): boolean => {
63 return isAddonType(addonOrName, MEMBER_ADDON_PREFIX);
66 export const isDomainAddon: AddonGuard = (addonOrName): boolean => {
67 return isAddonType(addonOrName, DOMAIN_ADDON_PREFIX);
70 export const isIpAddon: AddonGuard = (addonOrName): boolean => {
71 return isAddonType(addonOrName, IP_ADDON_PREFIX);
74 export const removeAddon = (originalPlanIDs: PlanIDs, addonGuard: AddonGuard): PlanIDs => {
75 const planIDs: PlanIDs = { ...originalPlanIDs };
77 // if guard returns true, it means that the addon should be removed
78 for (const addonName of Object.keys(planIDs) as (ADDON_NAMES | PLANS)[]) {
79 if (addonGuard(addonName)) {
80 delete planIDs[addonName];
87 export const countAddonsByType = (planIDs: PlanIDs, addonGuard: AddonGuard): number => {
88 return Object.keys(planIDs).reduce((acc, key) => {
89 const addonName = key as ADDON_NAMES | PLANS;
91 if (addonGuard(addonName)) {
92 return acc + (planIDs[addonName] ?? 0);
115 export type SupportedAddons = Partial<Record<ADDON_NAMES, boolean>>;
117 export function getSupportedB2CAddons(planIDs: PlanIDs): SupportedAddons {
118 const supported: SupportedAddons = {};
120 // Re-enable the scribe addons when/if B2C plans trully support them
123 // supported[ADDON_NAMES.MEMBER_SCRIBE_MAILPLUS] = true;
126 if (planIDs[DRIVE]) {
127 // supported[ADDON_NAMES.MEMBER_SCRIBE_DRIVEPLUS] = true;
130 if (planIDs[BUNDLE]) {
131 // supported[ADDON_NAMES.MEMBER_SCRIBE_BUNDLE] = true;
137 export function getSupportedB2BAddons(planIDs: PlanIDs): SupportedAddons {
138 const supported: SupportedAddons = {};
140 if (planIDs[MAIL_PRO]) {
141 supported[ADDON_NAMES.MEMBER_MAIL_PRO] = true;
142 supported[ADDON_NAMES.MEMBER_SCRIBE_MAIL_PRO] = true;
145 if (planIDs[MAIL_BUSINESS]) {
146 supported[ADDON_NAMES.MEMBER_MAIL_BUSINESS] = true;
147 supported[ADDON_NAMES.MEMBER_SCRIBE_MAIL_BUSINESS] = true;
150 if (planIDs[DRIVE_PRO]) {
151 supported[ADDON_NAMES.MEMBER_DRIVE_PRO] = true;
154 if (planIDs[DRIVE_BUSINESS]) {
155 supported[ADDON_NAMES.MEMBER_DRIVE_BUSINESS] = true;
158 if (planIDs[BUNDLE_PRO]) {
159 supported[ADDON_NAMES.MEMBER_BUNDLE_PRO] = true;
160 supported[ADDON_NAMES.DOMAIN_BUNDLE_PRO] = true;
161 supported[ADDON_NAMES.IP_BUNDLE_PRO] = true;
162 supported[ADDON_NAMES.MEMBER_SCRIBE_BUNDLE_PRO] = true;
165 if (planIDs[BUNDLE_PRO_2024]) {
166 supported[ADDON_NAMES.MEMBER_BUNDLE_PRO_2024] = true;
167 supported[ADDON_NAMES.DOMAIN_BUNDLE_PRO_2024] = true;
168 supported[ADDON_NAMES.IP_BUNDLE_PRO_2024] = true;
169 supported[ADDON_NAMES.MEMBER_SCRIBE_BUNDLE_PRO_2024] = true;
172 if (planIDs[ENTERPRISE]) {
173 supported[ADDON_NAMES.MEMBER_ENTERPRISE] = true;
174 supported[ADDON_NAMES.DOMAIN_ENTERPRISE] = true;
177 if (planIDs[VPN_PRO]) {
178 supported[ADDON_NAMES.MEMBER_VPN_PRO] = true;
181 if (planIDs[VPN_BUSINESS]) {
182 supported[ADDON_NAMES.MEMBER_VPN_BUSINESS] = true;
183 supported[ADDON_NAMES.IP_VPN_BUSINESS] = true;
186 if (planIDs[PASS_PRO]) {
187 supported[ADDON_NAMES.MEMBER_PASS_PRO] = true;
190 if (planIDs[PASS_BUSINESS]) {
191 supported[ADDON_NAMES.MEMBER_PASS_BUSINESS] = true;
197 export const getSupportedAddons = (planIDs: PlanIDs): SupportedAddons => {
198 const supported: SupportedAddons = {
199 ...getSupportedB2CAddons(planIDs),
200 ...getSupportedB2BAddons(planIDs),