Parcourir la source

Moves & renames some sub methods for clarity

No functional changes at all
main
Eric Amodio il y a 1 an
Parent
révision
d85736a545
3 fichiers modifiés avec 201 ajouts et 187 suppressions
  1. +189
    -0
      src/plus/gk/subscription/checkin.ts
  2. +4
    -0
      src/plus/gk/subscription/subscription.ts
  3. +8
    -187
      src/plus/gk/subscription/subscriptionService.ts

+ 189
- 0
src/plus/gk/subscription/checkin.ts Voir le fichier

@ -0,0 +1,189 @@
import type { Subscription } from './subscription';
import { getSubscriptionPlan, getSubscriptionPlanPriority, SubscriptionPlanId } from './subscription';
export interface GKCheckInResponse {
readonly user: GKUser;
readonly licenses: {
readonly paidLicenses: Record<GKLicenseType, GKLicense>;
readonly effectiveLicenses: Record<GKLicenseType, GKLicense>;
};
readonly orgIds?: string[];
}
export interface GKUser {
readonly id: string;
readonly name: string;
readonly email: string;
readonly status: 'activated' | 'pending';
readonly createdDate: string;
readonly firstGitLensCheckIn?: string;
}
export interface GKLicense {
readonly latestStatus: 'active' | 'canceled' | 'cancelled' | 'expired' | 'in_trial' | 'non_renewing' | 'trial';
readonly latestStartDate: string;
readonly latestEndDate: string;
readonly organizationId: string | undefined;
readonly reactivationCount?: number;
}
export type GKLicenseType =
| 'gitlens-pro'
| 'gitlens-teams'
| 'gitlens-hosted-enterprise'
| 'gitlens-self-hosted-enterprise'
| 'gitlens-standalone-enterprise'
| 'bundle-pro'
| 'bundle-teams'
| 'bundle-hosted-enterprise'
| 'bundle-self-hosted-enterprise'
| 'bundle-standalone-enterprise'
| 'gitkraken_v1-pro'
| 'gitkraken_v1-teams'
| 'gitkraken_v1-hosted-enterprise'
| 'gitkraken_v1-self-hosted-enterprise'
| 'gitkraken_v1-standalone-enterprise';
export function getSubscriptionFromCheckIn(data: GKCheckInResponse): Partial<Subscription> {
const account: Subscription['account'] = {
id: data.user.id,
name: data.user.name,
email: data.user.email,
verified: data.user.status === 'activated',
createdOn: data.user.createdDate,
organizationIds: data.orgIds ?? [],
};
const effectiveLicenses = Object.entries(data.licenses.effectiveLicenses) as [GKLicenseType, GKLicense][];
const paidLicenses = Object.entries(data.licenses.paidLicenses) as [GKLicenseType, GKLicense][];
let actual: Subscription['plan']['actual'] | undefined;
if (paidLicenses.length > 0) {
if (paidLicenses.length > 1) {
paidLicenses.sort(
(a, b) =>
getSubscriptionPlanPriority(convertLicenseTypeToPlanId(b[0])) +
licenseStatusPriority(b[1].latestStatus) -
(getSubscriptionPlanPriority(convertLicenseTypeToPlanId(a[0])) +
licenseStatusPriority(a[1].latestStatus)),
);
}
const [licenseType, license] = paidLicenses[0];
actual = getSubscriptionPlan(
convertLicenseTypeToPlanId(licenseType),
isBundleLicenseType(licenseType),
license.reactivationCount ?? 0,
license.organizationId,
new Date(license.latestStartDate),
new Date(license.latestEndDate),
license.latestStatus === 'cancelled',
);
}
if (actual == null) {
actual = getSubscriptionPlan(
SubscriptionPlanId.FreePlus,
false,
0,
undefined,
data.user.firstGitLensCheckIn != null
? new Date(data.user.firstGitLensCheckIn)
: data.user.createdDate != null
? new Date(data.user.createdDate)
: undefined,
);
}
let effective: Subscription['plan']['effective'] | undefined;
if (effectiveLicenses.length > 0) {
if (effectiveLicenses.length > 1) {
effectiveLicenses.sort(
(a, b) =>
getSubscriptionPlanPriority(convertLicenseTypeToPlanId(b[0])) +
licenseStatusPriority(b[1].latestStatus) -
(getSubscriptionPlanPriority(convertLicenseTypeToPlanId(a[0])) +
licenseStatusPriority(a[1].latestStatus)),
);
}
const [licenseType, license] = effectiveLicenses[0];
effective = getSubscriptionPlan(
convertLicenseTypeToPlanId(licenseType),
isBundleLicenseType(licenseType),
license.reactivationCount ?? 0,
license.organizationId,
new Date(license.latestStartDate),
new Date(license.latestEndDate),
license.latestStatus === 'cancelled',
);
}
if (effective == null || getSubscriptionPlanPriority(actual.id) >= getSubscriptionPlanPriority(effective.id)) {
effective = { ...actual };
}
return {
plan: {
actual: actual,
effective: effective,
},
account: account,
};
}
function convertLicenseTypeToPlanId(licenseType: GKLicenseType): SubscriptionPlanId {
switch (licenseType) {
case 'gitlens-pro':
case 'bundle-pro':
case 'gitkraken_v1-pro':
return SubscriptionPlanId.Pro;
case 'gitlens-teams':
case 'bundle-teams':
case 'gitkraken_v1-teams':
return SubscriptionPlanId.Teams;
case 'gitlens-hosted-enterprise':
case 'gitlens-self-hosted-enterprise':
case 'gitlens-standalone-enterprise':
case 'bundle-hosted-enterprise':
case 'bundle-self-hosted-enterprise':
case 'bundle-standalone-enterprise':
case 'gitkraken_v1-hosted-enterprise':
case 'gitkraken_v1-self-hosted-enterprise':
case 'gitkraken_v1-standalone-enterprise':
return SubscriptionPlanId.Enterprise;
default:
return SubscriptionPlanId.FreePlus;
}
}
function isBundleLicenseType(licenseType: GKLicenseType): boolean {
switch (licenseType) {
case 'bundle-pro':
case 'bundle-teams':
case 'bundle-hosted-enterprise':
case 'bundle-self-hosted-enterprise':
case 'bundle-standalone-enterprise':
return true;
default:
return false;
}
}
function licenseStatusPriority(status: GKLicense['latestStatus']): number {
switch (status) {
case 'active':
return 100;
case 'expired':
case 'cancelled':
return -100;
case 'in_trial':
case 'trial':
return 1;
case 'canceled':
case 'non_renewing':
return 0;
default:
return -200;
}
}

+ 4
- 0
src/plus/gk/subscription/subscription.ts Voir le fichier

@ -251,3 +251,7 @@ export function hasAccountFromSubscriptionState(state: SubscriptionState | undef
state !== SubscriptionState.FreeInPreviewTrial
);
}
export function assertSubscriptionState(
subscription: Optional<Subscription, 'state'>,
): asserts subscription is Subscription {}

+ 8
- 187
src/plus/gk/subscription/subscriptionService.ts Voir le fichier

@ -42,12 +42,14 @@ import { satisfies } from '../../../system/version';
import { authenticationProviderId, authenticationProviderScopes } from '../authenticationProvider';
import type { ServerConnection } from '../serverConnection';
import { ensurePlusFeaturesEnabled } from '../utils';
import type { GKCheckInResponse } from './checkin';
import { getSubscriptionFromCheckIn } from './checkin';
import type { Subscription } from './subscription';
import {
assertSubscriptionState,
computeSubscriptionState,
getSubscriptionPlan,
getSubscriptionPlanName,
getSubscriptionPlanPriority,
getSubscriptionTimeRemaining,
getTimeRemaining,
isSubscriptionExpired,
@ -575,8 +577,8 @@ export class SubscriptionService implements Disposable {
throw new AccountValidationError('Unable to validate account', undefined, rsp.status, rsp.statusText);
}
const data: GKLicenseInfo = await rsp.json();
this.validateSubscription(data);
const data: GKCheckInResponse = await rsp.json();
this.validateAndUpdateSubscription(data);
} catch (ex) {
Logger.error(ex, scope);
debugger;
@ -605,94 +607,14 @@ export class SubscriptionService implements Disposable {
}
@debug()
private validateSubscription(data: GKLicenseInfo) {
const account: Subscription['account'] = {
id: data.user.id,
name: data.user.name,
email: data.user.email,
verified: data.user.status === 'activated',
createdOn: data.user.createdDate,
organizationIds: data.orgIds ?? [],
};
const effectiveLicenses = Object.entries(data.licenses.effectiveLicenses) as [GKLicenseType, GKLicense][];
const paidLicenses = Object.entries(data.licenses.paidLicenses) as [GKLicenseType, GKLicense][];
let actual: Subscription['plan']['actual'] | undefined;
if (paidLicenses.length > 0) {
if (paidLicenses.length > 1) {
paidLicenses.sort(
(a, b) =>
getSubscriptionPlanPriority(convertLicenseTypeToPlanId(b[0])) +
licenseStatusPriority(b[1].latestStatus) -
(getSubscriptionPlanPriority(convertLicenseTypeToPlanId(a[0])) +
licenseStatusPriority(a[1].latestStatus)),
);
}
const [licenseType, license] = paidLicenses[0];
actual = getSubscriptionPlan(
convertLicenseTypeToPlanId(licenseType),
isBundleLicenseType(licenseType),
license.reactivationCount ?? 0,
license.organizationId,
new Date(license.latestStartDate),
new Date(license.latestEndDate),
license.latestStatus === 'cancelled',
);
}
if (actual == null) {
actual = getSubscriptionPlan(
SubscriptionPlanId.FreePlus,
false,
0,
undefined,
data.user.firstGitLensCheckIn != null
? new Date(data.user.firstGitLensCheckIn)
: data.user.createdDate != null
? new Date(data.user.createdDate)
: undefined,
);
}
let effective: Subscription['plan']['effective'] | undefined;
if (effectiveLicenses.length > 0) {
if (effectiveLicenses.length > 1) {
effectiveLicenses.sort(
(a, b) =>
getSubscriptionPlanPriority(convertLicenseTypeToPlanId(b[0])) +
licenseStatusPriority(b[1].latestStatus) -
(getSubscriptionPlanPriority(convertLicenseTypeToPlanId(a[0])) +
licenseStatusPriority(a[1].latestStatus)),
);
}
const [licenseType, license] = effectiveLicenses[0];
effective = getSubscriptionPlan(
convertLicenseTypeToPlanId(licenseType),
isBundleLicenseType(licenseType),
license.reactivationCount ?? 0,
license.organizationId,
new Date(license.latestStartDate),
new Date(license.latestEndDate),
license.latestStatus === 'cancelled',
);
}
if (effective == null || getSubscriptionPlanPriority(actual.id) >= getSubscriptionPlanPriority(effective.id)) {
effective = { ...actual };
}
private validateAndUpdateSubscription(data: GKCheckInResponse) {
const subscription = getSubscriptionFromCheckIn(data);
this._lastValidatedDate = new Date();
this.changeSubscription(
{
...this._subscription,
plan: {
actual: actual,
effective: effective,
},
account: account,
...subscription,
},
{ store: true },
);
@ -1094,104 +1016,3 @@ function flattenSubscription(subscription: Optional | und
'subscription.state': subscription.state,
};
}
function assertSubscriptionState(subscription: Optional<Subscription, 'state'>): asserts subscription is Subscription {}
interface GKLicenseInfo {
readonly user: GKUser;
readonly licenses: {
readonly paidLicenses: Record<GKLicenseType, GKLicense>;
readonly effectiveLicenses: Record<GKLicenseType, GKLicense>;
};
readonly orgIds?: string[];
}
interface GKLicense {
readonly latestStatus: 'active' | 'canceled' | 'cancelled' | 'expired' | 'in_trial' | 'non_renewing' | 'trial';
readonly latestStartDate: string;
readonly latestEndDate: string;
readonly organizationId: string | undefined;
readonly reactivationCount?: number;
}
type GKLicenseType =
| 'gitlens-pro'
| 'gitlens-teams'
| 'gitlens-hosted-enterprise'
| 'gitlens-self-hosted-enterprise'
| 'gitlens-standalone-enterprise'
| 'bundle-pro'
| 'bundle-teams'
| 'bundle-hosted-enterprise'
| 'bundle-self-hosted-enterprise'
| 'bundle-standalone-enterprise'
| 'gitkraken_v1-pro'
| 'gitkraken_v1-teams'
| 'gitkraken_v1-hosted-enterprise'
| 'gitkraken_v1-self-hosted-enterprise'
| 'gitkraken_v1-standalone-enterprise';
interface GKUser {
readonly id: string;
readonly name: string;
readonly email: string;
readonly status: 'activated' | 'pending';
readonly createdDate: string;
readonly firstGitLensCheckIn?: string;
}
function convertLicenseTypeToPlanId(licenseType: GKLicenseType): SubscriptionPlanId {
switch (licenseType) {
case 'gitlens-pro':
case 'bundle-pro':
case 'gitkraken_v1-pro':
return SubscriptionPlanId.Pro;
case 'gitlens-teams':
case 'bundle-teams':
case 'gitkraken_v1-teams':
return SubscriptionPlanId.Teams;
case 'gitlens-hosted-enterprise':
case 'gitlens-self-hosted-enterprise':
case 'gitlens-standalone-enterprise':
case 'bundle-hosted-enterprise':
case 'bundle-self-hosted-enterprise':
case 'bundle-standalone-enterprise':
case 'gitkraken_v1-hosted-enterprise':
case 'gitkraken_v1-self-hosted-enterprise':
case 'gitkraken_v1-standalone-enterprise':
return SubscriptionPlanId.Enterprise;
default:
return SubscriptionPlanId.FreePlus;
}
}
function isBundleLicenseType(licenseType: GKLicenseType): boolean {
switch (licenseType) {
case 'bundle-pro':
case 'bundle-teams':
case 'bundle-hosted-enterprise':
case 'bundle-self-hosted-enterprise':
case 'bundle-standalone-enterprise':
return true;
default:
return false;
}
}
function licenseStatusPriority(status: GKLicense['latestStatus']): number {
switch (status) {
case 'active':
return 100;
case 'expired':
case 'cancelled':
return -100;
case 'in_trial':
case 'trial':
return 1;
case 'canceled':
case 'non_renewing':
return 0;
default:
return -200;
}
}

Chargement…
Annuler
Enregistrer