diff --git a/packages/bsync/src/purchases/purchasesClient.ts b/packages/bsync/src/purchases/purchasesClient.ts index 47c19d6f73f..5bdf6e9baa7 100644 --- a/packages/bsync/src/purchases/purchasesClient.ts +++ b/packages/bsync/src/purchases/purchasesClient.ts @@ -7,7 +7,7 @@ type SubscriptionGroupId = 'core' type SubscriptionOfferingId = 'core:monthly' | 'core:annual' -const assertSubscriptionGroup: ( +export const assertSubscriptionGroup: ( group: string, ) => asserts group is SubscriptionGroupId = (group: string) => { if (['core'].includes(group)) { @@ -16,9 +16,9 @@ const assertSubscriptionGroup: ( throw new Error(`invalid subscription group: '${group}'`) } -const assertPlatform: (platform: string) => asserts platform is PlatformId = ( +export const assertPlatform: ( platform: string, -) => { +) => asserts platform is PlatformId = (platform: string) => { if (['web', 'ios', 'android'].includes(platform)) { return } @@ -128,10 +128,11 @@ export class PurchasesClient { return this.revenueCatClient.isWebhookAuthorizationValid(authorization) } - getSubscriptionGroup(group: string, platform: string) { - assertSubscriptionGroup(group) - assertPlatform(platform) - return this.GROUPS[group][platform] + getSubscriptionGroup( + subscriptionGroupId: SubscriptionGroupId, + platformId: PlatformId, + ) { + return this.GROUPS[subscriptionGroupId][platformId] } async getEntitlements(did: string): Promise { @@ -187,10 +188,10 @@ export class PurchasesClient { let status = 'unknown' if (s.auto_resume_date) { - if (now > expiresAt) { + if (now >= expiresAt) { status = 'paused' } - } else if (now > expiresAt) { + } else if (now >= expiresAt) { status = 'expired' } else if (now < expiresAt) { status = 'active' @@ -200,7 +201,7 @@ export class PurchasesClient { if (s.auto_resume_date) { if (now < expiresAt) { renewalStatus = 'will_pause' - } else if (now > expiresAt) { + } else if (now >= expiresAt) { renewalStatus = 'will_renew' } } else if (now < expiresAt) { @@ -208,13 +209,13 @@ export class PurchasesClient { if (s.unsubscribe_detected_at) { renewalStatus = 'will_not_renew' } - } else if (now > expiresAt) { + } else if (now >= expiresAt) { renewalStatus = 'will_not_renew' } let periodEndsAt = s.expires_date if (s.auto_resume_date) { - if (now > expiresAt) { + if (now >= expiresAt) { periodEndsAt = s.auto_resume_date } } diff --git a/packages/bsync/src/routes/get-subscription-group.ts b/packages/bsync/src/routes/get-subscription-group.ts index 379909bb3e9..872219aa039 100644 --- a/packages/bsync/src/routes/get-subscription-group.ts +++ b/packages/bsync/src/routes/get-subscription-group.ts @@ -3,6 +3,7 @@ import { Service } from '../proto/bsync_connect' import { GetSubscriptionGroupResponse } from '../proto/bsync_pb' import AppContext from '../context' import { authWithApiKey } from './auth' +import { assertPlatform, assertSubscriptionGroup } from '../purchases' export default (ctx: AppContext): Partial> => ({ async getSubscriptionGroup(req, handlerCtx) { @@ -18,13 +19,16 @@ export default (ctx: AppContext): Partial> => ({ const { group, platform } = req try { - const offerings = purchasesClient.getSubscriptionGroup(group, platform) - - return new GetSubscriptionGroupResponse({ - offerings, - }) + assertSubscriptionGroup(group) + assertPlatform(platform) } catch (error) { throw new ConnectError((error as Error).message, Code.InvalidArgument) } + + const offerings = purchasesClient.getSubscriptionGroup(group, platform) + + return new GetSubscriptionGroupResponse({ + offerings, + }) }, }) diff --git a/packages/bsync/tests/purchases.test.ts b/packages/bsync/tests/purchases.test.ts index 0b48e8375e9..7716ec07d83 100644 --- a/packages/bsync/tests/purchases.test.ts +++ b/packages/bsync/tests/purchases.test.ts @@ -1,6 +1,12 @@ -import http from 'node:http' import { once } from 'node:events' +import http from 'node:http' + +import { Timestamp } from '@bufbuild/protobuf' +import { Code, ConnectError } from '@connectrpc/connect' import getPort from 'get-port' + +import { DAY, wait } from '@atproto/common' + import { authWithApiKey, BsyncClient, @@ -9,18 +15,15 @@ import { Database, envToCfg, } from '../src' +import { + GetSubscriptionsResponse, + PurchaseOperation, +} from '../src/proto/bsync_pb' import { RcEntitlement, RcEventBody, RcGetSubscriberResponse, } from '../src/purchases' -import { Code, ConnectError } from '@connectrpc/connect' -import { - GetSubscriptionsResponse, - PurchaseOperation, -} from '../src/proto/bsync_pb' -import { Timestamp } from '@bufbuild/protobuf' -import { DAY, wait } from '@atproto/common' const revenueCatWebhookAuthorization = 'Bearer any-token'