-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1b19260
commit 438d9de
Showing
6 changed files
with
466 additions
and
456 deletions.
There are no files selected for viewing
176 changes: 89 additions & 87 deletions
176
packages/adapter-utils/src/entitlement/entitlement.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,106 @@ | ||
import { describe, it, expect, vi } from "vitest"; | ||
import { Entitlement } from "./entitlement"; | ||
import type { | ||
Benefit, | ||
WebhookBenefitGrantCreatedPayload, | ||
WebhookBenefitGrantRevokedPayload, | ||
Benefit, | ||
WebhookBenefitGrantCreatedPayload, | ||
WebhookBenefitGrantRevokedPayload, | ||
} from "@polar-sh/sdk/models/components"; | ||
import { EntitlementStrategy } from "./entitlement"; | ||
|
||
describe("Entitlement", () => { | ||
it("should run grant on handler", () => { | ||
const onGrant = vi.fn(); | ||
const onRevoke = vi.fn(); | ||
describe("EntitlementStrategy", () => { | ||
it("should run grant on handler", () => { | ||
const onGrant = vi.fn(); | ||
const onRevoke = vi.fn(); | ||
|
||
const entitlement = Entitlement<{ test: string }>().grant(onGrant); | ||
const entitlement = new EntitlementStrategy<{ test: string }>().grant( | ||
onGrant, | ||
); | ||
|
||
expect(entitlement).toBeDefined(); | ||
expect(entitlement).toBeDefined(); | ||
|
||
const payload = { | ||
type: "benefit_grant.created", | ||
data: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
isGranted: true, | ||
benefitId: "123", | ||
customerId: "123", | ||
subscriptionId: "123", | ||
orderId: "123", | ||
userId: "123", | ||
isRevoked: false, | ||
properties: { test: "test" }, | ||
customer: { | ||
email: "[email protected]", | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
metadata: {}, | ||
emailVerified: true, | ||
billingAddress: { | ||
line1: "123", | ||
line2: "123", | ||
city: "123", | ||
state: "123", | ||
postalCode: "123", | ||
country: "123", | ||
}, | ||
name: "Test", | ||
taxId: ["123"], | ||
organizationId: "123", | ||
avatarUrl: "123", | ||
}, | ||
benefit: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
description: "Test", | ||
selectable: true, | ||
slug: "test", | ||
} as unknown as Benefit, | ||
}, | ||
} as WebhookBenefitGrantCreatedPayload; | ||
const payload = { | ||
type: "benefit_grant.created", | ||
data: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
isGranted: true, | ||
benefitId: "123", | ||
customerId: "123", | ||
subscriptionId: "123", | ||
orderId: "123", | ||
userId: "123", | ||
isRevoked: false, | ||
properties: { test: "test" }, | ||
customer: { | ||
email: "[email protected]", | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
metadata: {}, | ||
emailVerified: true, | ||
billingAddress: { | ||
line1: "123", | ||
line2: "123", | ||
city: "123", | ||
state: "123", | ||
postalCode: "123", | ||
country: "123", | ||
}, | ||
name: "Test", | ||
taxId: ["123"], | ||
organizationId: "123", | ||
avatarUrl: "123", | ||
}, | ||
benefit: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
selectable: true, | ||
description: "test", | ||
} as unknown as Benefit, | ||
}, | ||
} as WebhookBenefitGrantCreatedPayload; | ||
|
||
entitlement.handler("test")(payload); | ||
entitlement.handler("test")(payload); | ||
|
||
expect(onGrant).toHaveBeenCalledWith({ | ||
payload, | ||
customer: payload.data.customer, | ||
properties: payload.data.properties, | ||
}); | ||
expect(onGrant).toHaveBeenCalledWith({ | ||
payload, | ||
customer: payload.data.customer, | ||
properties: payload.data.properties, | ||
}); | ||
|
||
expect(onRevoke).not.toHaveBeenCalled(); | ||
}); | ||
expect(onRevoke).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it("should run revoke on handler", () => { | ||
const onGrant = vi.fn(); | ||
const onRevoke = vi.fn(); | ||
it("should run revoke on handler", () => { | ||
const onGrant = vi.fn(); | ||
const onRevoke = vi.fn(); | ||
|
||
const entitlement = Entitlement<{ test: string }>() | ||
.grant(onGrant) | ||
.revoke(onRevoke); | ||
const entitlement = new EntitlementStrategy<{ test: string }>() | ||
.grant(onGrant) | ||
.revoke(onRevoke); | ||
|
||
const payload = { | ||
type: "benefit_grant.revoked", | ||
data: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
isGranted: false, | ||
benefitId: "123", | ||
customerId: "123", | ||
}, | ||
} as WebhookBenefitGrantRevokedPayload; | ||
const payload = { | ||
type: "benefit_grant.revoked", | ||
data: { | ||
id: "123", | ||
createdAt: new Date(), | ||
modifiedAt: new Date(), | ||
isGranted: false, | ||
benefitId: "123", | ||
customerId: "123", | ||
benefit: { description: "test" }, | ||
}, | ||
} as WebhookBenefitGrantRevokedPayload; | ||
|
||
entitlement.handler("test")(payload); | ||
entitlement.handler("test")(payload); | ||
|
||
expect(onGrant).not.toHaveBeenCalled(); | ||
expect(onGrant).not.toHaveBeenCalled(); | ||
|
||
expect(onRevoke).toHaveBeenCalledWith({ | ||
payload, | ||
customer: payload.data.customer, | ||
properties: payload.data.properties, | ||
}); | ||
}); | ||
expect(onRevoke).toHaveBeenCalledWith({ | ||
payload, | ||
customer: payload.data.customer, | ||
properties: payload.data.properties, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,89 @@ | ||
import type { | ||
Customer, | ||
WebhookBenefitGrantCreatedPayload, | ||
WebhookBenefitGrantRevokedPayload, | ||
Customer, | ||
WebhookBenefitGrantCreatedPayload, | ||
WebhookBenefitGrantRevokedPayload, | ||
} from "@polar-sh/sdk/models/components"; | ||
|
||
export type EntitlementProperties = Record<string, string>; | ||
|
||
export type EntitlementHandler = ( | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload, | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload, | ||
) => Promise<void>; | ||
|
||
export interface EntitlementContext<T extends EntitlementProperties> { | ||
customer: Customer; | ||
properties: T; | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload; | ||
customer: Customer; | ||
properties: T; | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload; | ||
} | ||
|
||
export class EntitlementStrategy<T extends EntitlementProperties> { | ||
private grantCallbacks: (( | ||
context: EntitlementContext<T>, | ||
) => Promise<void>)[] = []; | ||
private revokeCallbacks: (( | ||
context: EntitlementContext<T>, | ||
) => Promise<void>)[] = []; | ||
private grantCallbacks: (( | ||
context: EntitlementContext<T>, | ||
) => Promise<void>)[] = []; | ||
|
||
public grant(callback: (context: EntitlementContext<T>) => Promise<void>) { | ||
this.grantCallbacks.push(callback); | ||
return this; | ||
} | ||
private revokeCallbacks: (( | ||
context: EntitlementContext<T>, | ||
) => Promise<void>)[] = []; | ||
|
||
public revoke(callback: (context: EntitlementContext<T>) => Promise<void>) { | ||
this.revokeCallbacks.push(callback); | ||
return this; | ||
} | ||
public grant(callback: (context: EntitlementContext<T>) => Promise<void>) { | ||
this.grantCallbacks.push(callback); | ||
return this; | ||
} | ||
|
||
public handler(slug: string): EntitlementHandler { | ||
return async ( | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload, | ||
) => { | ||
if (payload.data.benefit.slug === slug) { | ||
switch (payload.type) { | ||
case "benefit_grant.created": | ||
await Promise.all( | ||
this.grantCallbacks.map((callback) => | ||
callback({ | ||
customer: payload.data.customer, | ||
properties: payload.data.properties as T, | ||
payload, | ||
}), | ||
), | ||
); | ||
break; | ||
case "benefit_grant.revoked": | ||
await Promise.all( | ||
this.revokeCallbacks.map((callback) => | ||
callback({ | ||
customer: payload.data.customer, | ||
properties: payload.data.properties as T, | ||
payload, | ||
}), | ||
), | ||
); | ||
break; | ||
} | ||
} | ||
}; | ||
} | ||
public revoke(callback: (context: EntitlementContext<T>) => Promise<void>) { | ||
this.revokeCallbacks.push(callback); | ||
return this; | ||
} | ||
|
||
public handler(slug: string): EntitlementHandler { | ||
return async ( | ||
payload: | ||
| WebhookBenefitGrantCreatedPayload | ||
| WebhookBenefitGrantRevokedPayload, | ||
) => { | ||
if (payload.data.benefit.description === slug) { | ||
switch (payload.type) { | ||
case "benefit_grant.created": | ||
await Promise.all( | ||
this.grantCallbacks.map((callback) => | ||
callback({ | ||
customer: payload.data.customer, | ||
properties: payload.data.properties as T, | ||
payload, | ||
}), | ||
), | ||
); | ||
break; | ||
case "benefit_grant.revoked": | ||
await Promise.all( | ||
this.revokeCallbacks.map((callback) => | ||
callback({ | ||
customer: payload.data.customer, | ||
properties: payload.data.properties as T, | ||
payload, | ||
}), | ||
), | ||
); | ||
break; | ||
} | ||
} | ||
}; | ||
} | ||
} | ||
|
||
export const Entitlement = < | ||
T extends EntitlementProperties = EntitlementProperties, | ||
>() => { | ||
return new EntitlementStrategy<T>(); | ||
}; | ||
export class Entitlements { | ||
static handlers = [] as EntitlementHandler[]; | ||
|
||
static use<T extends EntitlementProperties = EntitlementProperties>( | ||
slug: string, | ||
strategy: EntitlementStrategy<T>, | ||
) { | ||
this.handlers.push(strategy.handler(slug)); | ||
|
||
return this; | ||
} | ||
} |
41 changes: 0 additions & 41 deletions
41
packages/adapter-utils/src/entitlements/Figma/Figma.test.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.