diff --git a/clients/apps/web/package.json b/clients/apps/web/package.json index 48d8a39deb..e6ea4f470c 100644 --- a/clients/apps/web/package.json +++ b/clients/apps/web/package.json @@ -59,6 +59,7 @@ "d3": "^7.9.0", "d3-scale-chromatic": "^3.1.0", "date-fns": "^3.6.0", + "event-source-plus": "^0.1.8", "eventemitter3": "^5.0.1", "framer-motion": "^10.18.0", "geist": "^1.3.1", diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/file-downloads/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/file-downloads/ClientPage.tsx index 805b593358..e7fba8968f 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/file-downloads/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/file-downloads/ClientPage.tsx @@ -1,10 +1,14 @@ 'use client' -import { DownloadableItem as InnerDownloadableItem } from '@/components/Benefit/Downloadables/SubscriberWidget' +import { DownloadableItem as InnerDownloadableItem } from '@/components/Benefit/Downloadables/DownloadablesBenefitGrant' import Pagination from '@/components/Pagination/Pagination' import { PurchasesQueryParametersContext } from '@/components/Purchases/PurchasesQueryParametersContext' import PurchaseSidebar from '@/components/Purchases/PurchasesSidebar' -import { useUserBenefit, useUserDownloadables } from '@/hooks/queries' +import { + useCustomerBenefitGrants, + useCustomerDownloadables, +} from '@/hooks/queries' +import { api } from '@/utils/api' import { FileDownloadOutlined } from '@mui/icons-material' import { DownloadableRead } from '@polar-sh/sdk' import Link from 'next/link' @@ -30,7 +34,7 @@ export default function ClientPage() { [setPurchaseParameters], ) - const { data: downloadables } = useUserDownloadables({ + const { data: downloadables } = useCustomerDownloadables(api, { limit: purchaseParameters.limit, page: purchaseParameters.page, }) @@ -85,7 +89,12 @@ interface DownloadableItemProps { } const DownloadableItem = ({ downloadable }: DownloadableItemProps) => { - const { data: benefit } = useUserBenefit(downloadable.benefit_id) + const { data: benefitGrants } = useCustomerBenefitGrants(api, { + limit: 1, + benefitId: downloadable.benefit_id, + }) + const benefitGrant = benefitGrants?.items[0] + const benefit = benefitGrant?.benefit const organizationLink = useMemo(() => { if (benefit?.organization.profile_settings?.enabled) { @@ -94,7 +103,7 @@ const DownloadableItem = ({ downloadable }: DownloadableItemProps) => { className="dark:text-polar-500 dark:hover:text-polar-200 text-sm text-gray-500 hover:text-gray-700" href={`/${benefit.organization.slug}`} > - {benefit?.organization.name} + {benefit.organization.name} ) } diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/license-keys/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/license-keys/ClientPage.tsx index c1ece4cb6a..98e25e1f47 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/license-keys/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/license-keys/ClientPage.tsx @@ -5,9 +5,13 @@ import { LicenseKeyDetails } from '@/components/Benefit/LicenseKeys/LicenseKeyDe import Pagination from '@/components/Pagination/Pagination' import { PurchasesQueryParametersContext } from '@/components/Purchases/PurchasesQueryParametersContext' import PurchaseSidebar from '@/components/Purchases/PurchasesSidebar' -import { useUserBenefit, useUserLicenseKeys } from '@/hooks/queries' +import { + useCustomerBenefitGrants, + useCustomerLicenseKey, +} from '@/hooks/queries' +import { api } from '@/utils/api' import { Key } from '@mui/icons-material' -import { LicenseKeyRead } from '@polar-sh/sdk' +import { BenefitType, CustomerBenefitGrantLicenseKeys } from '@polar-sh/sdk' import Link from 'next/link' import { useSearchParams } from 'next/navigation' import Avatar from 'polarkit/components/ui/atoms/avatar' @@ -31,9 +35,10 @@ export default function ClientPage() { [setPurchaseParameters], ) - const { data: licenseKeys } = useUserLicenseKeys({ + const { data: benefitGrants } = useCustomerBenefitGrants(api, { limit: purchaseParameters.limit, page: purchaseParameters.page, + type: BenefitType.LICENSE_KEYS, }) return ( @@ -47,7 +52,7 @@ export default function ClientPage() {

License Keys

- {licenseKeys?.pagination.total_count === 0 ? ( + {benefitGrants?.pagination.total_count === 0 ? (
) : (
- {licenseKeys?.items.map((licenseKey) => ( - + {benefitGrants?.items.map((benefitGrant) => ( + ))} { - const { data: benefit } = useUserBenefit(licenseKey.benefit_id) +const LicenseKeyItem = ({ benefitGrant }: LicenseKeyItemProps) => { + const { benefit } = benefitGrant + const { data: licenseKey } = useCustomerLicenseKey( + api, + benefitGrant.properties.license_key_id as string, + ) const organizationLink = useMemo(() => { - if (benefit?.organization.profile_settings?.enabled) { + if (benefit.organization.profile_settings?.enabled) { return ( - {benefit?.organization.name} + {benefit.organization.name} ) } return ( - {benefit?.organization.name} + {benefit.organization.name} ) }, [benefit]) @@ -117,11 +129,15 @@ const LicenseKeyItem = ({ licenseKey }: LicenseKeyItemProps) => {
{benefit?.description}
-
- - -
- + {licenseKey && ( + <> +
+ + +
+ + + )} ) } diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/ClientPage.tsx index 316f6fdc98..46600f5e8e 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/ClientPage.tsx @@ -5,9 +5,10 @@ import Pagination from '@/components/Pagination/Pagination' import { PurchasesQueryParametersContext } from '@/components/Purchases/PurchasesQueryParametersContext' import PurchaseSidebar from '@/components/Purchases/PurchasesSidebar' import AmountLabel from '@/components/Shared/AmountLabel' -import { useUserOrders } from '@/hooks/queries' +import { useCustomerOrders } from '@/hooks/queries' +import { api } from '@/utils/api' import { Search, ShoppingBagOutlined } from '@mui/icons-material' -import { ProductPriceType, UserOrder } from '@polar-sh/sdk' +import { CustomerOrder, ProductPriceType } from '@polar-sh/sdk' import Link from 'next/link' import { useSearchParams } from 'next/navigation' import Button from 'polarkit/components/ui/atoms/button' @@ -31,7 +32,7 @@ export default function ClientPage() { [setPurchaseParameters], ) - const { data: orders } = useUserOrders({ + const { data: orders } = useCustomerOrders(api, { productPriceType: ProductPriceType.ONE_TIME, query: purchaseParameters.query, limit: purchaseParameters.limit, @@ -102,7 +103,7 @@ export default function ClientPage() { ) } -const OrderItem = ({ order }: { order: UserOrder }) => { +const OrderItem = ({ order }: { order: CustomerOrder }) => { const organization = order.product.organization return ( diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/ClientPage.tsx index aaa99103ab..e48113a3e7 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/ClientPage.tsx @@ -1,40 +1,12 @@ 'use client' -import BenefitDetails from '@/components/Benefit/BenefitDetails' -import { BenefitRow } from '@/components/Benefit/BenefitRow' -import { InlineModal } from '@/components/Modal/InlineModal' -import { useUserBenefits, useUserOrderInvoice } from '@/hooks/queries' -import { markdownOptions } from '@/utils/markdown' -import { organizationPageLink } from '@/utils/nav' +import CustomerPortalOrder from '@/components/CustomerPortal/CustomerPortalOrder' +import { api } from '@/utils/api' import { ArrowBackOutlined } from '@mui/icons-material' -import { UserBenefit, UserOrder } from '@polar-sh/sdk' -import Markdown from 'markdown-to-jsx' +import { CustomerOrder } from '@polar-sh/sdk' import Link from 'next/link' -import Avatar from 'polarkit/components/ui/atoms/avatar' -import Button from 'polarkit/components/ui/atoms/button' -import { List, ListItem } from 'polarkit/components/ui/atoms/list' -import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' -import { formatCurrencyAndAmount } from 'polarkit/lib/money' -import { useCallback, useState } from 'react' - -const ClientPage = ({ order }: { order: UserOrder }) => { - const organization = order.product.organization - const { data: benefits } = useUserBenefits({ - orderId: order.id, - limit: 100, - sorting: ['type'], - }) - - const [selectedBenefit, setSelectedBenefit] = useState( - null, - ) - - const orderInvoiceMutation = useUserOrderInvoice() - const openInvoice = useCallback(async () => { - const { url } = await orderInvoiceMutation.mutateAsync(order.id) - window.open(url, '_blank') - }, [orderInvoiceMutation, order]) +const ClientPage = ({ order }: { order: CustomerOrder }) => { return (
{ Back to Purchases -
-
- - {organization && ( - - -

{organization.name}

- - )} -

{order.product.name}

- {order.product.description ? ( -
- - {order.product.description} - -
- ) : ( - <> - )} -
- {(benefits?.items.length ?? 0) > 0 && ( -
-

Benefits

- - {benefits?.items.map((benefit) => ( - setSelectedBenefit(benefit)} - > - - - ))} - -
- )} -
- -
- -

{order.product.name}

-
-

- {formatCurrencyAndAmount(order.amount, order.currency, 0)} -

-

- Purchased on{' '} - {new Date(order.created_at).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - })} -

-
-
- - {organization && - organization.profile_settings?.enabled && - !order.product.is_archived && ( - - - - )} -
-
-
-
- setSelectedBenefit(null)} - modalContent={ -
- {selectedBenefit && ( - - )} -
- } - /> +
) } diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/page.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/page.tsx index afefdf5820..1f364e0d38 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/page.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/products/[id]/page.tsx @@ -1,15 +1,15 @@ import { getServerSideAPI } from '@/utils/api/serverside' -import { ResponseError, UserOrder } from '@polar-sh/sdk' +import { CustomerOrder, ResponseError } from '@polar-sh/sdk' import { notFound } from 'next/navigation' import ClientPage from './ClientPage' export default async function Page({ params }: { params: { id: string } }) { const api = getServerSideAPI() - let order: UserOrder + let order: CustomerOrder try { - order = await api.usersOrders.get({ id: params.id }) + order = await api.customerPortalOrders.get({ id: params.id }) } catch (e) { if (e instanceof ResponseError && e.response.status === 404) { notFound() diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/ClientPage.tsx index e483c16a5a..0d7704ce5f 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/ClientPage.tsx @@ -4,9 +4,10 @@ import Pagination from '@/components/Pagination/Pagination' import { PurchasesQueryParametersContext } from '@/components/Purchases/PurchasesQueryParametersContext' import PurchaseSidebar from '@/components/Purchases/PurchasesSidebar' import AmountLabel from '@/components/Shared/AmountLabel' -import { useUserSubscriptions } from '@/hooks/queries' +import { useCustomerSubscriptions } from '@/hooks/queries' +import { api } from '@/utils/api' import { Search, ShoppingBagOutlined } from '@mui/icons-material' -import { UserSubscription } from '@polar-sh/sdk' +import { CustomerSubscription } from '@polar-sh/sdk' import Link from 'next/link' import { useSearchParams } from 'next/navigation' import { Switch } from 'polarkit/components/ui/atoms' @@ -33,7 +34,7 @@ export default function ClientPage() { [setPurchaseParameters], ) - const { data: subscriptions } = useUserSubscriptions({ + const { data: subscriptions } = useCustomerSubscriptions(api, { active: purchaseParameters.inactive ? undefined : true, query: purchaseParameters.query, limit: purchaseParameters.limit, @@ -135,7 +136,7 @@ const StatusWrapper = ({ const SubscriptionItem = ({ subscription, }: { - subscription: UserSubscription + subscription: CustomerSubscription }) => { const organization = subscription.product.organization diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/ClientPage.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/ClientPage.tsx index 15e226d749..257d7b580f 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/ClientPage.tsx @@ -1,74 +1,16 @@ 'use client' -import BenefitDetails from '@/components/Benefit/BenefitDetails' -import { BenefitRow } from '@/components/Benefit/BenefitRow' -import { ConfirmModal } from '@/components/Modal/ConfirmModal' -import { InlineModal } from '@/components/Modal/InlineModal' -import AmountLabel from '@/components/Shared/AmountLabel' -import ChangePlanModal from '@/components/Subscriptions/ChangePlanModal' -import { - useCancelSubscription, - useUserBenefits, - useUserOrderInvoice, - useUserOrders, -} from '@/hooks/queries' -import { markdownOptions } from '@/utils/markdown' -import { ArrowBackOutlined, ReceiptOutlined } from '@mui/icons-material' -import { UserBenefit, UserOrder, UserSubscription } from '@polar-sh/sdk' -import Markdown from 'markdown-to-jsx' +import CustomerPortalSubscription from '@/components/CustomerPortal/CustomerPortalSubscription' +import { api } from '@/utils/api' +import { ArrowBackOutlined } from '@mui/icons-material' +import { CustomerSubscription } from '@polar-sh/sdk' import Link from 'next/link' -import { FormattedDateTime } from 'polarkit/components/ui/atoms' -import Avatar from 'polarkit/components/ui/atoms/avatar' -import Button from 'polarkit/components/ui/atoms/button' -import { List, ListItem } from 'polarkit/components/ui/atoms/list' -import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' -import { formatCurrencyAndAmount } from 'polarkit/lib/money' -import { useCallback, useState } from 'react' const ClientPage = ({ - subscription: _subscription, + subscription, }: { - subscription: UserSubscription + subscription: CustomerSubscription }) => { - const [subscription, setSubscription] = useState(_subscription) - const organization = subscription.product.organization - const { data: benefits } = useUserBenefits({ - subscriptionId: subscription.id, - limit: 100, - sorting: ['type'], - }) - - const [selectedBenefit, setSelectedBenefit] = useState( - null, - ) - - const { data: orders } = useUserOrders({ - subscriptionId: subscription.id, - limit: 100, - sorting: ['-created_at'], - }) - - const orderInvoiceMutation = useUserOrderInvoice() - const openInvoice = useCallback( - async (order: UserOrder) => { - const { url } = await orderInvoiceMutation.mutateAsync(order.id) - window.open(url, '_blank') - }, - [orderInvoiceMutation], - ) - - const hasInvoices = orders?.items && orders.items.length > 0 - - const [showChangePlanModal, setShowChangePlanModal] = useState(false) - - const cancelSubscription = useCancelSubscription(subscription.id) - const isCanceled = - cancelSubscription.isPending || - cancelSubscription.isSuccess || - subscription.ended_at || - subscription.cancel_at_period_end - const [showCancelModal, setShowCancelModal] = useState(false) - return (
Back to Purchases -
-
- - {organization && ( - - -

{organization.name}

- - )} -

- {subscription.product.name} -

- {subscription.product.description ? ( -
- - {subscription.product.description} - -
- ) : ( - <> - )} -
- {(benefits?.items.length ?? 0) > 0 && ( -
-

Benefits

- - {benefits?.items.map((benefit) => ( - setSelectedBenefit(benefit)} - > - - - ))} - -
- )} -
- -
- -

{subscription.product.name}

-
-

- {subscription.amount && subscription.currency && ( - - )} -

- {!isCanceled && subscription.started_at && ( -

- Subscribed since{' '} - {new Date(subscription.started_at).toLocaleDateString( - 'en-US', - { - year: 'numeric', - month: 'long', - day: 'numeric', - }, - )} -

- )} - {isCanceled && - !subscription.ended_at && - subscription.cancel_at_period_end && - subscription.current_period_end && ( -

- Will be canceled at{' '} - {new Date( - subscription.current_period_end, - ).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - })} -

- )} - {isCanceled && subscription.ended_at && ( -

- Canceled since{' '} - {new Date(subscription.ended_at).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - })} -

- )} -
-
- {!isCanceled && ( - - )} - {!isCanceled && ( - - )} - setShowCancelModal(false)} - title={`Unsubscribe from ${subscription.product.name}?`} - description={ - "At the end of your billing period, you won't have access to your benefits anymore." - } - destructiveText="Unsubscribe" - onConfirm={() => cancelSubscription.mutateAsync()} - destructive - /> -
-
- {hasInvoices && ( -
-

Invoices

- - {orders.items?.map((order) => ( - -
- - - - - {formatCurrencyAndAmount( - order.amount, - order.currency, - 0, - )} - -
- -
- ))} -
-
- )} -
-
- setSelectedBenefit(null)} - modalContent={ -
- {selectedBenefit && ( - - )} -
- } - /> - {organization && ( - setShowChangePlanModal(false)} - modalContent={ - setShowChangePlanModal(false)} - onUserSubscriptionUpdate={setSubscription} - /> - } - /> - )} +
) } diff --git a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/page.tsx b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/page.tsx index 3ee0c0c065..0c5f5770e0 100644 --- a/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/page.tsx +++ b/clients/apps/web/src/app/(main)/(topbar)/(backer)/purchases/subscriptions/[id]/page.tsx @@ -1,15 +1,15 @@ import { getServerSideAPI } from '@/utils/api/serverside' -import { ResponseError, UserSubscription } from '@polar-sh/sdk' +import { CustomerSubscription, ResponseError } from '@polar-sh/sdk' import { notFound } from 'next/navigation' import ClientPage from './ClientPage' export default async function Page({ params }: { params: { id: string } }) { const api = getServerSideAPI() - let subscription: UserSubscription + let subscription: CustomerSubscription try { - subscription = await api.usersSubscriptions.get({ id: params.id }) + subscription = await api.customerPortalSubscriptions.get({ id: params.id }) } catch (e) { if (e instanceof ResponseError && e.response.status === 404) { notFound() diff --git a/clients/apps/web/src/app/(main)/[organization]/(header)/portal/ClientPage.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/ClientPage.tsx similarity index 62% rename from clients/apps/web/src/app/(main)/[organization]/(header)/portal/ClientPage.tsx rename to clients/apps/web/src/app/(main)/[organization]/portal/ClientPage.tsx index 9a41f0166b..03db4d0142 100644 --- a/clients/apps/web/src/app/(main)/[organization]/(header)/portal/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/[organization]/portal/ClientPage.tsx @@ -2,8 +2,8 @@ import { CustomerPortal } from '@/components/CustomerPortal/CustomerPortal' import { - ListResourceUserOrder, - ListResourceUserSubscription, + ListResourceCustomerOrder, + ListResourceCustomerSubscription, Organization, } from '@polar-sh/sdk' @@ -11,16 +11,19 @@ const ClientPage = ({ organization, subscriptions, orders, + customerSessionToken, }: { organization: Organization - subscriptions: ListResourceUserSubscription - orders: ListResourceUserOrder + subscriptions: ListResourceCustomerSubscription + orders: ListResourceCustomerOrder + customerSessionToken?: string }) => { return ( ) } diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/ClientPage.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/ClientPage.tsx new file mode 100644 index 0000000000..c0101cd9d2 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/ClientPage.tsx @@ -0,0 +1,109 @@ +'use client' + +import { useCustomerPortalSessionAuthenticate } from '@/hooks/queries' +import { api } from '@/utils/api' +import { setValidationErrors } from '@/utils/api/errors' +import { Organization, ResponseError, ValidationError } from '@polar-sh/sdk' +import { useRouter } from 'next/navigation' +import Button from 'polarkit/components/ui/atoms/button' + +import { + InputOTP, + InputOTPGroup, + InputOTPSlot, +} from 'polarkit/components/ui/atoms/input-otp' +import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' + +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from 'polarkit/components/ui/form' +import { useCallback } from 'react' +import { useForm } from 'react-hook-form' + +const ClientPage = ({ organization }: { organization: Organization }) => { + const router = useRouter() + const form = useForm<{ code: string }>() + const { control, handleSubmit, setError } = form + const sessionRequest = useCustomerPortalSessionAuthenticate(api) + + const onSubmit = useCallback( + async ({ code }: { code: string }) => { + try { + const { token } = await sessionRequest.mutateAsync({ code }) + router.push( + `/${organization.slug}/portal/?customer_session_token=${token}`, + ) + } catch (e) { + if (e instanceof ResponseError) { + const body = await e.response.json() + if (e.response.status === 422) { + const validationErrors = body['detail'] as ValidationError[] + setValidationErrors(validationErrors, setError) + } + } + } + }, + [sessionRequest, setError, router, organization], + ) + + return ( + +
+
+

+ Verification code +

+

+ Enter the verification code sent to your email address. +

+
+
+ + { + return ( + + + + + {Array.from({ length: 6 }).map((_, index) => ( + + ))} + + + + + + ) + }} + /> + + + +
+
+ ) +} + +export default ClientPage diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/page.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/page.tsx new file mode 100644 index 0000000000..80d5bed32a --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/authenticate/page.tsx @@ -0,0 +1,56 @@ +import { getServerSideAPI } from '@/utils/api/serverside' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' +import type { Metadata } from 'next' +import ClientPage from './ClientPage' + +export async function generateMetadata({ + params, +}: { + params: { organization: string } +}): Promise { + const api = getServerSideAPI() + const organization = await getOrganizationOrNotFound(api, params.organization) + + return { + title: `Customer Portal | ${organization.name}`, // " | Polar is added by the template" + openGraph: { + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + siteName: 'Polar', + type: 'website', + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + }, + ], + }, + twitter: { + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + alt: `${organization.name} on Polar`, + }, + ], + card: 'summary_large_image', + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + }, + } +} + +export default async function Page({ + params, + searchParams, +}: { + params: { organization: string } + searchParams: { customer_session_token?: string } +}) { + const api = getServerSideAPI(searchParams.customer_session_token) + const organization = await getOrganizationOrNotFound(api, params.organization) + + return +} diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/layout.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/layout.tsx new file mode 100644 index 0000000000..ca39815392 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/layout.tsx @@ -0,0 +1,34 @@ +import PublicLayout from '@/components/Layout/PublicLayout' +import { getServerSideAPI } from '@/utils/api/serverside' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' +import Avatar from 'polarkit/components/ui/atoms/avatar' + +export default async function Layout({ + params, + children, +}: { + params: { organization: string } + children: React.ReactNode +}) { + const api = getServerSideAPI() + const organization = await getOrganizationOrNotFound(api, params.organization) + + return ( +
+ +
+
+ +

{organization.name}

+
+

Customer Portal

+
+ {children} +
+
+ ) +} diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/ClientPage.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/ClientPage.tsx new file mode 100644 index 0000000000..a55e79bc4a --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/ClientPage.tsx @@ -0,0 +1,19 @@ +'use client' + +import CustomerPortalOrder from '@/components/CustomerPortal/CustomerPortalOrder' +import { buildAPI } from '@/utils/api' +import { CustomerOrder, Organization } from '@polar-sh/sdk' + +const ClientPage = ({ + order, + customerSessionToken, +}: { + organization: Organization + order: CustomerOrder + customerSessionToken?: string +}) => { + const api = buildAPI({ token: customerSessionToken }) + return +} + +export default ClientPage diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/page.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/page.tsx new file mode 100644 index 0000000000..b3f0220838 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/orders/[id]/page.tsx @@ -0,0 +1,75 @@ +import { getServerSideAPI } from '@/utils/api/serverside' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' +import { CustomerOrder, ResponseError } from '@polar-sh/sdk' +import type { Metadata } from 'next' +import { redirect } from 'next/navigation' +import ClientPage from './ClientPage' + +export async function generateMetadata({ + params, +}: { + params: { organization: string } +}): Promise { + const api = getServerSideAPI() + const organization = await getOrganizationOrNotFound(api, params.organization) + + return { + title: `Customer Portal | ${organization.name}`, // " | Polar is added by the template" + openGraph: { + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + siteName: 'Polar', + type: 'website', + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + }, + ], + }, + twitter: { + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + alt: `${organization.name} on Polar`, + }, + ], + card: 'summary_large_image', + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + }, + } +} + +export default async function Page({ + params, + searchParams, +}: { + params: { organization: string; id: string } + searchParams: { customer_session_token?: string } +}) { + const api = getServerSideAPI(searchParams.customer_session_token) + const organization = await getOrganizationOrNotFound(api, params.organization) + + let order: CustomerOrder | undefined + try { + order = await api.customerPortalOrders.get({ id: params.id }) + } catch (e) { + if (e instanceof ResponseError && e.response.status === 401) { + redirect(`/${organization.slug}/portal/request`) + } else { + throw e + } + } + + return ( + + ) +} diff --git a/clients/apps/web/src/app/(main)/[organization]/(header)/portal/page.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/page.tsx similarity index 64% rename from clients/apps/web/src/app/(main)/[organization]/(header)/portal/page.tsx rename to clients/apps/web/src/app/(main)/[organization]/portal/page.tsx index 8cc7b41dd3..b71a1fc6ed 100644 --- a/clients/apps/web/src/app/(main)/[organization]/(header)/portal/page.tsx +++ b/clients/apps/web/src/app/(main)/[organization]/portal/page.tsx @@ -1,12 +1,12 @@ import { getServerSideAPI } from '@/utils/api/serverside' -import { getStorefrontOrNotFound } from '@/utils/storefront' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' import { - ListResourceUserOrder, - ListResourceUserSubscription, + ListResourceCustomerOrder, + ListResourceCustomerSubscription, ResponseError, } from '@polar-sh/sdk' import type { Metadata } from 'next' -import { notFound } from 'next/navigation' +import { redirect } from 'next/navigation' import ClientPage from './ClientPage' const cacheConfig = { @@ -21,10 +21,7 @@ export async function generateMetadata({ params: { organization: string } }): Promise { const api = getServerSideAPI() - const { organization } = await getStorefrontOrNotFound( - api, - params.organization, - ) + const organization = await getOrganizationOrNotFound(api, params.organization) return { title: `Customer Portal | ${organization.name}`, // " | Polar is added by the template" @@ -59,29 +56,28 @@ export async function generateMetadata({ export default async function Page({ params, + searchParams, }: { - params: { organization: string; productId: string } + params: { organization: string } + searchParams: { customer_session_token?: string } }) { - const api = getServerSideAPI() - const { organization } = await getStorefrontOrNotFound( - api, - params.organization, - ) + const api = getServerSideAPI(searchParams.customer_session_token) + const organization = await getOrganizationOrNotFound(api, params.organization) - let subscriptions: ListResourceUserSubscription | undefined - let oneTimePurchases: ListResourceUserOrder | undefined + let subscriptions: ListResourceCustomerSubscription | undefined + let oneTimePurchases: ListResourceCustomerOrder | undefined try { - subscriptions = await api.usersSubscriptions.list( + subscriptions = await api.customerPortalSubscriptions.list( { organizationId: organization.id, active: true, limit: 100 }, cacheConfig, ) - oneTimePurchases = await api.usersOrders.list({ + oneTimePurchases = await api.customerPortalOrders.list({ organizationId: organization.id, limit: 100, }) } catch (e) { - if (e instanceof ResponseError && e.response.status === 404) { - notFound() + if (e instanceof ResponseError && e.response.status === 401) { + redirect(`/${organization.slug}/portal/request`) } else { throw e } @@ -92,6 +88,7 @@ export default async function Page({ organization={organization} subscriptions={subscriptions} orders={oneTimePurchases} + customerSessionToken={searchParams.customer_session_token} /> ) } diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/request/ClientPage.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/request/ClientPage.tsx new file mode 100644 index 0000000000..3bc4ff00a0 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/request/ClientPage.tsx @@ -0,0 +1,99 @@ +'use client' + +import { useCustomerPortalSessionRequest } from '@/hooks/queries' +import { api } from '@/utils/api' +import { setValidationErrors } from '@/utils/api/errors' +import { Organization, ResponseError, ValidationError } from '@polar-sh/sdk' +import { useRouter } from 'next/navigation' +import Button from 'polarkit/components/ui/atoms/button' +import Input from 'polarkit/components/ui/atoms/input' +import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' + +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from 'polarkit/components/ui/form' +import { useCallback } from 'react' +import { useForm } from 'react-hook-form' + +const ClientPage = ({ organization }: { organization: Organization }) => { + const router = useRouter() + const form = useForm<{ email: string }>() + const { control, handleSubmit, setError } = form + const sessionRequest = useCustomerPortalSessionRequest(api, organization.id) + + const onSubmit = useCallback( + async ({ email }: { email: string }) => { + try { + await sessionRequest.mutateAsync({ email }) + router.push(`/${organization.slug}/portal/authenticate`) + } catch (e) { + if (e instanceof ResponseError) { + const body = await e.response.json() + if (e.response.status === 422) { + const validationErrors = body['detail'] as ValidationError[] + setValidationErrors(validationErrors, setError) + } + } + } + }, + [sessionRequest, setError, router, organization], + ) + + return ( + +
+
+

Sign in

+

+ Enter your email address to access your purchases. A verification + code will be sent to you. +

+
+
+ + { + return ( + + + + + + + ) + }} + /> + + + +
+
+ ) +} + +export default ClientPage diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/request/page.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/request/page.tsx new file mode 100644 index 0000000000..80d5bed32a --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/request/page.tsx @@ -0,0 +1,56 @@ +import { getServerSideAPI } from '@/utils/api/serverside' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' +import type { Metadata } from 'next' +import ClientPage from './ClientPage' + +export async function generateMetadata({ + params, +}: { + params: { organization: string } +}): Promise { + const api = getServerSideAPI() + const organization = await getOrganizationOrNotFound(api, params.organization) + + return { + title: `Customer Portal | ${organization.name}`, // " | Polar is added by the template" + openGraph: { + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + siteName: 'Polar', + type: 'website', + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + }, + ], + }, + twitter: { + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + alt: `${organization.name} on Polar`, + }, + ], + card: 'summary_large_image', + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + }, + } +} + +export default async function Page({ + params, + searchParams, +}: { + params: { organization: string } + searchParams: { customer_session_token?: string } +}) { + const api = getServerSideAPI(searchParams.customer_session_token) + const organization = await getOrganizationOrNotFound(api, params.organization) + + return +} diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/ClientPage.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/ClientPage.tsx new file mode 100644 index 0000000000..8c5c53c542 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/ClientPage.tsx @@ -0,0 +1,19 @@ +'use client' + +import CustomerPortalSubscription from '@/components/CustomerPortal/CustomerPortalSubscription' +import { buildAPI } from '@/utils/api' +import { CustomerSubscription, Organization } from '@polar-sh/sdk' + +const ClientPage = ({ + subscription, + customerSessionToken, +}: { + organization: Organization + subscription: CustomerSubscription + customerSessionToken?: string +}) => { + const api = buildAPI({ token: customerSessionToken }) + return +} + +export default ClientPage diff --git a/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/page.tsx b/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/page.tsx new file mode 100644 index 0000000000..ef6bb08623 --- /dev/null +++ b/clients/apps/web/src/app/(main)/[organization]/portal/subscriptions/[id]/page.tsx @@ -0,0 +1,75 @@ +import { getServerSideAPI } from '@/utils/api/serverside' +import { getOrganizationOrNotFound } from '@/utils/customerPortal' +import { CustomerSubscription, ResponseError } from '@polar-sh/sdk' +import type { Metadata } from 'next' +import { redirect } from 'next/navigation' +import ClientPage from './ClientPage' + +export async function generateMetadata({ + params, +}: { + params: { organization: string } +}): Promise { + const api = getServerSideAPI() + const organization = await getOrganizationOrNotFound(api, params.organization) + + return { + title: `Customer Portal | ${organization.name}`, // " | Polar is added by the template" + openGraph: { + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + siteName: 'Polar', + type: 'website', + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + }, + ], + }, + twitter: { + images: [ + { + url: `https://polar.sh/og?org=${organization.slug}`, + width: 1200, + height: 630, + alt: `${organization.name} on Polar`, + }, + ], + card: 'summary_large_image', + title: `Customer Portal | ${organization.name} on Polar`, + description: `Customer Portal | ${organization.name} on Polar`, + }, + } +} + +export default async function Page({ + params, + searchParams, +}: { + params: { organization: string; id: string } + searchParams: { customer_session_token?: string } +}) { + const api = getServerSideAPI(searchParams.customer_session_token) + const organization = await getOrganizationOrNotFound(api, params.organization) + + let subscription: CustomerSubscription | undefined + try { + subscription = await api.customerPortalSubscriptions.get({ id: params.id }) + } catch (e) { + if (e instanceof ResponseError && e.response.status === 401) { + redirect(`/${organization.slug}/portal/request`) + } else { + throw e + } + } + + return ( + + ) +} diff --git a/clients/apps/web/src/app/(main)/dashboard/[organization]/(header)/benefits/license-keys/ClientPage.tsx b/clients/apps/web/src/app/(main)/dashboard/[organization]/(header)/benefits/license-keys/ClientPage.tsx index d5e237c79b..acac23e266 100644 --- a/clients/apps/web/src/app/(main)/dashboard/[organization]/(header)/benefits/license-keys/ClientPage.tsx +++ b/clients/apps/web/src/app/(main)/dashboard/[organization]/(header)/benefits/license-keys/ClientPage.tsx @@ -1,11 +1,11 @@ 'use client' -import { LicenseKeyActivations } from '@/components/Benefit/LicenseKeys/LicenseKeyActivations' import { LicenseKeyDetails } from '@/components/Benefit/LicenseKeys/LicenseKeyDetails' import { LicenseKeysList } from '@/components/Benefit/LicenseKeys/LicenseKeysList' import { DashboardBody } from '@/components/Layout/DashboardLayout' import { useBenefits, + useLicenseKey, useLicenseKeyUpdate, useOrganizationLicenseKeys, } from '@/hooks/queries' @@ -32,7 +32,7 @@ import { SelectTrigger, SelectValue, } from 'polarkit/components/ui/atoms/select' -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useState } from 'react' export const ClientPage = ({ organization, @@ -62,13 +62,9 @@ export const ClientPage = ({ 'license_keys', ) - const selectedLicenseKey = useMemo(() => { - const selectedLicenseKeyIds = Object.keys(selectedLicenseKeys) - const key = licenseKeys?.items.find( - (licenseKey) => licenseKey.id === selectedLicenseKeyIds[0], - ) - return key - }, [selectedLicenseKeys, licenseKeys]) + const { data: selectedLicenseKey } = useLicenseKey( + Object.keys(selectedLicenseKeys)[0], + ) const getSearchParams = ( pagination: DataTablePaginationState, @@ -147,8 +143,8 @@ export const ClientPage = ({
{selectedLicenseKey.user?.public_name} @@ -161,7 +157,6 @@ export const ClientPage = ({
-
{['disabled', 'revoked'].includes(selectedLicenseKey.status) && (
diff --git a/clients/apps/web/src/components/Benefit/BenefitDetails.tsx b/clients/apps/web/src/components/Benefit/BenefitDetails.tsx deleted file mode 100644 index b5ca2bba6b..0000000000 --- a/clients/apps/web/src/components/Benefit/BenefitDetails.tsx +++ /dev/null @@ -1,84 +0,0 @@ -'use client' - -import GitHubIcon from '@/components/Icons/GitHubIcon' -import { UserBenefit, UserOrder, UserSubscription } from '@polar-sh/sdk' -import Link from 'next/link' -import Button from 'polarkit/components/ui/atoms/button' -import DownloadablesSubscriberWidget from './Downloadables/SubscriberWidget' -import { LicenseKeysSubscriberWidget } from './LicenseKeys/SubscriberWidget' -import ConfigureAdCampaigns from './ads/ConfigureAdCampaigns' -import { resolveBenefitTypeDisplayName } from './utils' - -const GitHubRepoWidget = ({ benefit }: BenefitDetailsProps) => { - if (benefit.type !== 'github_repository') { - return <> - } - - const orgName = benefit.properties.repository_owner - const repoName = benefit.properties.repository_name - const githubURL = `https://github.com/${orgName}/${repoName}` - - return ( - <> - - - - - ) -} - -interface BenefitDetailsProps { - benefit: UserBenefit - order?: UserOrder - subscription?: UserSubscription -} - -const BenefitDetails = ({ - benefit, - order, - subscription, -}: BenefitDetailsProps) => { - const org = benefit.organization - - return ( -
-
-

{benefit.description}

- - {resolveBenefitTypeDisplayName(benefit.type)} - -
- {benefit.type === 'custom' && benefit.properties.note && ( -
-

Note from {org.name}

-

{benefit.properties.note}

-
- )} - - {benefit.type === 'github_repository' && ( - - )} - - {benefit.type === 'ads' ? ( - - ) : null} - - {benefit.type === 'downloadables' ? ( - - ) : null} - - {benefit.type === 'license_keys' ? ( - - ) : null} -
- ) -} - -export default BenefitDetails diff --git a/clients/apps/web/src/components/Benefit/BenefitForm.tsx b/clients/apps/web/src/components/Benefit/BenefitForm.tsx index c3c900c67e..c3465f985e 100644 --- a/clients/apps/web/src/components/Benefit/BenefitForm.tsx +++ b/clients/apps/web/src/components/Benefit/BenefitForm.tsx @@ -374,12 +374,11 @@ const BenefitTypeSelect = ({}) => { - {Object.values(BenefitType) - .map((value) => ( - - {benefitsDisplayNames[value]} - - ))} + {Object.values(BenefitType).map((value) => ( + + {benefitsDisplayNames[value]} + + ))} diff --git a/clients/apps/web/src/components/Benefit/BenefitGrant.tsx b/clients/apps/web/src/components/Benefit/BenefitGrant.tsx new file mode 100644 index 0000000000..5d9a2c3733 --- /dev/null +++ b/clients/apps/web/src/components/Benefit/BenefitGrant.tsx @@ -0,0 +1,282 @@ +import { + useCustomerBenefitGrantUpdate, + useCustomerPortalCustomer, +} from '@/hooks/queries' +import { + CustomerBenefitGrant, + CustomerBenefitGrantCustom, + CustomerBenefitGrantDiscord, + CustomerBenefitGrantDownloadables, + CustomerBenefitGrantGitHubRepository, + CustomerBenefitGrantLicenseKeys, + PolarAPI, +} from '@polar-sh/sdk' +import { usePathname } from 'next/navigation' +import Button from 'polarkit/components/ui/atoms/button' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from 'polarkit/components/ui/atoms/select' +import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' +import { useCallback, useMemo, useState } from 'react' +import { twMerge } from 'tailwind-merge' +import DownloadablesBenefitGrant from './Downloadables/DownloadablesBenefitGrant' +import { LicenseKeyBenefitGrant } from './LicenseKeys/LicenseKeyBenefitGrant' +import { benefitsDisplayNames, resolveBenefitIcon } from './utils' + +interface BenefitGrantProps { + api: PolarAPI + benefitGrant: CustomerBenefitGrant +} + +const BenefitGrantCustom = ({ + benefitGrant, +}: { + benefitGrant: CustomerBenefitGrantCustom +}) => { + const { + benefit: { + properties: { note }, + }, + } = benefitGrant + if (!note) { + return null + } + return ( + +

{note}

+
+ ) +} + +const BenefitGrantOAuth = ({ + api, + benefitGrant, + platform, + connectButtonText, + openButtonUrl, + openButtonText, + selectPlaceholder, +}: { + api: PolarAPI + benefitGrant: + | CustomerBenefitGrantGitHubRepository + | CustomerBenefitGrantDiscord + platform: 'github' | 'discord' + openButtonText: string + openButtonUrl: string + connectButtonText: string + selectPlaceholder: string +}) => { + const pathname = usePathname() + const { + customer_id, + properties: { account_id }, + benefit: { type: benefitType }, + } = benefitGrant + const { data: customer } = useCustomerPortalCustomer(api, customer_id) + const accounts = useMemo( + () => + customer + ? Object.keys(customer.oauth_accounts || {}) + .filter((key) => key.startsWith(platform)) + .map((key) => customer.oauth_accounts[key]) + : [], + [customer, platform], + ) + + const authorize = useCallback(async () => { + const { url } = + await api.customerPortalOauthAccounts.customerPortalOauthAccountsAuthorize( + { + platform, + returnTo: pathname, + customerId: customer_id, + }, + ) + window.location.href = url + }, [customer_id, api, pathname, platform]) + + const updateBenefitGrant = useCustomerBenefitGrantUpdate(api) + const [selectedAccountKey, setSelectedAccountKey] = useState< + string | undefined + >(undefined) + const onAccountSubmit = useCallback(async () => { + if (!selectedAccountKey) { + return + } + await updateBenefitGrant.mutateAsync({ + id: benefitGrant.id, + body: { + benefit_type: benefitType, + properties: { + account_id: selectedAccountKey, + }, + }, + }) + }, [updateBenefitGrant, selectedAccountKey, benefitGrant.id, benefitType]) + + return ( + +
+ {account_id && ( + + + + )} + {!account_id && ( + <> + {accounts.length === 0 ? ( + + ) : ( + <> + + + + )} + + )} +
+
+ ) +} + +const BenefitGrantGitHubRepository = ({ + api, + benefitGrant, +}: { + api: PolarAPI + benefitGrant: CustomerBenefitGrantGitHubRepository +}) => { + const { + benefit: { + properties: { repository_owner, repository_name }, + }, + } = benefitGrant + return ( + + ) +} + +const BenefitGrantDiscord = ({ + api, + benefitGrant, +}: { + api: PolarAPI + benefitGrant: CustomerBenefitGrantDiscord +}) => { + const { + benefit: { + properties: { guild_id }, + }, + } = benefitGrant + return ( + + ) +} + +export const BenefitGrant = ({ api, benefitGrant }: BenefitGrantProps) => { + const { benefit } = benefitGrant + + return ( +
+
+
+ + {resolveBenefitIcon(benefit, 'small')} + +
+
+

+ {benefit.description} +

+

+ {benefitsDisplayNames[benefit.type]} +

+
+
+ {benefit.type === 'custom' && ( + + )} + {benefit.type === 'downloadables' && ( + + )} + {benefit.type === 'license_keys' && ( + + )} + {benefit.type === 'github_repository' && ( + + )} + {benefit.type === 'discord' && ( + + )} +
+ ) +} diff --git a/clients/apps/web/src/components/Benefit/BenefitRow.tsx b/clients/apps/web/src/components/Benefit/BenefitRow.tsx deleted file mode 100644 index 191383604c..0000000000 --- a/clients/apps/web/src/components/Benefit/BenefitRow.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useDiscordAccount, useGitHubAccount } from '@/hooks' -import { getGitHubAuthorizeURL, getUserDiscordAuthorizeURL } from '@/utils/auth' -import { AutoAwesome } from '@mui/icons-material' -import { UserBenefit, UserOrder, UserSubscription } from '@polar-sh/sdk' -import { usePathname } from 'next/navigation' -import { Pill } from 'polarkit/components/ui/atoms' -import Button from 'polarkit/components/ui/atoms/button' -import { twMerge } from 'tailwind-merge' -import { getLicenseKeyGrant } from './LicenseKeys/SubscriberWidget' -import { useBenefitActions } from './useBenefitAction' -import { benefitsDisplayNames, resolveBenefitIcon } from './utils' - -interface BenefitRowProps { - benefit: UserBenefit - order?: UserOrder - subscription?: UserSubscription -} - -export const BenefitRow = ({ - benefit, - order, - subscription, -}: BenefitRowProps) => { - const benefitActions = useBenefitActions(benefit) - const discordAccount = useDiscordAccount() - const gitHubAccount = useGitHubAccount() - const pathname = usePathname() - - const licenseKeyGrant = getLicenseKeyGrant(benefit, order, subscription) - - return ( -
-
-
- - {resolveBenefitIcon(benefit, 'small')} - -
-
-

- {benefit.description} -

-

- {benefitsDisplayNames[benefit.type]} -

-
-
- {benefit.type === 'custom' && benefit.properties.note && ( -
- - - - Private note -
- )} - {benefit.type === 'discord' && !discordAccount && ( - - )} - {benefit.type === 'github_repository' && !gitHubAccount && ( - - )} - {licenseKeyGrant && ( - - {licenseKeyGrant.properties.display_key} - - )} - {benefitActions.length > 0 && ( -
- {benefitActions.map((action) => ( - - ))} -
- )} -
- ) -} diff --git a/clients/apps/web/src/components/Benefit/CreateBenefitModalContent.tsx b/clients/apps/web/src/components/Benefit/CreateBenefitModalContent.tsx index 933eeb10ff..fcb0b29276 100644 --- a/clients/apps/web/src/components/Benefit/CreateBenefitModalContent.tsx +++ b/clients/apps/web/src/components/Benefit/CreateBenefitModalContent.tsx @@ -2,11 +2,11 @@ import { useCreateBenefit } from '@/hooks/queries' import { setValidationErrors } from '@/utils/api/errors' import { BenefitCreate, - type Benefit, BenefitType, Organization, ResponseError, ValidationError, + type Benefit, } from '@polar-sh/sdk' import { useSearchParams } from 'next/navigation' import Button from 'polarkit/components/ui/atoms/button' diff --git a/clients/apps/web/src/components/Benefit/Downloadables/SubscriberWidget.tsx b/clients/apps/web/src/components/Benefit/Downloadables/DownloadablesBenefitGrant.tsx similarity index 73% rename from clients/apps/web/src/components/Benefit/Downloadables/SubscriberWidget.tsx rename to clients/apps/web/src/components/Benefit/Downloadables/DownloadablesBenefitGrant.tsx index 76f5fba5b7..1e30bae591 100644 --- a/clients/apps/web/src/components/Benefit/Downloadables/SubscriberWidget.tsx +++ b/clients/apps/web/src/components/Benefit/Downloadables/DownloadablesBenefitGrant.tsx @@ -1,6 +1,10 @@ -import { BenefitDownloadablesSubscriber, DownloadableRead } from '@polar-sh/sdk' +import { + CustomerBenefitGrantDownloadables, + DownloadableRead, + PolarAPI, +} from '@polar-sh/sdk' -import { useDownloadables } from '@/hooks/queries' +import { useCustomerDownloadables } from '@/hooks/queries' import { ArrowDownward, MoreVertOutlined } from '@mui/icons-material' import { Pill } from 'polarkit/components/ui/atoms' import Button from 'polarkit/components/ui/atoms/button' @@ -10,7 +14,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from 'polarkit/components/ui/dropdown-menu' -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import { twMerge } from 'tailwind-merge' import { FilePreview } from './FileList/FileListItem' @@ -98,25 +102,42 @@ export const DownloadableItem = ({ ) } -const DownloadablesSubscriberWidget = ({ - benefit, +const DownloadablesBenefitGrant = ({ + api, + benefitGrant, }: { - benefit: BenefitDownloadablesSubscriber + api: PolarAPI + benefitGrant: CustomerBenefitGrantDownloadables }) => { - const downloadablesQuery = useDownloadables( - benefit.id, - benefit.properties.active_files, - ) - - let activeLookup: { [key: string]: boolean } = {} - benefit.properties.active_files.reduce((acc, fileId: string) => { - acc[fileId] = true - return acc - }, activeLookup) + const { + benefit: { + properties: { active_files }, + }, + } = benefitGrant + const { data: downloadables, isLoading } = useCustomerDownloadables(api, { + benefitId: benefitGrant.benefit.id, + }) - const downloadables = downloadablesQuery.data?.items + const sortedDownloadables = useMemo(() => { + if (!downloadables) return [] + return downloadables.items.sort((a, b) => { + if ( + active_files.includes(a.file.id) && + !active_files.includes(b.file.id) + ) { + return -1 + } + if ( + !active_files.includes(a.file.id) && + active_files.includes(b.file.id) + ) { + return 1 + } + return active_files.indexOf(a.file.id) - active_files.indexOf(b.file.id) + }) + }, [downloadables, active_files]) - if (downloadablesQuery.isLoading) { + if (isLoading) { // TODO: Style me return
Loading...
} @@ -124,11 +145,11 @@ const DownloadablesSubscriberWidget = ({ return (
    - {downloadables?.map((downloadable) => ( + {sortedDownloadables.map((downloadable) => (
  • ))} @@ -137,4 +158,4 @@ const DownloadablesSubscriberWidget = ({ ) } -export default DownloadablesSubscriberWidget +export default DownloadablesBenefitGrant diff --git a/clients/apps/web/src/components/Benefit/GitHubRepositoryBenefitForm.tsx b/clients/apps/web/src/components/Benefit/GitHubRepositoryBenefitForm.tsx index bca7fca7c7..66a71a7a82 100644 --- a/clients/apps/web/src/components/Benefit/GitHubRepositoryBenefitForm.tsx +++ b/clients/apps/web/src/components/Benefit/GitHubRepositoryBenefitForm.tsx @@ -1,9 +1,9 @@ import { useAuth } from '@/hooks' +import { usePostHog } from '@/hooks/posthog' import { useListIntegrationsGithubRepositoryBenefitUserRepositories } from '@/hooks/queries' import { useUserSSE } from '@/hooks/sse' import { getGitHubRepositoryBenefitAuthorizeURL } from '@/utils/auth' import { defaultApiUrl } from '@/utils/domain' -import { usePostHog } from '@/hooks/posthog' import { RefreshOutlined } from '@mui/icons-material' import { BenefitGitHubRepositoryCreate, @@ -30,7 +30,6 @@ import { FormLabel, FormMessage, } from 'polarkit/components/ui/form' -import { Banner } from 'polarkit/components/ui/molecules' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useFormContext } from 'react-hook-form' @@ -38,100 +37,6 @@ interface GitHubRepositoryBenefitFormProps { update?: boolean } -const GitHubRepositoryBenefitFormForDeprecatedPolarApp = () => { - const { - formState: { defaultValues }, - } = useFormContext() - - return ( - <> - - This benefit is using an older type of integration, and can no longer be - updated. - - - -
    - Organization -
    -
    - - - -
    - -
    - - -
    - Repository -
    -
    - - - -
    - -
    - - -
    - Role -
    -
    - - - -
    - -
    - - ) -} - export const GitHubRepositoryBenefitForm = ({ update = false, }: GitHubRepositoryBenefitFormProps) => { @@ -225,9 +130,12 @@ export const GitHubRepositoryBenefitForm = ({ const onRepositoryChange = useCallback( (key: string) => { const repo = repos.find((r) => r.key == key) + if (!repo) { + return + } setSelectedRepository(repo) - setValue('properties.repository_owner', repo?.repository_owner) - setValue('properties.repository_name', repo?.repository_name) + setValue('properties.repository_owner', repo.repository_owner) + setValue('properties.repository_name', repo.repository_name) }, [repos, setValue], ) @@ -291,12 +199,6 @@ export const GitHubRepositoryBenefitForm = ({ return getGitHubRepositoryBenefitAuthorizeURL({ returnTo }) }, [pathname, description, update]) - // Show configuration for deprecated integration setup - // Does not allow edits - if (defaultValues?.properties?.repository_id) { - return - } - if (!userGitHubBenefitOauth) { return ( <> diff --git a/clients/apps/web/src/components/Benefit/LicenseKeys/BenefitForm.tsx b/clients/apps/web/src/components/Benefit/LicenseKeys/BenefitForm.tsx index f96f4709df..838ad647e0 100644 --- a/clients/apps/web/src/components/Benefit/LicenseKeys/BenefitForm.tsx +++ b/clients/apps/web/src/components/Benefit/LicenseKeys/BenefitForm.tsx @@ -41,7 +41,7 @@ export const LicenseKeysBenefitForm = () => { const showActivationFields = !!activations const defaultActivations: BenefitLicenseKeyActivationProperties = { limit: 5, - enable_user_admin: true, + enable_customer_admin: true, } const limitUsage = watch('properties.limit_usage', undefined) @@ -174,18 +174,18 @@ export const LicenseKeysBenefitForm = () => {
    { return ( { // String | boolean type for some reason const value = checked ? true : false setValue( - 'properties.activations.enable_user_admin', + 'properties.activations.enable_customer_admin', value, ) }} diff --git a/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyActivations.tsx b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyActivations.tsx index e58c4eca90..47578bd431 100644 --- a/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyActivations.tsx +++ b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyActivations.tsx @@ -1,19 +1,20 @@ -import { useLicenseKey, useLicenseKeyDeactivation } from '@/hooks/queries' +import { useCustomerLicenseKeyDeactivate } from '@/hooks/queries' import { CloseOutlined } from '@mui/icons-material' +import { LicenseKeyWithActivations, PolarAPI } from '@polar-sh/sdk' import { FormattedDateTime } from 'polarkit/components/ui/atoms' import Button from 'polarkit/components/ui/atoms/button' import { List, ListItem } from 'polarkit/components/ui/atoms/list' interface LicenseKeyActivationsProps { - licenseKeyId: string + api: PolarAPI + licenseKey: LicenseKeyWithActivations } export const LicenseKeyActivations = ({ - licenseKeyId, + api, + licenseKey, }: LicenseKeyActivationsProps) => { - const { data: licenseKey } = useLicenseKey({ licenseKeyId }) - - const onDeactivate = useLicenseKeyDeactivation(licenseKeyId) + const onDeactivate = useCustomerLicenseKeyDeactivate(api, licenseKey.id) const hasActivations = (licenseKey?.activations?.length ?? 0) > 0 diff --git a/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyBenefitGrant.tsx b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyBenefitGrant.tsx new file mode 100644 index 0000000000..63a8c39b08 --- /dev/null +++ b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeyBenefitGrant.tsx @@ -0,0 +1,58 @@ +import { + CustomerBenefitGrantLicenseKeys, + LicenseKeyWithActivations, + PolarAPI, +} from '@polar-sh/sdk' + +import { useCustomerLicenseKey } from '@/hooks/queries' +import CopyToClipboardInput from 'polarkit/components/ui/atoms/copytoclipboardinput' +import { LicenseKeyActivations } from './LicenseKeyActivations' +import { LicenseKeyDetails } from './LicenseKeyDetails' + +const LicenseKey = ({ + api, + licenseKey, +}: { + api: PolarAPI + licenseKey: LicenseKeyWithActivations +}) => { + if (!licenseKey) { + return <> + } + + return ( + <> + + + + + ) +} + +export const LicenseKeyBenefitGrant = ({ + api, + benefitGrant, +}: { + api: PolarAPI + benefitGrant: CustomerBenefitGrantLicenseKeys +}) => { + const { data: licenseKey, isLoading } = useCustomerLicenseKey( + api, + benefitGrant.properties.license_key_id as string, + ) + + if (isLoading) { + // TODO: Style me + return
    Loading...
    + } + + if (!licenseKey) { + return <> + } + + return ( +
    + +
    + ) +} diff --git a/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeysList.tsx b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeysList.tsx index 5d15b19f08..6b630b0472 100644 --- a/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeysList.tsx +++ b/clients/apps/web/src/components/Benefit/LicenseKeys/LicenseKeysList.tsx @@ -78,28 +78,24 @@ export const LicenseKeysList = ({ }, }, { - id: 'user', - accessorKey: 'user', - sortingFn: (a, b) => { - return a.original.user.public_name.localeCompare( - b.original.user.public_name, - ) - }, + id: 'customer', + accessorKey: 'customer', + enableSorting: false, header: ({ column }) => ( - + ), cell: ({ row: { original: licenseKey } }) => { return (
    - {licenseKey.user.public_name} + {licenseKey.customer.email} - {licenseKey.user.email} + {licenseKey.customer.email}
    diff --git a/clients/apps/web/src/components/Benefit/LicenseKeys/SubscriberWidget.tsx b/clients/apps/web/src/components/Benefit/LicenseKeys/SubscriberWidget.tsx deleted file mode 100644 index 9ee54009e9..0000000000 --- a/clients/apps/web/src/components/Benefit/LicenseKeys/SubscriberWidget.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { - BenefitGrantLicenseKeys, - BenefitLicenseKeysSubscriber, - LicenseKeyWithActivations, - UserBenefit, - UserOrder, - UserSubscription, -} from '@polar-sh/sdk' - -import { useLicenseKey } from '@/hooks/queries' -import CopyToClipboardInput from 'polarkit/components/ui/atoms/copytoclipboardinput' -import { LicenseKeyActivations } from './LicenseKeyActivations' -import { LicenseKeyDetails } from './LicenseKeyDetails' - -export const getLicenseKeyGrant = ( - benefit: UserBenefit, - order?: UserOrder, - subscription?: UserSubscription, -) => { - let licenseKeyGrant = undefined - if (benefit.type === 'license_keys') { - if (order) { - licenseKeyGrant = benefit.grants - .filter((grant) => grant.order_id === order.id) - .pop() - } else if (subscription) { - licenseKeyGrant = benefit.grants - .filter((grant) => grant.subscription_id === subscription.id) - .pop() - } - } - return licenseKeyGrant -} - -const LicenseKey = ({ - licenseKey, -}: { - licenseKey: LicenseKeyWithActivations -}) => { - if (!licenseKey) { - return <> - } - - return ( - <> - - - - - ) -} - -const LicenseKeysWidget = ({ grant }: { grant: BenefitGrantLicenseKeys }) => { - const licenseKeyId = grant.properties.license_key_id - const licenseKeyQuery = useLicenseKey({ licenseKeyId }) - const licenseKey = licenseKeyQuery.data - - if (licenseKeyQuery.isLoading) { - // TODO: Style me - return
    Loading...
    - } - - if (!licenseKey) { - return <> - } - - return ( -
    - -
    - ) -} - -export const LicenseKeysSubscriberWidget = ({ - benefit, - order, - subscription, -}: { - benefit: BenefitLicenseKeysSubscriber - order?: UserOrder - subscription?: UserSubscription -}) => { - const licenseKeyGrant = getLicenseKeyGrant(benefit, order, subscription) - if (!licenseKeyGrant) { - return <> - } - - return -} diff --git a/clients/apps/web/src/components/Benefit/UpdateBenefitModalContent.tsx b/clients/apps/web/src/components/Benefit/UpdateBenefitModalContent.tsx index a3098fbf03..5fe976c722 100644 --- a/clients/apps/web/src/components/Benefit/UpdateBenefitModalContent.tsx +++ b/clients/apps/web/src/components/Benefit/UpdateBenefitModalContent.tsx @@ -10,7 +10,7 @@ import { } from '@polar-sh/sdk' import Button from 'polarkit/components/ui/atoms/button' import { Form } from 'polarkit/components/ui/form' -import { useCallback, useState, MouseEvent } from 'react' +import { MouseEvent, useCallback, useState } from 'react' import { useForm } from 'react-hook-form' import { UpdateBenefitForm } from '../Benefit/BenefitForm' @@ -39,6 +39,7 @@ const UpdateBenefitModalContent = ({ setIsLoading(true) await updateSubscriptionBenefit.mutateAsync({ id: benefit.id, + // @ts-ignore body: { ...benefitUpdate, }, @@ -97,11 +98,7 @@ const UpdateBenefitModalContent = ({ -
    diff --git a/clients/apps/web/src/components/Benefit/ads/ConfigureAdCampaigns.tsx b/clients/apps/web/src/components/Benefit/ads/ConfigureAdCampaigns.tsx deleted file mode 100644 index 85d04135ba..0000000000 --- a/clients/apps/web/src/components/Benefit/ads/ConfigureAdCampaigns.tsx +++ /dev/null @@ -1,401 +0,0 @@ -import ImageUpload from '@/components/Form/ImageUpload' -import { - useUserAdvertisementCampaigns, - useUserCreateAdvertisementCampaign, - useUserDeleteAdvertisementCampaign, - useUserEnableAdvertisementCampaign, - useUserUpdateAdvertisementCampaign, -} from '@/hooks/queries' -import { - AdvertisementCampaign, - BenefitAdsSubscriber, - UserAdvertisementCampaign, - UserAdvertisementCampaignCreate, - UserAdvertisementCampaignUpdate, -} from '@polar-sh/sdk' -import Button from 'polarkit/components/ui/atoms/button' -import Input from 'polarkit/components/ui/atoms/input' -import { - Select, - SelectContent, - SelectItem, - SelectSeparator, - SelectTrigger, - SelectValue, -} from 'polarkit/components/ui/atoms/select' -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from 'polarkit/components/ui/form' -import { useCallback, useEffect, useMemo, useState } from 'react' -import { useForm, useFormContext } from 'react-hook-form' - -const ConfigureAdCampaigns = ({ - benefit, -}: { - benefit: BenefitAdsSubscriber -}) => { - const { data: campaigns } = useUserAdvertisementCampaigns({ limit: 100 }) - const benefitCampaignId = useMemo( - () => - benefit.grants.length > 0 - ? benefit.grants[0].properties.advertisement_campaign_id - : undefined, - [benefit.grants], - ) - const [selectedCampaign, setSelectedCampaign] = useState< - UserAdvertisementCampaign | undefined - >() - const [create, setCreate] = useState(false) - - const form = useForm< - UserAdvertisementCampaignCreate | UserAdvertisementCampaignUpdate - >() - const { reset } = form - - const onSelectCampaign = useCallback( - (value: string | 'create') => { - if (value === 'create') { - setCreate(true) - setSelectedCampaign(undefined) - reset({ - image_url: undefined, - image_url_dark: undefined, - link_url: undefined, - text: undefined, - }) - } else { - setCreate(false) - const campaign = campaigns?.items.find((c) => c.id === value) - setSelectedCampaign(campaign) - reset({ ...campaign }) - } - }, - [campaigns, reset], - ) - - useEffect(() => { - if (!benefitCampaignId) { - return - } - onSelectCampaign(benefitCampaignId) - }, [benefitCampaignId, onSelectCampaign]) - - const enable = useUserEnableAdvertisementCampaign() - const onSubmit = useCallback( - async (campaign: UserAdvertisementCampaign) => { - await enable.mutateAsync({ - id: campaign.id, - body: { benefit_id: benefit.id }, - }) - setCreate(false) - setSelectedCampaign(campaign) - reset(campaign) - }, - [enable, benefit, reset], - ) - - return ( -
    -

    Configure Ad

    - -
    - {selectedCampaign && ( - - )} - {create && } - -
    - ) -} - -export default ConfigureAdCampaigns - -const CreateCampaign = ({ - benefit, - onSubmit: _onSubmit, -}: { - benefit: BenefitAdsSubscriber - onSubmit: (campaign: UserAdvertisementCampaign) => Promise -}) => { - const create = useUserCreateAdvertisementCampaign() - - const form = useFormContext() - const { handleSubmit } = form - - const onSubmit = useCallback( - async ( - userAdvertisementCampaignCreate: UserAdvertisementCampaignCreate, - ) => { - const campaign = await create.mutateAsync(userAdvertisementCampaignCreate) - await _onSubmit(campaign) - }, - [create, _onSubmit], - ) - - return ( -
    -
    -
    -
    - - - -
    - - - - - - -
    -
    - ) -} - -const EditCampaign = ({ - campaign, - benefit, - onSubmit: _onSubmit, -}: { - campaign: AdvertisementCampaign - benefit: BenefitAdsSubscriber - onSubmit: (campaign: UserAdvertisementCampaign) => Promise -}) => { - const edit = useUserUpdateAdvertisementCampaign(campaign.id) - const deleteAd = useUserDeleteAdvertisementCampaign(campaign.id) - - const form = useFormContext() - const { handleSubmit } = form - - const onSubmit = useCallback( - async ( - userAdvertisementCampaignUpdate: UserAdvertisementCampaignUpdate, - ) => { - const updatedCampaign = await edit.mutateAsync( - userAdvertisementCampaignUpdate, - ) - await _onSubmit(updatedCampaign) - }, - [edit, _onSubmit], - ) - - const onDelete = async () => { - await deleteAd.mutateAsync() - } - - return ( -
    -
    -
    -
    - - - -
    - - - - -
    - - -
    - -
    -
    - ) -} - -const FormImage = ({ - height, - width, - name, - title, - description, - required, -}: { - height: number - width: number - name: 'image_url' | 'image_url_dark' - title: string - description?: string - required: boolean -}) => { - const { control } = useFormContext() - - const expectedSizes = [ - [width, height], - [width * 2, height * 2], - [width * 3, height * 3], - ] - - return ( - { - return ( - -
    - {title} - {description && ( -

    - {description} -

    - )} -
    - - { - if (el.naturalWidth === 0 && el.naturalHeight === 0) { - return undefined - } - - const size = [el.naturalWidth, el.naturalHeight] - - for (const expect of expectedSizes) { - if (expect[0] === size[0] && expect[1] === size[1]) { - return undefined - } - } - - return `Expected an image with a resolution of ${expectedSizes - .map((v) => v.join('x')) - .join(' or ')}. Got ${size.join('x')}.` - }} - /> - - -
    - ) - }} - /> - ) -} - -const FormLinkURL = ({}) => { - const { control } = useFormContext() - return ( - { - return ( - -
    - Link -
    - - - - -
    - ) - }} - /> - ) -} - -const FormText = ({}) => { - const { control } = useFormContext() - return ( - { - return ( - -
    - Text -
    - - - - -
    - ) - }} - /> - ) -} diff --git a/clients/apps/web/src/components/Benefit/useBenefitAction.tsx b/clients/apps/web/src/components/Benefit/useBenefitAction.tsx deleted file mode 100644 index 9fec61a268..0000000000 --- a/clients/apps/web/src/components/Benefit/useBenefitAction.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useDiscordAccount, useGitHubAccount } from '@/hooks' -import { LinkOutlined } from '@mui/icons-material' -import { SvgIconTypeMap } from '@mui/material' -import { OverridableComponent } from '@mui/material/OverridableComponent' -import { UserBenefit } from '@polar-sh/sdk' - -interface BenefitAction { - icon: OverridableComponent> & { - muiName: string - } - onClick: () => void - key: string -} - -export const useBenefitActions = (benefit: UserBenefit): BenefitAction[] => { - const discordAccount = useDiscordAccount() - const gitHubAccount = useGitHubAccount() - - switch (benefit.type) { - case 'discord': - return [ - ...(discordAccount - ? [ - { - key: 'discord_link', - icon: LinkOutlined, - onClick: () => { - window.open( - `https://www.discord.com/channels/${benefit.properties.guild_id}`, - ) - }, - }, - ] - : []), - ] - case 'github_repository': - return [ - ...(gitHubAccount - ? [ - { - key: 'github_link', - icon: LinkOutlined, - onClick: () => { - window.open( - `https://github.com/${benefit.properties.repository_owner}/${benefit.properties.repository_name}/invitations`, - ) - }, - }, - ] - : []), - ] - default: - return [] - } -} diff --git a/clients/apps/web/src/components/Benefit/utils.tsx b/clients/apps/web/src/components/Benefit/utils.tsx index c539ac623e..4190593d05 100644 --- a/clients/apps/web/src/components/Benefit/utils.tsx +++ b/clients/apps/web/src/components/Benefit/utils.tsx @@ -8,7 +8,7 @@ import { import { BenefitBase, BenefitType } from '@polar-sh/sdk' import { twMerge } from 'tailwind-merge' -export type CreatableBenefit = BenefitType; +export type CreatableBenefit = BenefitType export const resolveBenefitCategoryIcon = ( type?: BenefitType, @@ -33,7 +33,7 @@ export const resolveBenefitCategoryIcon = ( } export const resolveBenefitIcon = ( - benefit?: BenefitBase, + benefit: BenefitBase, fontSize: 'small' | 'inherit' | 'large' | 'medium' = 'small', className?: string, ) => { diff --git a/clients/apps/web/src/components/Checkout/Checkout.tsx b/clients/apps/web/src/components/Checkout/Checkout.tsx index 19571de227..3b3dc1ee49 100644 --- a/clients/apps/web/src/components/Checkout/Checkout.tsx +++ b/clients/apps/web/src/components/Checkout/Checkout.tsx @@ -5,6 +5,7 @@ import { setValidationErrors } from '@/utils/api/errors' import { CheckoutConfirmStripe, CheckoutPublic, + CheckoutPublicConfirmed, CheckoutUpdatePublic, Organization, ResponseError, @@ -89,7 +90,7 @@ export const Checkout = ({ ) const onCheckoutConfirm = useCallback( - async (body: CheckoutConfirmStripe): Promise => { + async (body: CheckoutConfirmStripe): Promise => { try { const updatedCheckout = await api.checkouts.clientConfirm({ clientSecret: checkout.client_secret, diff --git a/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx b/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx new file mode 100644 index 0000000000..d342186626 --- /dev/null +++ b/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx @@ -0,0 +1,57 @@ +import { useCustomerBenefitGrants } from '@/hooks/queries/customerPortal' +import { useCustomerSSE } from '@/hooks/sse' +import { buildAPI } from '@/utils/api' +import { CheckoutPublic } from '@polar-sh/sdk' +import { List, ListItem } from 'polarkit/components/ui/atoms/list' +import { useEffect } from 'react' +import { BenefitGrant } from '../Benefit/BenefitGrant' +import { SpinnerNoMargin } from '../Shared/Spinner' + +interface CheckoutBenefitsProps { + checkout: CheckoutPublic + customerSessionToken?: string +} + +const CheckoutBenefits = ({ + checkout, + customerSessionToken, +}: CheckoutBenefitsProps) => { + const api = buildAPI({ token: customerSessionToken }) + const { data: benefitGrants, refetch } = useCustomerBenefitGrants(api, { + checkoutId: checkout.id, + }) + const expectedBenefits = checkout.product.benefits.length + + const customerEvents = useCustomerSSE(customerSessionToken) + useEffect(() => { + customerEvents.on('benefit.granted', refetch) + return () => { + customerEvents.off('benefit.granted', refetch) + } + }, [customerEvents, refetch]) + + return ( + <> +
    + + {benefitGrants?.items.map((benefitGrant) => ( + + + + ))} + {!benefitGrants || + (benefitGrants.items.length < expectedBenefits && ( + + +

    + Granting benefits... +

    +
    + ))} +
    +
    + + ) +} + +export default CheckoutBenefits diff --git a/clients/apps/web/src/components/Checkout/CheckoutCelebration.tsx b/clients/apps/web/src/components/Checkout/CheckoutCelebration.tsx deleted file mode 100644 index 63f02032ff..0000000000 --- a/clients/apps/web/src/components/Checkout/CheckoutCelebration.tsx +++ /dev/null @@ -1,112 +0,0 @@ -interface CheckoutCelebrationProps {} - -const CheckoutCelebration: React.FC = () => { - const [gradientColorStart, gradientColorEnd] = ['#d2a1ff', '#9d4cff'] - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) -} - -export default CheckoutCelebration diff --git a/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx b/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx index 26a3425ead..e482a6de01 100644 --- a/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx +++ b/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx @@ -1,7 +1,5 @@ 'use client' -import { useAuth } from '@/hooks' -import { useSendMagicLink } from '@/hooks/magicLink' import { useCheckoutClientSSE } from '@/hooks/sse' import { api } from '@/utils/api' import { organizationPageLink } from '@/utils/nav' @@ -9,14 +7,13 @@ import { CheckoutPublic, CheckoutStatus, Organization } from '@polar-sh/sdk' import { Elements, ElementsConsumer } from '@stripe/react-stripe-js' import { Stripe, loadStripe } from '@stripe/stripe-js' import Link from 'next/link' -import { useRouter } from 'next/navigation' import Avatar from 'polarkit/components/ui/atoms/avatar' import Button from 'polarkit/components/ui/atoms/button' import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' import { useCallback, useEffect, useState } from 'react' import LogoType from '../Brand/LogoType' import { SpinnerNoMargin } from '../Shared/Spinner' -import { CheckoutCard } from './CheckoutCard' +import CheckoutBenefits from './CheckoutBenefits' const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY || '') @@ -79,18 +76,18 @@ const StripeRequiresAction = ({ export interface CheckoutConfirmationProps { checkout: CheckoutPublic organization: Organization + customerSessionToken?: string disabled?: boolean } export const CheckoutConfirmation = ({ checkout: _checkout, organization, + customerSessionToken, disabled, }: CheckoutConfirmationProps) => { - const router = useRouter() - const { currentUser } = useAuth() const [checkout, setCheckout] = useState(_checkout) - const { customer_email: email, product, status } = checkout + const { product, status } = checkout const updateCheckout = useCallback(async () => { const updatedCheckout = await api.checkouts.clientGet({ @@ -110,25 +107,6 @@ export const CheckoutConfirmation = ({ } }, [disabled, checkout, status, checkoutEvents, updateCheckout]) - const [emailSigninLoading, setEmailSigninLoading] = useState(false) - const sendMagicLink = useSendMagicLink() - - const onEmailSignin = useCallback(async () => { - if (!email) { - router.push('/login') - return - } - - setEmailSigninLoading(true) - try { - sendMagicLink(email, `/${organization.slug}`) - } catch (err) { - // TODO: error handling - } finally { - setEmailSigninLoading(false) - } - }, [email, router, organization, sendMagicLink]) - return (
    @@ -158,7 +136,6 @@ export const CheckoutConfirmation = ({ {status === CheckoutStatus.FAILED && 'Please try again or contact support.'}

    - {status === CheckoutStatus.CONFIRMED && (
    {checkout.payment_processor === 'stripe' ? ( @@ -180,31 +157,10 @@ export const CheckoutConfirmation = ({ )} {status === CheckoutStatus.SUCCEEDED && ( <> - {currentUser ? ( - <> - - - - - ) : ( -
    -

    - You now have an account with Polar! Sign in now to manage your - purchases and benefits. -

    - -
    - )} +

    This order was processed by our online reseller & Merchant of Record, Polar, who also handles order-related inquiries and diff --git a/clients/apps/web/src/components/Checkout/CheckoutForm.tsx b/clients/apps/web/src/components/Checkout/CheckoutForm.tsx index 420ca5c24a..9fc56028d3 100644 --- a/clients/apps/web/src/components/Checkout/CheckoutForm.tsx +++ b/clients/apps/web/src/components/Checkout/CheckoutForm.tsx @@ -8,6 +8,7 @@ import { PolarEmbedCheckout } from '@polar-sh/checkout/embed' import { CheckoutConfirmStripe, CheckoutPublic, + CheckoutPublicConfirmed, CheckoutStatus, CheckoutUpdatePublic, } from '@polar-sh/sdk' @@ -602,7 +603,9 @@ const BaseCheckoutForm = ({ interface CheckoutFormProps { checkout: CheckoutPublic onCheckoutUpdate?: (body: CheckoutUpdatePublic) => Promise - onCheckoutConfirm?: (body: CheckoutConfirmStripe) => Promise + onCheckoutConfirm?: ( + body: CheckoutConfirmStripe, + ) => Promise theme?: 'light' | 'dark' embed?: boolean } @@ -648,7 +651,7 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { const checkoutEvents = useCheckoutClientSSE(checkout.client_secret) const onSuccess = useCallback( - async (url: string) => { + async (url: string, customerSessionToken: string) => { const parsedURL = new URL(url) const isInternalURL = url.startsWith(CONFIG.FRONTEND_BASE_URL) @@ -661,6 +664,8 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { } } + parsedURL.searchParams.set('customer_session_token', customerSessionToken) + // For external success URL, make sure the checkout is processed before redirecting // It ensures the user will have an up-to-date status when they are redirected, // especially if the external URL doesn't implement proper webhook handling @@ -769,14 +774,17 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { setLoading(true) if (!checkout.is_payment_form_required) { - let updatedCheckout: CheckoutPublic + let updatedCheckout: CheckoutPublicConfirmed try { updatedCheckout = await onCheckoutConfirm(data) } catch (e) { setLoading(false) return } - await onSuccess(updatedCheckout.success_url) + await onSuccess( + updatedCheckout.success_url, + updatedCheckout.customer_session_token, + ) return } @@ -836,7 +844,7 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { return } - let updatedCheckout: CheckoutPublic + let updatedCheckout: CheckoutPublicConfirmed try { updatedCheckout = await onCheckoutConfirm({ ...data, @@ -861,7 +869,10 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { } } - await onSuccess(updatedCheckout.success_url) + await onSuccess( + updatedCheckout.success_url, + updatedCheckout.customer_session_token, + ) } const inputBoxShadow = diff --git a/clients/apps/web/src/components/CustomerPortal/CustomerPortal.tsx b/clients/apps/web/src/components/CustomerPortal/CustomerPortal.tsx index edc26ec6b5..c178e294b8 100644 --- a/clients/apps/web/src/components/CustomerPortal/CustomerPortal.tsx +++ b/clients/apps/web/src/components/CustomerPortal/CustomerPortal.tsx @@ -1,7 +1,11 @@ 'use client' import AmountLabel from '@/components/Shared/AmountLabel' -import { Organization, UserOrder, UserSubscription } from '@polar-sh/sdk' +import { + CustomerOrder, + CustomerSubscription, + Organization, +} from '@polar-sh/sdk' import Link from 'next/link' import Avatar from 'polarkit/components/ui/atoms/avatar' import Button from 'polarkit/components/ui/atoms/button' @@ -14,41 +18,35 @@ import { PropsWithChildren, useMemo } from 'react' import { twMerge } from 'tailwind-merge' export interface CustomerPortalProps { - organization?: Organization - subscriptions: UserSubscription[] - orders: UserOrder[] + organization: Organization + subscriptions: CustomerSubscription[] + orders: CustomerOrder[] + customerSessionToken?: string } export const CustomerPortal = ({ organization, subscriptions, orders, + customerSessionToken, }: CustomerPortalProps) => { return (

    - {organization && !organization.profile_settings?.enabled && ( -
    - -

    {organization.name}

    -
    - )} -
    -

    Customer Portal

    -
    -
    {subscriptions.map((s) => ( - + ))}
    @@ -130,14 +128,22 @@ export const CustomerPortal = ({ /> ), cell: ({ row }) => { + const { + id, + product: { is_recurring }, + subscription_id, + } = row.original return (
    )}
    - +
    @@ -283,7 +296,12 @@ const SubscriptionItem = ({
    Benefits - + diff --git a/clients/apps/web/src/components/CustomerPortal/CustomerPortalOrder.tsx b/clients/apps/web/src/components/CustomerPortal/CustomerPortalOrder.tsx new file mode 100644 index 0000000000..d68772cf00 --- /dev/null +++ b/clients/apps/web/src/components/CustomerPortal/CustomerPortalOrder.tsx @@ -0,0 +1,129 @@ +'use client' + +import { BenefitGrant } from '@/components/Benefit/BenefitGrant' +import { + useCustomerBenefitGrants, + useCustomerOrderInvoice, +} from '@/hooks/queries' +import { markdownOptions } from '@/utils/markdown' +import { organizationPageLink } from '@/utils/nav' +import { CustomerOrder, PolarAPI } from '@polar-sh/sdk' +import Markdown from 'markdown-to-jsx' +import Link from 'next/link' +import Avatar from 'polarkit/components/ui/atoms/avatar' +import Button from 'polarkit/components/ui/atoms/button' +import { List, ListItem } from 'polarkit/components/ui/atoms/list' +import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' +import { formatCurrencyAndAmount } from 'polarkit/lib/money' +import { useCallback } from 'react' + +const CustomerPortalOrder = ({ + api, + order, +}: { + api: PolarAPI + order: CustomerOrder +}) => { + const organization = order.product.organization + const { data: benefitGrants } = useCustomerBenefitGrants(api, { + orderId: order.id, + limit: 100, + sorting: ['type'], + }) + + const orderInvoiceMutation = useCustomerOrderInvoice(api) + const openInvoice = useCallback(async () => { + const { url } = await orderInvoiceMutation.mutateAsync({ id: order.id }) + window.open(url, '_blank') + }, [orderInvoiceMutation, order]) + + return ( + <> +
    +
    + + + +

    {organization.name}

    + +

    {order.product.name}

    + {order.product.description ? ( +
    + + {order.product.description} + +
    + ) : ( + <> + )} +
    + {(benefitGrants?.items.length ?? 0) > 0 && ( +
    +

    Benefits

    + + {benefitGrants?.items.map((benefitGrant) => ( + + + + ))} + +
    + )} +
    + +
    + +

    {order.product.name}

    +
    +

    + {formatCurrencyAndAmount(order.amount, order.currency, 0)} +

    +

    + Purchased on{' '} + {new Date(order.created_at).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + })} +

    +
    +
    + + {organization && + organization.profile_settings?.enabled && + !order.product.is_archived && ( + + + + )} +
    +
    +
    +
    + + ) +} + +export default CustomerPortalOrder diff --git a/clients/apps/web/src/components/CustomerPortal/CustomerPortalSubscription.tsx b/clients/apps/web/src/components/CustomerPortal/CustomerPortalSubscription.tsx new file mode 100644 index 0000000000..ae12117605 --- /dev/null +++ b/clients/apps/web/src/components/CustomerPortal/CustomerPortalSubscription.tsx @@ -0,0 +1,259 @@ +'use client' + +import { BenefitGrant } from '@/components/Benefit/BenefitGrant' +import { ConfirmModal } from '@/components/Modal/ConfirmModal' +import { InlineModal } from '@/components/Modal/InlineModal' +import AmountLabel from '@/components/Shared/AmountLabel' +import ChangePlanModal from '@/components/Subscriptions/ChangePlanModal' +import { + useCustomerBenefitGrants, + useCustomerCancelSubscription, + useCustomerOrderInvoice, + useCustomerOrders, +} from '@/hooks/queries' +import { markdownOptions } from '@/utils/markdown' +import { ReceiptOutlined } from '@mui/icons-material' +import { CustomerOrder, CustomerSubscription, PolarAPI } from '@polar-sh/sdk' +import Markdown from 'markdown-to-jsx' +import Link from 'next/link' +import { FormattedDateTime } from 'polarkit/components/ui/atoms' +import Avatar from 'polarkit/components/ui/atoms/avatar' +import Button from 'polarkit/components/ui/atoms/button' +import { List, ListItem } from 'polarkit/components/ui/atoms/list' +import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' +import { formatCurrencyAndAmount } from 'polarkit/lib/money' +import { useCallback, useState } from 'react' + +const CustomerPortalSubscription = ({ + api, + subscription: _subscription, +}: { + api: PolarAPI + subscription: CustomerSubscription +}) => { + const [subscription, setSubscription] = useState(_subscription) + const organization = subscription.product.organization + const { data: benefitGrants } = useCustomerBenefitGrants(api, { + subscriptionId: subscription.id, + limit: 100, + sorting: ['type'], + }) + + const { data: orders } = useCustomerOrders(api, { + subscriptionId: subscription.id, + limit: 100, + sorting: ['-created_at'], + }) + + const orderInvoiceMutation = useCustomerOrderInvoice(api) + const openInvoice = useCallback( + async (order: CustomerOrder) => { + const { url } = await orderInvoiceMutation.mutateAsync({ id: order.id }) + window.open(url, '_blank') + }, + [orderInvoiceMutation], + ) + + const hasInvoices = orders?.items && orders.items.length > 0 + + const [showChangePlanModal, setShowChangePlanModal] = useState(false) + + const cancelSubscription = useCustomerCancelSubscription(api) + const isCanceled = + cancelSubscription.isPending || + cancelSubscription.isSuccess || + subscription.ended_at || + subscription.cancel_at_period_end + const [showCancelModal, setShowCancelModal] = useState(false) + + return ( + <> +
    +
    + + + +

    {organization.name}

    + +

    + {subscription.product.name} +

    + {subscription.product.description ? ( +
    + + {subscription.product.description} + +
    + ) : ( + <> + )} +
    + {(benefitGrants?.items.length ?? 0) > 0 && ( +
    +

    Benefits

    + + {benefitGrants?.items.map((benefitGrant) => ( + + + + ))} + +
    + )} +
    + +
    + +

    {subscription.product.name}

    +
    +

    + {subscription.amount && subscription.currency && ( + + )} +

    + {!isCanceled && subscription.started_at && ( +

    + Subscribed since{' '} + {new Date(subscription.started_at).toLocaleDateString( + 'en-US', + { + year: 'numeric', + month: 'long', + day: 'numeric', + }, + )} +

    + )} + {isCanceled && + !subscription.ended_at && + subscription.cancel_at_period_end && + subscription.current_period_end && ( +

    + Will be canceled at{' '} + {new Date( + subscription.current_period_end, + ).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + })} +

    + )} + {isCanceled && subscription.ended_at && ( +

    + Canceled since{' '} + {new Date(subscription.ended_at).toLocaleDateString('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric', + })} +

    + )} +
    +
    + {!isCanceled && ( + + )} + {!isCanceled && ( + + )} + setShowCancelModal(false)} + title={`Unsubscribe from ${subscription.product.name}?`} + description={ + "At the end of your billing period, you won't have access to your benefits anymore." + } + destructiveText="Unsubscribe" + onConfirm={() => + cancelSubscription.mutateAsync({ id: subscription.id }) + } + destructive + /> +
    +
    + {hasInvoices && ( +
    +

    Invoices

    + + {orders.items?.map((order) => ( + +
    + + + + + {formatCurrencyAndAmount( + order.amount, + order.currency, + 0, + )} + +
    + +
    + ))} +
    +
    + )} +
    +
    + setShowChangePlanModal(false)} + modalContent={ + setShowChangePlanModal(false)} + onUserSubscriptionUpdate={setSubscription} + /> + } + /> + + ) +} + +export default CustomerPortalSubscription diff --git a/clients/apps/web/src/components/Customization/utils.ts b/clients/apps/web/src/components/Customization/utils.ts index 6ffdb70428..22a6e02ed3 100644 --- a/clients/apps/web/src/components/Customization/utils.ts +++ b/clients/apps/web/src/components/Customization/utils.ts @@ -2,10 +2,10 @@ import { CheckoutProduct, CheckoutPublic, CheckoutStatus, + CustomerOrder, + CustomerSubscription, ProductPrice, ProductStorefront, - UserOrder, - UserSubscription, } from '@polar-sh/sdk' const PRODUCT_DESCRIPTION = `# Et Tritonia pectora partus praebentem @@ -210,12 +210,13 @@ export const CHECKOUT_PREVIEW: CheckoutPublic = createCheckoutPreview( PRODUCT_PREVIEW.prices[0], ) -export const ORDER_PREVIEW: UserOrder = { +export const ORDER_PREVIEW: CustomerOrder = { id: '123', amount: 10000, currency: 'usd', tax_amount: 1200, user_id: '123', + customer_id: '123', product_id: PRODUCT_PREVIEW.id, product_price_id: PRODUCT_PREVIEW.prices[0].id, product_price: PRODUCT_PREVIEW.prices[0], @@ -229,7 +230,7 @@ export const ORDER_PREVIEW: UserOrder = { modified_at: new Date().toDateString(), } -export const SUBSCRIPTION_ORDER_PREVIEW: UserSubscription = { +export const SUBSCRIPTION_ORDER_PREVIEW: CustomerSubscription = { created_at: new Date().toDateString(), modified_at: new Date().toDateString(), id: '123', @@ -245,6 +246,7 @@ export const SUBSCRIPTION_ORDER_PREVIEW: UserSubscription = { started_at: new Date().toDateString(), ended_at: null, user_id: '123', + customer_id: '123', product_id: SUBSCRIPTION_PRODUCT_PREVIEW.id, price_id: SUBSCRIPTION_PRODUCT_PREVIEW.prices[0].id, checkout_id: null, diff --git a/clients/apps/web/src/components/Dashboard/navigation.tsx b/clients/apps/web/src/components/Dashboard/navigation.tsx index 6a6157a391..e2d9be93e5 100644 --- a/clients/apps/web/src/components/Dashboard/navigation.tsx +++ b/clients/apps/web/src/components/Dashboard/navigation.tsx @@ -8,6 +8,7 @@ import { HiveOutlined, HowToVote, ModeStandby, + PeopleOutlined, ShoppingBagOutlined, SpaceDashboardOutlined, Storefront, @@ -182,6 +183,16 @@ const generalRoutesList = (org: Organization): Route[] => [ }, ], }, + { + id: 'customers', + title: 'Customers', + icon: , + link: `/dashboard/${org.slug}/customers`, + checkIsActive: (currentRoute: string): boolean => { + return currentRoute.startsWith(`/dashboard/${org.slug}/customers`) + }, + if: true, + }, { id: 'org-sales', title: 'Sales', diff --git a/clients/apps/web/src/components/Embed/Subscribe.tsx b/clients/apps/web/src/components/Embed/Subscribe.tsx index 7d693a641e..b02806cf28 100644 --- a/clients/apps/web/src/components/Embed/Subscribe.tsx +++ b/clients/apps/web/src/components/Embed/Subscribe.tsx @@ -1,4 +1,4 @@ -import { Customer } from '@polar-sh/sdk' +import { StorefrontCustomer } from '@polar-sh/sdk' import React from 'react' export const Subscribe = ({ @@ -7,7 +7,7 @@ export const Subscribe = ({ darkmode, label, }: { - customers: Customer[] + customers: StorefrontCustomer[] totalCustomers: number darkmode: boolean label: string @@ -88,48 +88,31 @@ export const Subscribe = ({ height: '22px', }} > - {customers.map((user, idx) => ( + {customers.map((customer, idx) => ( - {user.avatar_url && ( - 0 ? '-6px' : '', - flexShrink: '0', - }} - /> - )} - {!user.avatar_url && ( -
    - {user.public_name} -
    - )} +
    + {customer.name} +
    ))} diff --git a/clients/apps/web/src/components/Notifications/Popover.tsx b/clients/apps/web/src/components/Notifications/Popover.tsx index ba484e4e0a..89545efc0c 100644 --- a/clients/apps/web/src/components/Notifications/Popover.tsx +++ b/clients/apps/web/src/components/Notifications/Popover.tsx @@ -9,7 +9,6 @@ import { import { useOutsideClick } from '@/utils/useOutsideClick' import { Announcement, Notifications, VerifiedUser } from '@mui/icons-material' import { - BenefitPreconditionErrorNotification, MaintainerAccountReviewedNotification, MaintainerAccountUnderReviewNotification, MaintainerCreateAccountNotification, @@ -677,39 +676,6 @@ const MaintainerNewProductSale = ({ ) } -const BenefitPreconditionError = ({ - n, -}: { - n: BenefitPreconditionErrorNotification -}) => { - const { - payload: { - scope_name, - benefit_description, - organization_name, - extra_context, - }, - } = n - return ( - - {{ - text: ( - <> - The benefit {benefit_description} from {organization_name}'s{' '} - {scope_name} could not be granted.{' '} - {extra_context && (extra_context as any).url && ( - - <>Solve it - - )} - - ), - icon: , - }} - - ) -} - const MaintainerCreateAccount = ({ n, }: { @@ -790,9 +756,6 @@ export const Notification = ({ case 'MaintainerNewProductSaleNotification': return - case 'BenefitPreconditionErrorNotification': - return - case 'MaintainerCreateAccountNotification': return } diff --git a/clients/apps/web/src/components/Organization/StorefrontNav.tsx b/clients/apps/web/src/components/Organization/StorefrontNav.tsx index 78bd1b79dd..102cf18965 100644 --- a/clients/apps/web/src/components/Organization/StorefrontNav.tsx +++ b/clients/apps/web/src/components/Organization/StorefrontNav.tsx @@ -1,6 +1,7 @@ 'use client' -import { useUserOrders } from '@/hooks/queries' +import { useCustomerOrders } from '@/hooks/queries' +import { api } from '@/utils/api' import { organizationPageLink } from '@/utils/nav' import { Organization } from '@polar-sh/sdk' import Link from 'next/link' @@ -28,7 +29,7 @@ export const StorefrontNav = ({ const currentTab = routeSegment ?? 'products' const router = useRouter() - const { data: orders } = useUserOrders({ + const { data: orders } = useCustomerOrders(api, { organizationId: organization.id, }) diff --git a/clients/apps/web/src/components/Products/CreateProductPage.tsx b/clients/apps/web/src/components/Products/CreateProductPage.tsx index 40a0e7eace..3eb643b087 100644 --- a/clients/apps/web/src/components/Products/CreateProductPage.tsx +++ b/clients/apps/web/src/components/Products/CreateProductPage.tsx @@ -44,9 +44,9 @@ export const CreateProductPage = ({ organization }: CreateProductPageProps) => { clearDraft, } = useStore() - const [enabledBenefitIds, setEnabledBenefitIds] = useState< - Benefit['id'][] - >([]) + const [enabledBenefitIds, setEnabledBenefitIds] = useState( + [], + ) const [isLoading, setLoading] = useState(false) diff --git a/clients/apps/web/src/components/Products/EditProductPage.tsx b/clients/apps/web/src/components/Products/EditProductPage.tsx index 87a9e27f05..6d878e959c 100644 --- a/clients/apps/web/src/components/Products/EditProductPage.tsx +++ b/clients/apps/web/src/components/Products/EditProductPage.tsx @@ -51,9 +51,9 @@ export const EditProductPage = ({ [benefits], ) - const [enabledBenefitIds, setEnabledBenefitIds] = useState< - Benefit['id'][] - >(product.benefits.map((benefit) => benefit.id) ?? []) + const [enabledBenefitIds, setEnabledBenefitIds] = useState( + product.benefits.map((benefit) => benefit.id) ?? [], + ) const form = useForm({ defaultValues: { diff --git a/clients/apps/web/src/components/Products/ProductWizard/useCreateProductWizard.ts b/clients/apps/web/src/components/Products/ProductWizard/useCreateProductWizard.ts index df2c3b5281..a4b1dd15c6 100644 --- a/clients/apps/web/src/components/Products/ProductWizard/useCreateProductWizard.ts +++ b/clients/apps/web/src/components/Products/ProductWizard/useCreateProductWizard.ts @@ -29,9 +29,9 @@ export const useCreateProductWizard = ( [benefits], ) - const [enabledBenefitIds, setEnabledBenefitIds] = useState< - Benefit['id'][] - >([]) + const [enabledBenefitIds, setEnabledBenefitIds] = useState( + [], + ) const [isLoading, setLoading] = useState(false) diff --git a/clients/apps/web/src/components/Profile/CreatorEditor/CreatorsModal.tsx b/clients/apps/web/src/components/Profile/CreatorEditor/CreatorsModal.tsx index 8ed69f4aa7..e4ab09de3f 100644 --- a/clients/apps/web/src/components/Profile/CreatorEditor/CreatorsModal.tsx +++ b/clients/apps/web/src/components/Profile/CreatorEditor/CreatorsModal.tsx @@ -1,5 +1,5 @@ import ProductPill from '@/components/Products/ProductPill' -import { useOrganization, useUserSubscriptions } from '@/hooks/queries' +import { useCustomerSubscriptions, useOrganization } from '@/hooks/queries' import { api } from '@/utils/api' import { getStorefrontOrNotFound } from '@/utils/storefront' import { CloseOutlined } from '@mui/icons-material' @@ -27,7 +27,7 @@ export const CreatorsModal = ({ const [username, setUsername] = useState('') const [showOrgNotFound, toggleOrgNotFound] = useState(false) - const subscriptions = useUserSubscriptions().data?.items || [] + const subscriptions = useCustomerSubscriptions(api).data?.items || [] const addCreator = async (organizationName: string) => { toggleOrgNotFound(false) diff --git a/clients/apps/web/src/components/Purchases/PurchasesSidebar.tsx b/clients/apps/web/src/components/Purchases/PurchasesSidebar.tsx index 7c5d17b55f..ed59c34fcb 100644 --- a/clients/apps/web/src/components/Purchases/PurchasesSidebar.tsx +++ b/clients/apps/web/src/components/Purchases/PurchasesSidebar.tsx @@ -1,13 +1,13 @@ 'use client' import { + useCustomerBenefitGrants, + useCustomerOrders, + useCustomerSubscriptions, usePersonalDashboard, - useUserDownloadables, - useUserLicenseKeys, - useUserOrders, - useUserSubscriptions, } from '@/hooks/queries' -import { ProductPriceType } from '@polar-sh/sdk' +import { api } from '@/utils/api' +import { BenefitType, ProductPriceType } from '@polar-sh/sdk' import Link, { LinkProps } from 'next/link' import { usePathname } from 'next/navigation' import ShadowBox from 'polarkit/components/ui/atoms/shadowbox' @@ -37,16 +37,22 @@ const PurchaseLink = ({ ...props }: PropsWithChildren) => { const PurchaseSidebar: React.FC> = ({ children, }) => { - const { data: orders } = useUserOrders({ + const { data: orders } = useCustomerOrders(api, { limit: 1, productPriceType: ProductPriceType.ONE_TIME, }) - const { data: subscriptions } = useUserSubscriptions({ + const { data: subscriptions } = useCustomerSubscriptions(api, { limit: 1, active: true, }) - const { data: licenseKeys } = useUserLicenseKeys({ limit: 1 }) - const { data: fileDownloads } = useUserDownloadables({ limit: 1 }) + const { data: licenseKeysGrants } = useCustomerBenefitGrants(api, { + limit: 1, + type: BenefitType.LICENSE_KEYS, + }) + const { data: fileDownloadsGrants } = useCustomerBenefitGrants(api, { + limit: 1, + type: BenefitType.DOWNLOADABLES, + }) const { data: dashboard } = usePersonalDashboard({ ...DefaultFilters, @@ -77,11 +83,11 @@ const PurchaseSidebar: React.FC> = ({ License Keys - {licenseKeys?.pagination.total_count || 0} + {licenseKeysGrants?.pagination.total_count || 0} File Downloads - {fileDownloads?.pagination.total_count || 0} + {fileDownloadsGrants?.pagination.total_count || 0} {fundedIssues > 0 && ( diff --git a/clients/apps/web/src/components/Subscriptions/ChangePlanModal.tsx b/clients/apps/web/src/components/Subscriptions/ChangePlanModal.tsx index 215bb2c8a6..039b9b8f48 100644 --- a/clients/apps/web/src/components/Subscriptions/ChangePlanModal.tsx +++ b/clients/apps/web/src/components/Subscriptions/ChangePlanModal.tsx @@ -1,19 +1,19 @@ 'use client' import { + CustomerSubscription, Organization, + PolarAPI, ProductPrice, ProductPriceRecurringFixed, ProductPriceRecurringFree, ProductStorefront, ResponseError, SubscriptionRecurringInterval, - UserSubscription, } from '@polar-sh/sdk' import { InlineModalHeader } from '@/components/Modal/InlineModal' -import { useStorefront, useUpdateSubscription } from '@/hooks/queries' -import { api } from '@/utils/api' +import { useCustomerUpdateSubscription, useStorefront } from '@/hooks/queries' import { formatCurrencyAndAmount } from '@polarkit/lib/money' import { useRouter } from 'next/navigation' import Button from 'polarkit/components/ui/atoms/button' @@ -47,15 +47,17 @@ const ProductPriceListItem = ({ } const ChangePlanModal = ({ + api, organization, subscription, hide, onUserSubscriptionUpdate, }: { + api: PolarAPI organization: Organization - subscription: UserSubscription + subscription: CustomerSubscription hide: () => void - onUserSubscriptionUpdate: (subscription: UserSubscription) => void + onUserSubscriptionUpdate: (subscription: CustomerSubscription) => void }) => { const router = useRouter() const { data: storefront } = useStorefront(organization.slug) @@ -114,7 +116,7 @@ const ChangePlanModal = ({ } }, [selectedPrice, currentPrice]) - const updateSubscription = useUpdateSubscription() + const updateSubscription = useCustomerUpdateSubscription(api) const onConfirm = useCallback(async () => { if (!selectedPrice) return try { diff --git a/clients/apps/web/src/components/Widgets/OrdersWidget.tsx b/clients/apps/web/src/components/Widgets/OrdersWidget.tsx index f088ddec5a..086221236d 100644 --- a/clients/apps/web/src/components/Widgets/OrdersWidget.tsx +++ b/clients/apps/web/src/components/Widgets/OrdersWidget.tsx @@ -48,8 +48,8 @@ const OrderCard = ({ className, order }: OrderCardProps) => {
    {order.user.public_name} diff --git a/clients/apps/web/src/hooks/queries/customerPortal.ts b/clients/apps/web/src/hooks/queries/customerPortal.ts new file mode 100644 index 0000000000..05bae5b70c --- /dev/null +++ b/clients/apps/web/src/hooks/queries/customerPortal.ts @@ -0,0 +1,166 @@ +import { queryClient } from '@/utils/api' +import { + CustomerBenefitGrantUpdate, + CustomerPortalBenefitGrantsApiListRequest, + CustomerPortalDownloadablesApiListRequest, + CustomerPortalLicenseKeysApiListRequest, + CustomerPortalOrdersApiListRequest, + CustomerPortalSubscriptionsApiListRequest, + CustomerSubscriptionUpdate, + PolarAPI, +} from '@polar-sh/sdk' +import { useMutation, useQuery } from '@tanstack/react-query' +import { defaultRetry } from './retry' + +export const useCustomerPortalSessionRequest = ( + api: PolarAPI, + organizationId: string, +) => + useMutation({ + mutationFn: ({ email }: { email: string }) => + api.customerPortalCustomerSession.customerPortalCustomerSessionRequest({ + body: { email, organization_id: organizationId }, + }), + }) + +export const useCustomerPortalSessionAuthenticate = (api: PolarAPI) => + useMutation({ + mutationFn: ({ code }: { code: string }) => + api.customerPortalCustomerSession.customerPortalCustomerSessionAuthenticate( + { + body: { code }, + }, + ), + }) + +export const useCustomerPortalCustomer = (api: PolarAPI, id: string) => + useQuery({ + queryKey: ['customer_portal_customer', { id }], + queryFn: () => api.customerPortalCustomers.get({ id }), + retry: defaultRetry, + }) + +export const useCustomerBenefitGrants = ( + api: PolarAPI, + parameters?: CustomerPortalBenefitGrantsApiListRequest, +) => + useQuery({ + queryKey: ['customer_benefit_grants', { ...(parameters || {}) }], + queryFn: () => api.customerPortalBenefitGrants.list(parameters), + retry: defaultRetry, + }) + +export const useCustomerBenefitGrantUpdate = (api: PolarAPI) => + useMutation({ + mutationFn: (variables: { id: string; body: CustomerBenefitGrantUpdate }) => + api.customerPortalBenefitGrants.update(variables), + onSuccess: async (_result, _variables, _ctx) => { + queryClient.invalidateQueries({ + queryKey: ['customer_benefit_grants'], + }) + }, + }) + +export const useCustomerLicenseKeys = ( + api: PolarAPI, + parameters: CustomerPortalLicenseKeysApiListRequest, +) => + useQuery({ + queryKey: ['customer_license_keys', { parameters }], + queryFn: () => api.customerPortalLicenseKeys.list(parameters), + retry: defaultRetry, + }) + +export const useCustomerLicenseKey = (api: PolarAPI, id: string) => + useQuery({ + queryKey: ['customer_license_keys', { id }], + queryFn: () => api.customerPortalLicenseKeys.get({ id }), + retry: defaultRetry, + }) + +export const useCustomerLicenseKeyDeactivate = (api: PolarAPI, id: string) => + useMutation({ + mutationFn: (opts: { + key: string + organizationId: string + activationId: string + }) => + api.customerPortalLicenseKeys.deactivate({ + body: { + key: opts.key, + organization_id: opts.organizationId, + activation_id: opts.activationId, + }, + }), + onSuccess: async (_result, _variables, _ctx) => { + queryClient.invalidateQueries({ + queryKey: ['customer_license_keys', { id }], + }) + }, + }) + +export const useCustomerDownloadables = ( + api: PolarAPI, + parameters?: CustomerPortalDownloadablesApiListRequest, +) => + useQuery({ + queryKey: ['customer_downloadables', { ...(parameters || {}) }], + queryFn: () => api.customerPortalDownloadables.list(parameters), + retry: defaultRetry, + }) + +export const useCustomerOrders = ( + api: PolarAPI, + parameters?: CustomerPortalOrdersApiListRequest, +) => + useQuery({ + queryKey: ['customer_orders', { ...(parameters || {}) }], + queryFn: () => api.customerPortalOrders.list(parameters), + retry: defaultRetry, + }) + +export const useCustomerOrderInvoice = (api: PolarAPI) => + useMutation({ + mutationFn: (variables: { id: string }) => + api.customerPortalOrders.invoice(variables), + }) + +export const useCustomerSubscriptions = ( + api: PolarAPI, + parameters?: CustomerPortalSubscriptionsApiListRequest, +) => + useQuery({ + queryKey: ['customer_subscriptions', { ...(parameters || {}) }], + queryFn: () => api.customerPortalSubscriptions.list(parameters), + retry: defaultRetry, + }) + +export const useCustomerUpdateSubscription = (api: PolarAPI) => + useMutation({ + mutationFn: (variables: { + id: string + body: CustomerSubscriptionUpdate + }) => { + return api.customerPortalSubscriptions.update({ + id: variables.id, + body: variables.body, + }) + }, + onSuccess: (_result, _variables, _ctx) => { + queryClient.invalidateQueries({ + queryKey: ['customer_subscriptions'], + }) + }, + }) + +export const useCustomerCancelSubscription = (api: PolarAPI) => + useMutation({ + mutationFn: (variables: { id: string }) => { + return api.customerPortalSubscriptions.cancel(variables) + }, + onSuccess: (_result, _variables, _ctx) => { + queryClient.invalidateQueries({ + queryKey: ['customer_subscriptions'], + }) + }, + }) diff --git a/clients/apps/web/src/hooks/queries/customers.ts b/clients/apps/web/src/hooks/queries/customers.ts new file mode 100644 index 0000000000..7394f43e70 --- /dev/null +++ b/clients/apps/web/src/hooks/queries/customers.ts @@ -0,0 +1,18 @@ +import { api } from '@/utils/api' +import { CustomersApiListRequest } from '@polar-sh/sdk' +import { useQuery } from '@tanstack/react-query' +import { defaultRetry } from './retry' + +export const useCustomers = ( + organizationId: string, + parameters?: Omit, +) => + useQuery({ + queryKey: ['customers', { organizationId, ...(parameters || {}) }], + queryFn: () => + api.customers.list({ + organizationId: organizationId ?? '', + ...(parameters || {}), + }), + retry: defaultRetry, + }) diff --git a/clients/apps/web/src/hooks/queries/downloadables.ts b/clients/apps/web/src/hooks/queries/downloadables.ts deleted file mode 100644 index 8c990cd526..0000000000 --- a/clients/apps/web/src/hooks/queries/downloadables.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { useQuery } from '@tanstack/react-query' - -import { api } from '@/utils/api' -import { - DownloadableRead, - ListResourceDownloadableRead, - UsersDownloadablesApiListRequest, -} from '@polar-sh/sdk' -import { defaultRetry } from './retry' - -export const useUserDownloadables = ( - params?: UsersDownloadablesApiListRequest, -) => - useQuery({ - queryKey: ['user', 'downloadables'], - queryFn: () => api.usersDownloadables.list(params), - retry: defaultRetry, - }) - -export const useDownloadables = ( - benefitId: string, - activeFileIds: string[] = [], -) => - useQuery({ - queryKey: ['user', 'downloadables', benefitId, ...activeFileIds], - queryFn: () => - api.usersDownloadables - .list({ - benefitId, - }) - .then((response: ListResourceDownloadableRead) => { - if (!response.items) { - return response - } - - if (activeFileIds.length < 1) { - return response - } - - let lookup: { [key: string]: DownloadableRead } = {} - const downloadables = response.items.reduce( - (lookup, downloadable) => { - lookup[downloadable.file.id] = downloadable - return lookup - }, - lookup, - ) - // Return in given ID order - const added: { [key: string]: boolean } = {} - const sorted: DownloadableRead[] = [] - activeFileIds.map((id) => { - sorted.push(downloadables[id]) - added[id] = true - }) - response.items.map((item) => { - if (item.file.id in added) { - return - } - sorted.push(item) - }) - - return { - items: sorted, - pagination: response.pagination, - } - }), - retry: defaultRetry, - }) diff --git a/clients/apps/web/src/hooks/queries/dummy_products.ts b/clients/apps/web/src/hooks/queries/dummy_products.ts index f474e05296..f2b3827e19 100644 --- a/clients/apps/web/src/hooks/queries/dummy_products.ts +++ b/clients/apps/web/src/hooks/queries/dummy_products.ts @@ -1,6 +1,6 @@ import { queryClient } from '@/utils/api' import { org } from '@/utils/testdata' -import { BenefitBase, Organization } from '@polar-sh/sdk' +import { Benefit, Organization } from '@polar-sh/sdk' import { useMutation, useQuery } from '@tanstack/react-query' import { defaultRetry } from './retry' @@ -10,7 +10,7 @@ export interface Product { description: string media: string[] price: number - benefits: BenefitBase[] + benefits: Benefit[] organization: Organization created_at: string updated_at: string @@ -79,6 +79,8 @@ export let products: Product[] = [ created_at: new Date().toISOString(), modified_at: null, organization_id: '123', + properties: { note: null }, + is_tax_applicable: true, }, ], media: [ @@ -104,6 +106,11 @@ export let products: Product[] = [ created_at: new Date().toISOString(), modified_at: null, organization_id: '123', + properties: { + repository_owner: 'polarsource', + repository_name: 'polar', + permission: 'pull', + }, }, ], media: [ @@ -129,6 +136,11 @@ export let products: Product[] = [ created_at: new Date().toISOString(), modified_at: null, organization_id: '123', + properties: { + repository_owner: 'polarsource', + repository_name: 'polar', + permission: 'pull', + }, }, { id: '456', @@ -139,6 +151,8 @@ export let products: Product[] = [ created_at: new Date().toISOString(), modified_at: null, organization_id: '123', + properties: { note: null }, + is_tax_applicable: true, }, ], media: [ diff --git a/clients/apps/web/src/hooks/queries/index.ts b/clients/apps/web/src/hooks/queries/index.ts index 4039465015..9ce2312387 100644 --- a/clients/apps/web/src/hooks/queries/index.ts +++ b/clients/apps/web/src/hooks/queries/index.ts @@ -17,11 +17,12 @@ export * from './advertisements' export * from './backoffice' export * from './benefits' export * from './checkout_links' +export * from './customerPortal' +export * from './customers' export * from './customFields' export * from './dashboard' export * from './discord' export * from './discounts' -export * from './downloadables' export * from './files' export * from './funding' export * from './github' diff --git a/clients/apps/web/src/hooks/queries/license_keys.ts b/clients/apps/web/src/hooks/queries/license_keys.ts index f7eb1bcae5..7a7ee3966e 100644 --- a/clients/apps/web/src/hooks/queries/license_keys.ts +++ b/clients/apps/web/src/hooks/queries/license_keys.ts @@ -7,21 +7,6 @@ import { } from '@polar-sh/sdk' import { defaultRetry } from './retry' -interface GetLicenseKeysRequest { - licenseKeyId?: string -} - -export const useLicenseKey = ({ licenseKeyId }: GetLicenseKeysRequest) => - useQuery({ - queryKey: ['user', 'license_key', licenseKeyId], - queryFn: () => - api.usersLicenseKeys.get({ - id: licenseKeyId as string, - }), - retry: defaultRetry, - enabled: !!licenseKeyId, - }) - export const useLicenseKeyUpdate = (organizationId: string) => useMutation({ mutationFn: (update: LicenseKeysApiUpdateRequest) => @@ -33,25 +18,12 @@ export const useLicenseKeyUpdate = (organizationId: string) => }, }) -export const useLicenseKeyDeactivation = (licenseKeyId: string) => - useMutation({ - mutationFn: (opts: { - key: string - organizationId: string - activationId: string - }) => - api.usersLicenseKeys.deactivate({ - body: { - key: opts.key, - organization_id: opts.organizationId, - activation_id: opts.activationId, - }, - }), - onSuccess: async (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'license_key', licenseKeyId], - }) - }, +export const useLicenseKey = (id?: string) => + useQuery({ + queryKey: ['license_keys', id], + queryFn: () => api.licenseKeys.get({ id: id as string }), + retry: defaultRetry, + enabled: !!id, }) export const useOrganizationLicenseKeys = ({ diff --git a/clients/apps/web/src/hooks/queries/user.ts b/clients/apps/web/src/hooks/queries/user.ts index 62d95c4848..faf17b6e87 100644 --- a/clients/apps/web/src/hooks/queries/user.ts +++ b/clients/apps/web/src/hooks/queries/user.ts @@ -1,16 +1,5 @@ import { api, queryClient } from '@/utils/api' -import { - PersonalAccessTokenCreate, - UserAdvertisementCampaignCreate, - UserAdvertisementCampaignUpdate, - UserSubscriptionUpdate, - UsersAdvertisementsApiEnableRequest, - UsersAdvertisementsApiListRequest, - UsersBenefitsApiListRequest, - UsersLicenseKeysApiListRequest, - UsersOrdersApiListRequest, - UsersSubscriptionsApiListRequest, -} from '@polar-sh/sdk' +import { PersonalAccessTokenCreate } from '@polar-sh/sdk' import { useMutation, useQuery } from '@tanstack/react-query' import { defaultRetry } from './retry' @@ -44,141 +33,3 @@ export const useDeletePersonalAccessToken = () => queryClient.invalidateQueries({ queryKey: ['personalAccessTokens'] }) }, }) - -export const useUserSubscriptions = ( - parameters: UsersSubscriptionsApiListRequest = {}, -) => - useQuery({ - queryKey: ['user', 'subscriptions', parameters], - queryFn: () => api.usersSubscriptions.list(parameters), - retry: defaultRetry, - }) - -export const useUserOrders = (parameters: UsersOrdersApiListRequest = {}) => - useQuery({ - queryKey: ['user', 'orders', parameters], - queryFn: () => api.usersOrders.list(parameters), - retry: defaultRetry, - }) - -export const useUserOrderInvoice = () => - useMutation({ - mutationFn: (id: string) => { - return api.usersOrders.invoice({ id }) - }, - }) - -export const useUpdateSubscription = () => - useMutation({ - mutationFn: (variables: { id: string; body: UserSubscriptionUpdate }) => { - return api.usersSubscriptions.update({ - id: variables.id, - body: variables.body, - }) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'subscriptions'], - }) - }, - }) - -export const useCancelSubscription = (id: string) => - useMutation({ - mutationFn: () => { - return api.usersSubscriptions.cancel({ id }) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'subscriptions'], - }) - }, - }) - -export const useUserBenefit = (id?: string) => - useQuery({ - queryKey: ['user', 'benefit', 'id', id], - queryFn: () => api.usersBenefits.get({ id: id ?? '' }), - retry: defaultRetry, - enabled: !!id, - }) - -export const useUserLicenseKeys = ( - parameters: UsersLicenseKeysApiListRequest = {}, -) => - useQuery({ - queryKey: ['user', 'licenseKeys', parameters], - queryFn: () => api.usersLicenseKeys.list(parameters), - retry: defaultRetry, - }) - -export const useUserBenefits = (parameters: UsersBenefitsApiListRequest = {}) => - useQuery({ - queryKey: ['user', 'benefits', parameters], - queryFn: () => api.usersBenefits.list(parameters), - retry: defaultRetry, - }) - -export const useUserAdvertisementCampaigns = ( - parameters: UsersAdvertisementsApiListRequest = {}, -) => - useQuery({ - queryKey: ['user', 'advertisementCampaigns', parameters], - queryFn: () => api.usersAdvertisements.list(parameters), - retry: defaultRetry, - }) - -export const useUserCreateAdvertisementCampaign = () => - useMutation({ - mutationFn: (body: UserAdvertisementCampaignCreate) => { - return api.usersAdvertisements.create({ - body, - }) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'advertisementCampaigns'], - }) - }, - }) - -export const useUserUpdateAdvertisementCampaign = (id: string) => - useMutation({ - mutationFn: (body: UserAdvertisementCampaignUpdate) => { - return api.usersAdvertisements.update({ - id, - body, - }) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'advertisementCampaigns'], - }) - }, - }) - -export const useUserEnableAdvertisementCampaign = () => - useMutation({ - mutationFn: (requestParameters: UsersAdvertisementsApiEnableRequest) => { - return api.usersAdvertisements.enable(requestParameters) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'benefits'], - }) - }, - }) - -export const useUserDeleteAdvertisementCampaign = (id: string) => - useMutation({ - mutationFn: () => { - return api.usersAdvertisements.delete({ - id, - }) - }, - onSuccess: (_result, _variables, _ctx) => { - queryClient.invalidateQueries({ - queryKey: ['user', 'advertisementCampaigns'], - }) - }, - }) diff --git a/clients/apps/web/src/hooks/sse/index.ts b/clients/apps/web/src/hooks/sse/index.ts index b67724b88d..3c19d8dbf9 100644 --- a/clients/apps/web/src/hooks/sse/index.ts +++ b/clients/apps/web/src/hooks/sse/index.ts @@ -1,4 +1,5 @@ import { getServerURL } from '@/utils/api' +import { EventSourcePlus } from 'event-source-plus' import EventEmitter from 'eventemitter3' import { useEffect } from 'react' import { onBenefitGranted, onBenefitRevoked } from './benefits' @@ -16,29 +17,30 @@ const ACTIONS: { const emitter = new EventEmitter() -const useSSE = (streamURL: string): EventEmitter => { +const useSSE = (streamURL: string, token?: string): EventEmitter => { useEffect(() => { - const connection = new EventSource(streamURL, { - withCredentials: true, + const eventSource = new EventSourcePlus(streamURL, { + credentials: 'include', + headers: { ...(token ? { Authorization: `Bearer ${token}` } : {}) }, + }) + + const controller = eventSource.listen({ + onMessage: async (message) => { + const data = JSON.parse(message.data) + const handler = ACTIONS[data.key] + if (handler) { + await handler(data.payload) + } + emitter.emit(data.key, data.payload) + }, }) const cleanup = () => { - connection.close() - } - // TODO: Add types for event. Just want to get the structure - // up and running first before getting stuck in protocol land. - connection.onmessage = async (event) => { - const data = JSON.parse(event.data) - const handler = ACTIONS[data.key] - if (handler) { - await handler(data.payload) - } - emitter.emit(data.key, data.payload) + controller.abort() } - connection.onerror = (_event) => cleanup return cleanup - }, [streamURL]) + }, [streamURL, token]) return emitter } @@ -48,3 +50,8 @@ export const useOrganizationSSE = (organizationId: string) => useSSE(getServerURL(`/v1/stream/organizations/${organizationId}`)) export const useCheckoutClientSSE = (clientSecret: string) => useSSE(getServerURL(`/v1/checkouts/custom/client/${clientSecret}/stream`)) +export const useCustomerSSE = (customerSessionToken?: string) => + useSSE( + getServerURL('/v1/customer-portal/customers/stream'), + customerSessionToken, + ) diff --git a/clients/apps/web/src/utils/api/index.ts b/clients/apps/web/src/utils/api/index.ts index f6fcabc932..af8d4948de 100644 --- a/clients/apps/web/src/utils/api/index.ts +++ b/clients/apps/web/src/utils/api/index.ts @@ -28,6 +28,7 @@ export const buildAPI = (opts: { token?: string }) => export const buildServerSideAPI = ( headers: Headers, cookies: any, + token?: string, ): PolarAPI => { let apiHeaders = {} @@ -57,6 +58,7 @@ export const buildServerSideAPI = ( basePath: getServerURL(), credentials: 'include', headers: apiHeaders, + accessToken: token, }), ) } diff --git a/clients/apps/web/src/utils/api/serverside.ts b/clients/apps/web/src/utils/api/serverside.ts index 6dd39343e5..7377fbcc42 100644 --- a/clients/apps/web/src/utils/api/serverside.ts +++ b/clients/apps/web/src/utils/api/serverside.ts @@ -3,8 +3,8 @@ import { cookies, headers } from 'next/headers' import { cache } from 'react' import { buildServerSideAPI } from '.' -const _getServerSideAPI = (): PolarAPI => { - return buildServerSideAPI(headers(), cookies()) +const _getServerSideAPI = (token?: string): PolarAPI => { + return buildServerSideAPI(headers(), cookies(), token) } // Memoize the API instance for the duration of the request diff --git a/clients/apps/web/src/utils/customerPortal.ts b/clients/apps/web/src/utils/customerPortal.ts new file mode 100644 index 0000000000..2869a6b69b --- /dev/null +++ b/clients/apps/web/src/utils/customerPortal.ts @@ -0,0 +1,41 @@ +import { Organization, PolarAPI, ResponseError } from '@polar-sh/sdk' +import { notFound } from 'next/navigation' +import { cache } from 'react' + +const _getOrganization = async ( + api: PolarAPI, + slug: string, +): Promise => { + try { + return await api.customerPortalOrganizations.get( + { + slug, + }, + { + next: { + revalidate: 600, + tags: [`organizations:${slug}`], + }, + }, + ) + } catch (err) { + if (err instanceof ResponseError && err.response.status === 404) { + return undefined + } + throw err + } +} + +// Tell React to memoize it for the duration of the request +export const getOrganization = cache(_getOrganization) + +export const getOrganizationOrNotFound = async ( + api: PolarAPI, + slug: string, +): Promise => { + const organization = await getOrganization(api, slug) + if (!organization) { + notFound() + } + return organization +} diff --git a/clients/packages/polarkit/package.json b/clients/packages/polarkit/package.json index 2bbb711b41..839942edc4 100644 --- a/clients/packages/polarkit/package.json +++ b/clients/packages/polarkit/package.json @@ -14,6 +14,7 @@ "./components/ui/atoms/countrystatepicker": "./src/components/ui/atoms/CountryStatePicker.tsx", "./components/ui/atoms/datatable": "./src/components/ui/atoms/datatable/index.ts", "./components/ui/atoms/input": "./src/components/ui/atoms/Input.tsx", + "./components/ui/atoms/input-otp": "./src/components/ui/atoms/InputOTP.tsx", "./components/ui/atoms/list": "./src/components/ui/atoms/List.tsx", "./components/ui/atoms/moneyinput": "./src/components/ui/atoms/MoneyInput.tsx", "./components/ui/atoms/percentageinput": "./src/components/ui/atoms/PercentageInput.tsx", @@ -75,6 +76,7 @@ "cmdk": "^1.0.0", "countries-list": "^3.1.1", "date-fns": "^3.6.0", + "input-otp": "^1.4.1", "lucide-react": "^0.461.0", "react": "^18.3.1", "react-day-picker": "^8.10.1", diff --git a/clients/packages/polarkit/src/components/ui/atoms/Avatar.tsx b/clients/packages/polarkit/src/components/ui/atoms/Avatar.tsx index fe16cf2c20..638d58dd9a 100644 --- a/clients/packages/polarkit/src/components/ui/atoms/Avatar.tsx +++ b/clients/packages/polarkit/src/components/ui/atoms/Avatar.tsx @@ -13,32 +13,31 @@ const Avatar = ({ height?: number | undefined width?: number | undefined }) => { - if (avatar_url) { - return ( - /* eslint-disable-next-line @next/next/no-img-element */ - {name} - ) - } - const initials = getInitials(name) return (
    - {initials} + {/* Always add initials below image because Gravatar returns a transparent image if the user does not have a Gravatar account */} +
    + {initials} +
    + {avatar_url && ( + <> + {/* eslint-disable-next-line @next/next/no-img-element */} + {name} + + )}
    ) } diff --git a/clients/packages/polarkit/src/components/ui/atoms/InputOTP.tsx b/clients/packages/polarkit/src/components/ui/atoms/InputOTP.tsx new file mode 100644 index 0000000000..6b56b022b2 --- /dev/null +++ b/clients/packages/polarkit/src/components/ui/atoms/InputOTP.tsx @@ -0,0 +1,8 @@ +import { + InputOTP, + InputOTPGroup, + InputOTPSeparator, + InputOTPSlot, +} from '../input-otp' + +export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } diff --git a/clients/packages/polarkit/src/components/ui/input-otp.tsx b/clients/packages/polarkit/src/components/ui/input-otp.tsx new file mode 100644 index 0000000000..28a5281e4e --- /dev/null +++ b/clients/packages/polarkit/src/components/ui/input-otp.tsx @@ -0,0 +1,71 @@ +"use client" + +import * as React from "react" +import { OTPInput, OTPInputContext } from "input-otp" +import { Dot } from "lucide-react" + +import { cn } from "@polarkit/lib/utils" + +const InputOTP = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, containerClassName, ...props }, ref) => ( + +)) +InputOTP.displayName = "InputOTP" + +const InputOTPGroup = React.forwardRef< + React.ElementRef<"div">, + React.ComponentPropsWithoutRef<"div"> +>(({ className, ...props }, ref) => ( +
    +)) +InputOTPGroup.displayName = "InputOTPGroup" + +const InputOTPSlot = React.forwardRef< + React.ElementRef<"div">, + React.ComponentPropsWithoutRef<"div"> & { index: number } +>(({ index, className, ...props }, ref) => { + const inputOTPContext = React.useContext(OTPInputContext) + const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] + + return ( +
    + {char} + {hasFakeCaret && ( +
    +
    +
    + )} +
    + ) +}) +InputOTPSlot.displayName = "InputOTPSlot" + +const InputOTPSeparator = React.forwardRef< + React.ElementRef<"div">, + React.ComponentPropsWithoutRef<"div"> +>(({ ...props }, ref) => ( +
    + +
    +)) +InputOTPSeparator.displayName = "InputOTPSeparator" + +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } diff --git a/clients/packages/sdk/src/client/.openapi-generator/FILES b/clients/packages/sdk/src/client/.openapi-generator/FILES index 92a94b0373..51b4a13f2e 100644 --- a/clients/packages/sdk/src/client/.openapi-generator/FILES +++ b/clients/packages/sdk/src/client/.openapi-generator/FILES @@ -7,6 +7,16 @@ apis/CheckoutLinksApi.ts apis/CheckoutsApi.ts apis/CheckoutsCustomApi.ts apis/CustomFieldsApi.ts +apis/CustomerPortalBenefitGrantsApi.ts +apis/CustomerPortalCustomerSessionApi.ts +apis/CustomerPortalCustomersApi.ts +apis/CustomerPortalDownloadablesApi.ts +apis/CustomerPortalLicenseKeysApi.ts +apis/CustomerPortalOauthAccountsApi.ts +apis/CustomerPortalOrdersApi.ts +apis/CustomerPortalOrganizationsApi.ts +apis/CustomerPortalSubscriptionsApi.ts +apis/CustomersApi.ts apis/DashboardApi.ts apis/DiscountsApi.ts apis/EmbedsApi.ts @@ -35,13 +45,7 @@ apis/RewardsApi.ts apis/StorefrontsApi.ts apis/SubscriptionsApi.ts apis/TransactionsApi.ts -apis/UsersAdvertisementsApi.ts apis/UsersApi.ts -apis/UsersBenefitsApi.ts -apis/UsersDownloadablesApi.ts -apis/UsersLicenseKeysApi.ts -apis/UsersOrdersApi.ts -apis/UsersSubscriptionsApi.ts apis/WebhooksApi.ts apis/index.ts models/index.ts diff --git a/clients/packages/sdk/src/client/PolarAPI.ts b/clients/packages/sdk/src/client/PolarAPI.ts index 1635ca894e..6513a7b94d 100644 --- a/clients/packages/sdk/src/client/PolarAPI.ts +++ b/clients/packages/sdk/src/client/PolarAPI.ts @@ -35,14 +35,18 @@ import { TransactionsApi, UsersApi, WebhooksApi, - UsersAdvertisementsApi, - UsersBenefitsApi, - UsersDownloadablesApi, - UsersLicenseKeysApi, - UsersOrdersApi, - UsersSubscriptionsApi, LicenseKeysApi, CheckoutLinksApi, + CustomerPortalBenefitGrantsApi, + CustomerPortalCustomerSessionApi, + CustomerPortalCustomersApi, + CustomerPortalDownloadablesApi, + CustomerPortalLicenseKeysApi, + CustomerPortalOauthAccountsApi, + CustomerPortalOrdersApi, + CustomerPortalOrganizationsApi, + CustomerPortalSubscriptionsApi, + CustomersApi, } from '.' export class PolarAPI { @@ -50,6 +54,16 @@ export class PolarAPI { public readonly advertisements: AdvertisementsApi public readonly auth: AuthApi public readonly backoffice: BackofficeApi + public readonly customers: CustomersApi + public readonly customerPortalBenefitGrants: CustomerPortalBenefitGrantsApi + public readonly customerPortalCustomers: CustomerPortalCustomersApi + public readonly customerPortalCustomerSession: CustomerPortalCustomerSessionApi + public readonly customerPortalDownloadables: CustomerPortalDownloadablesApi + public readonly customerPortalLicenseKeys: CustomerPortalLicenseKeysApi + public readonly customerPortalOauthAccounts: CustomerPortalOauthAccountsApi + public readonly customerPortalOrders: CustomerPortalOrdersApi + public readonly customerPortalOrganizations: CustomerPortalOrganizationsApi + public readonly customerPortalSubscriptions: CustomerPortalSubscriptionsApi public readonly legacyCheckouts: CheckoutsApi public readonly checkouts: CheckoutsCustomApi public readonly checkoutLinks: CheckoutLinksApi @@ -80,13 +94,7 @@ export class PolarAPI { public readonly storefronts: StorefrontsApi public readonly subscriptions: SubscriptionsApi public readonly transactions: TransactionsApi - public readonly usersAdvertisements: UsersAdvertisementsApi public readonly users: UsersApi - public readonly usersBenefits: UsersBenefitsApi - public readonly usersDownloadables: UsersDownloadablesApi - public readonly usersLicenseKeys: UsersLicenseKeysApi - public readonly usersOrders: UsersOrdersApi - public readonly usersSubscriptions: UsersSubscriptionsApi public readonly webhooks: WebhooksApi public readonly files: FilesApi @@ -95,6 +103,16 @@ export class PolarAPI { this.advertisements = new AdvertisementsApi(config) this.auth = new AuthApi(config) this.backoffice = new BackofficeApi(config) + this.customers = new CustomersApi(config) + this.customerPortalBenefitGrants = new CustomerPortalBenefitGrantsApi(config) + this.customerPortalCustomers = new CustomerPortalCustomersApi(config) + this.customerPortalCustomerSession = new CustomerPortalCustomerSessionApi(config) + this.customerPortalDownloadables = new CustomerPortalDownloadablesApi(config) + this.customerPortalLicenseKeys = new CustomerPortalLicenseKeysApi(config) + this.customerPortalOauthAccounts = new CustomerPortalOauthAccountsApi(config) + this.customerPortalOrders = new CustomerPortalOrdersApi(config) + this.customerPortalOrganizations = new CustomerPortalOrganizationsApi(config) + this.customerPortalSubscriptions = new CustomerPortalSubscriptionsApi(config) this.legacyCheckouts = new CheckoutsApi(config) this.checkouts = new CheckoutsCustomApi(config) this.checkoutLinks = new CheckoutLinksApi(config) @@ -126,13 +144,7 @@ export class PolarAPI { this.storefronts = new StorefrontsApi(config) this.subscriptions = new SubscriptionsApi(config) this.transactions = new TransactionsApi(config) - this.usersAdvertisements = new UsersAdvertisementsApi(config) this.users = new UsersApi(config) - this.usersBenefits = new UsersBenefitsApi(config) - this.usersDownloadables = new UsersDownloadablesApi(config) - this.usersLicenseKeys = new UsersLicenseKeysApi(config) - this.usersOrders = new UsersOrdersApi(config) - this.usersSubscriptions = new UsersSubscriptionsApi(config) this.webhooks = new WebhooksApi(config) this.files = new FilesApi(config) } diff --git a/clients/packages/sdk/src/client/apis/BenefitsApi.ts b/clients/packages/sdk/src/client/apis/BenefitsApi.ts index 200bf83496..1669031f8e 100644 --- a/clients/packages/sdk/src/client/apis/BenefitsApi.ts +++ b/clients/packages/sdk/src/client/apis/BenefitsApi.ts @@ -19,6 +19,7 @@ import type { BenefitCreate, BenefitTypeFilter, BenefitUpdate, + CustomerIDFilter1, HTTPValidationError, ListResourceBenefit, ListResourceBenefitGrant, @@ -42,8 +43,7 @@ export interface BenefitsApiGetRequest { export interface BenefitsApiGrantsRequest { id: string; isGranted?: boolean; - userId?: string; - githubUserId?: number; + customerId?: CustomerIDFilter1; page?: number; limit?: number; } @@ -214,12 +214,8 @@ export class BenefitsApi extends runtime.BaseAPI { queryParameters['is_granted'] = requestParameters['isGranted']; } - if (requestParameters['userId'] != null) { - queryParameters['user_id'] = requestParameters['userId']; - } - - if (requestParameters['githubUserId'] != null) { - queryParameters['github_user_id'] = requestParameters['githubUserId']; + if (requestParameters['customerId'] != null) { + queryParameters['customer_id'] = requestParameters['customerId']; } if (requestParameters['page'] != null) { diff --git a/clients/packages/sdk/src/client/apis/CheckoutsCustomApi.ts b/clients/packages/sdk/src/client/apis/CheckoutsCustomApi.ts index 0ba504c34b..d08f119b6b 100644 --- a/clients/packages/sdk/src/client/apis/CheckoutsCustomApi.ts +++ b/clients/packages/sdk/src/client/apis/CheckoutsCustomApi.ts @@ -20,6 +20,7 @@ import type { CheckoutCreate, CheckoutCreatePublic, CheckoutPublic, + CheckoutPublicConfirmed, CheckoutSortProperty, CheckoutUpdate, CheckoutUpdatePublic, @@ -78,7 +79,7 @@ export class CheckoutsCustomApi extends runtime.BaseAPI { * Confirm a checkout session by client secret. Orders and subscriptions will be processed. * Confirm Checkout Session from Client */ - async clientConfirmRaw(requestParameters: CheckoutsCustomApiClientConfirmRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async clientConfirmRaw(requestParameters: CheckoutsCustomApiClientConfirmRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { if (requestParameters['clientSecret'] == null) { throw new runtime.RequiredError( 'clientSecret', @@ -99,6 +100,14 @@ export class CheckoutsCustomApi extends runtime.BaseAPI { headerParameters['Content-Type'] = 'application/json'; + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } const response = await this.request({ path: `/v1/checkouts/custom/client/{client_secret}/confirm`.replace(`{${"client_secret"}}`, encodeURIComponent(String(requestParameters['clientSecret']))), method: 'POST', @@ -114,7 +123,7 @@ export class CheckoutsCustomApi extends runtime.BaseAPI { * Confirm a checkout session by client secret. Orders and subscriptions will be processed. * Confirm Checkout Session from Client */ - async clientConfirm(requestParameters: CheckoutsCustomApiClientConfirmRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + async clientConfirm(requestParameters: CheckoutsCustomApiClientConfirmRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { const response = await this.clientConfirmRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalBenefitGrantsApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalBenefitGrantsApi.ts new file mode 100644 index 0000000000..21f2a86b3d --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalBenefitGrantsApi.ts @@ -0,0 +1,251 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + BenefitIDFilter2, + BenefitTypeFilter, + CheckoutIDFilter, + CustomerBenefitGrant, + CustomerBenefitGrantSortProperty, + CustomerBenefitGrantUpdate, + HTTPValidationError, + ListResourceCustomerBenefitGrant, + NotPermitted, + OrderIDFilter, + OrganizationIDFilter, + ResourceNotFound, + SubscriptionIDFilter, +} from '../models/index'; + +export interface CustomerPortalBenefitGrantsApiGetRequest { + id: string; +} + +export interface CustomerPortalBenefitGrantsApiListRequest { + type?: BenefitTypeFilter; + benefitId?: BenefitIDFilter2; + organizationId?: OrganizationIDFilter; + checkoutId?: CheckoutIDFilter; + orderId?: OrderIDFilter; + subscriptionId?: SubscriptionIDFilter; + page?: number; + limit?: number; + sorting?: Array; +} + +export interface CustomerPortalBenefitGrantsApiUpdateRequest { + id: string; + body: CustomerBenefitGrantUpdate; +} + +/** + * + */ +export class CustomerPortalBenefitGrantsApi extends runtime.BaseAPI { + + /** + * Get a benefit grant by ID for the authenticated customer or user. + * Get Benefit Grant + */ + async getRaw(requestParameters: CustomerPortalBenefitGrantsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/benefit-grants/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a benefit grant by ID for the authenticated customer or user. + * Get Benefit Grant + */ + async get(requestParameters: CustomerPortalBenefitGrantsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List benefits grants of the authenticated customer or user. + * List Benefit Grants + */ + async listRaw(requestParameters: CustomerPortalBenefitGrantsApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['type'] != null) { + queryParameters['type'] = requestParameters['type']; + } + + if (requestParameters['benefitId'] != null) { + queryParameters['benefit_id'] = requestParameters['benefitId']; + } + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['checkoutId'] != null) { + queryParameters['checkout_id'] = requestParameters['checkoutId']; + } + + if (requestParameters['orderId'] != null) { + queryParameters['order_id'] = requestParameters['orderId']; + } + + if (requestParameters['subscriptionId'] != null) { + queryParameters['subscription_id'] = requestParameters['subscriptionId']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + if (requestParameters['sorting'] != null) { + queryParameters['sorting'] = requestParameters['sorting']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/benefit-grants/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List benefits grants of the authenticated customer or user. + * List Benefit Grants + */ + async list(requestParameters: CustomerPortalBenefitGrantsApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Update a benefit grant for the authenticated customer or user. + * Update Benefit Grant + */ + async updateRaw(requestParameters: CustomerPortalBenefitGrantsApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling update().' + ); + } + + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling update().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/benefit-grants/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'PATCH', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Update a benefit grant for the authenticated customer or user. + * Update Benefit Grant + */ + async update(requestParameters: CustomerPortalBenefitGrantsApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalCustomerSessionApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalCustomerSessionApi.ts new file mode 100644 index 0000000000..3ee559b3a9 --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalCustomerSessionApi.ts @@ -0,0 +1,113 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + CustomerSessionCodeAuthenticateRequest, + CustomerSessionCodeAuthenticateResponse, + CustomerSessionCodeRequest, + HTTPValidationError, +} from '../models/index'; + +export interface CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionAuthenticateRequest { + body: CustomerSessionCodeAuthenticateRequest; +} + +export interface CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionRequestRequest { + body: CustomerSessionCodeRequest; +} + +/** + * + */ +export class CustomerPortalCustomerSessionApi extends runtime.BaseAPI { + + /** + * Customer Portal.Customer Session.Authenticate + */ + async customerPortalCustomerSessionAuthenticateRaw(requestParameters: CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionAuthenticateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling customerPortalCustomerSessionAuthenticate().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v1/customer-portal/customer-session/authenticate`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Customer Portal.Customer Session.Authenticate + */ + async customerPortalCustomerSessionAuthenticate(requestParameters: CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionAuthenticateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.customerPortalCustomerSessionAuthenticateRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Customer Portal.Customer Session.Request + */ + async customerPortalCustomerSessionRequestRaw(requestParameters: CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionRequestRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling customerPortalCustomerSessionRequest().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v1/customer-portal/customer-session/request`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + } + + /** + * Customer Portal.Customer Session.Request + */ + async customerPortalCustomerSessionRequest(requestParameters: CustomerPortalCustomerSessionApiCustomerPortalCustomerSessionRequestRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.customerPortalCustomerSessionRequestRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalCustomersApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalCustomersApi.ts new file mode 100644 index 0000000000..056ee00787 --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalCustomersApi.ts @@ -0,0 +1,83 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + CustomerPortalCustomer, + HTTPValidationError, + ResourceNotFound, +} from '../models/index'; + +export interface CustomerPortalCustomersApiGetRequest { + id: string; +} + +/** + * + */ +export class CustomerPortalCustomersApi extends runtime.BaseAPI { + + /** + * Get a customer by ID for the authenticated customer or user. + * Get Customer + */ + async getRaw(requestParameters: CustomerPortalCustomersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/customers/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a customer by ID for the authenticated customer or user. + * Get Customer + */ + async get(requestParameters: CustomerPortalCustomersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalDownloadablesApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalDownloadablesApi.ts new file mode 100644 index 0000000000..70fd104043 --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalDownloadablesApi.ts @@ -0,0 +1,135 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + BenefitIDFilter1, + HTTPValidationError, + ListResourceDownloadableRead, + OrganizationIDFilter, +} from '../models/index'; + +export interface CustomerPortalDownloadablesApiCustomerPortalDownloadablesGetRequest { + token: string; +} + +export interface CustomerPortalDownloadablesApiListRequest { + organizationId?: OrganizationIDFilter; + benefitId?: BenefitIDFilter1; + page?: number; + limit?: number; +} + +/** + * + */ +export class CustomerPortalDownloadablesApi extends runtime.BaseAPI { + + /** + * Get Downloadable + */ + async customerPortalDownloadablesGetRaw(requestParameters: CustomerPortalDownloadablesApiCustomerPortalDownloadablesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['token'] == null) { + throw new runtime.RequiredError( + 'token', + 'Required parameter "token" was null or undefined when calling customerPortalDownloadablesGet().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/customer-portal/downloadables/{token}`.replace(`{${"token"}}`, encodeURIComponent(String(requestParameters['token']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + } + + /** + * Get Downloadable + */ + async customerPortalDownloadablesGet(requestParameters: CustomerPortalDownloadablesApiCustomerPortalDownloadablesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.customerPortalDownloadablesGetRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List Downloadables + */ + async listRaw(requestParameters: CustomerPortalDownloadablesApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['benefitId'] != null) { + queryParameters['benefit_id'] = requestParameters['benefitId']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/downloadables/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List Downloadables + */ + async list(requestParameters: CustomerPortalDownloadablesApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalLicenseKeysApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalLicenseKeysApi.ts new file mode 100644 index 0000000000..065212db89 --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalLicenseKeysApi.ts @@ -0,0 +1,282 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + HTTPValidationError, + LicenseKeyActivate, + LicenseKeyActivationRead, + LicenseKeyDeactivate, + LicenseKeyValidate, + LicenseKeyWithActivations, + ListResourceLicenseKeyRead, + NotPermitted, + OrganizationIDFilter, + ResourceNotFound, + Unauthorized, + ValidatedLicenseKey, +} from '../models/index'; + +export interface CustomerPortalLicenseKeysApiActivateRequest { + body: LicenseKeyActivate; +} + +export interface CustomerPortalLicenseKeysApiDeactivateRequest { + body: LicenseKeyDeactivate; +} + +export interface CustomerPortalLicenseKeysApiGetRequest { + id: string; +} + +export interface CustomerPortalLicenseKeysApiListRequest { + organizationId?: OrganizationIDFilter; + benefitId?: string; + page?: number; + limit?: number; +} + +export interface CustomerPortalLicenseKeysApiValidateRequest { + body: LicenseKeyValidate; +} + +/** + * + */ +export class CustomerPortalLicenseKeysApi extends runtime.BaseAPI { + + /** + * Activate a license key instance. + * Activate License Key + */ + async activateRaw(requestParameters: CustomerPortalLicenseKeysApiActivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling activate().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v1/customer-portal/license-keys/activate`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Activate a license key instance. + * Activate License Key + */ + async activate(requestParameters: CustomerPortalLicenseKeysApiActivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.activateRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Deactivate a license key instance. + * Deactivate License Key + */ + async deactivateRaw(requestParameters: CustomerPortalLicenseKeysApiDeactivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling deactivate().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v1/customer-portal/license-keys/deactivate`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Deactivate a license key instance. + * Deactivate License Key + */ + async deactivate(requestParameters: CustomerPortalLicenseKeysApiDeactivateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.deactivateRaw(requestParameters, initOverrides); + } + + /** + * Get a license key. + * Get License Key + */ + async getRaw(requestParameters: CustomerPortalLicenseKeysApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/license-keys/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a license key. + * Get License Key + */ + async get(requestParameters: CustomerPortalLicenseKeysApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List License Keys + */ + async listRaw(requestParameters: CustomerPortalLicenseKeysApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['benefitId'] != null) { + queryParameters['benefit_id'] = requestParameters['benefitId']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/license-keys/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List License Keys + */ + async list(requestParameters: CustomerPortalLicenseKeysApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Validate a license key. + * Validate License Key + */ + async validateRaw(requestParameters: CustomerPortalLicenseKeysApiValidateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling validate().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v1/customer-portal/license-keys/validate`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Validate a license key. + * Validate License Key + */ + async validate(requestParameters: CustomerPortalLicenseKeysApiValidateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.validateRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalOauthAccountsApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalOauthAccountsApi.ts new file mode 100644 index 0000000000..fc32004388 --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalOauthAccountsApi.ts @@ -0,0 +1,165 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + AuthorizeResponse, + CustomerOAuthPlatform, + HTTPValidationError, +} from '../models/index'; + +export interface CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsAuthorizeRequest { + platform: CustomerOAuthPlatform; + customerId: string; + returnTo?: string; +} + +export interface CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsCallbackRequest { + state: string; + code?: string; + error?: string; +} + +/** + * + */ +export class CustomerPortalOauthAccountsApi extends runtime.BaseAPI { + + /** + * Customer Portal.Oauth Accounts.Authorize + */ + async customerPortalOauthAccountsAuthorizeRaw(requestParameters: CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsAuthorizeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['platform'] == null) { + throw new runtime.RequiredError( + 'platform', + 'Required parameter "platform" was null or undefined when calling customerPortalOauthAccountsAuthorize().' + ); + } + + if (requestParameters['customerId'] == null) { + throw new runtime.RequiredError( + 'customerId', + 'Required parameter "customerId" was null or undefined when calling customerPortalOauthAccountsAuthorize().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['platform'] != null) { + queryParameters['platform'] = requestParameters['platform']; + } + + if (requestParameters['customerId'] != null) { + queryParameters['customer_id'] = requestParameters['customerId']; + } + + if (requestParameters['returnTo'] != null) { + queryParameters['return_to'] = requestParameters['returnTo']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/oauth-accounts/authorize`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Customer Portal.Oauth Accounts.Authorize + */ + async customerPortalOauthAccountsAuthorize(requestParameters: CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsAuthorizeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.customerPortalOauthAccountsAuthorizeRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Customer Portal.Oauth Accounts.Callback + */ + async customerPortalOauthAccountsCallbackRaw(requestParameters: CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsCallbackRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['state'] == null) { + throw new runtime.RequiredError( + 'state', + 'Required parameter "state" was null or undefined when calling customerPortalOauthAccountsCallback().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['state'] != null) { + queryParameters['state'] = requestParameters['state']; + } + + if (requestParameters['code'] != null) { + queryParameters['code'] = requestParameters['code']; + } + + if (requestParameters['error'] != null) { + queryParameters['error'] = requestParameters['error']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/oauth-accounts/callback`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + } + + /** + * Customer Portal.Oauth Accounts.Callback + */ + async customerPortalOauthAccountsCallback(requestParameters: CustomerPortalOauthAccountsApiCustomerPortalOauthAccountsCallbackRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.customerPortalOauthAccountsCallbackRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalOrdersApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalOrdersApi.ts new file mode 100644 index 0000000000..fdc65488fa --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalOrdersApi.ts @@ -0,0 +1,232 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + CustomerOrder, + CustomerOrderInvoice, + CustomerOrderSortProperty, + HTTPValidationError, + ListResourceCustomerOrder, + OrganizationIDFilter, + ProductIDFilter, + ProductPriceTypeFilter, + ResourceNotFound, + SubscriptionIDFilter, +} from '../models/index'; + +export interface CustomerPortalOrdersApiGetRequest { + id: string; +} + +export interface CustomerPortalOrdersApiInvoiceRequest { + id: string; +} + +export interface CustomerPortalOrdersApiListRequest { + organizationId?: OrganizationIDFilter; + productId?: ProductIDFilter; + productPriceType?: ProductPriceTypeFilter; + subscriptionId?: SubscriptionIDFilter; + query?: string; + page?: number; + limit?: number; + sorting?: Array; +} + +/** + * + */ +export class CustomerPortalOrdersApi extends runtime.BaseAPI { + + /** + * Get an order by ID for the authenticated customer or user. + * Get Order + */ + async getRaw(requestParameters: CustomerPortalOrdersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/orders/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get an order by ID for the authenticated customer or user. + * Get Order + */ + async get(requestParameters: CustomerPortalOrdersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Get an order\'s invoice data. + * Get Order Invoice + */ + async invoiceRaw(requestParameters: CustomerPortalOrdersApiInvoiceRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling invoice().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/orders/{id}/invoice`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get an order\'s invoice data. + * Get Order Invoice + */ + async invoice(requestParameters: CustomerPortalOrdersApiInvoiceRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.invoiceRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List orders of the authenticated customer or user. + * List Orders + */ + async listRaw(requestParameters: CustomerPortalOrdersApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['productId'] != null) { + queryParameters['product_id'] = requestParameters['productId']; + } + + if (requestParameters['productPriceType'] != null) { + queryParameters['product_price_type'] = requestParameters['productPriceType']; + } + + if (requestParameters['subscriptionId'] != null) { + queryParameters['subscription_id'] = requestParameters['subscriptionId']; + } + + if (requestParameters['query'] != null) { + queryParameters['query'] = requestParameters['query']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + if (requestParameters['sorting'] != null) { + queryParameters['sorting'] = requestParameters['sorting']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/orders/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List orders of the authenticated customer or user. + * List Orders + */ + async list(requestParameters: CustomerPortalOrdersApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalOrganizationsApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalOrganizationsApi.ts new file mode 100644 index 0000000000..d4a837c3db --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalOrganizationsApi.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + HTTPValidationError, + Organization, + ResourceNotFound, +} from '../models/index'; + +export interface CustomerPortalOrganizationsApiGetRequest { + slug: string; +} + +/** + * + */ +export class CustomerPortalOrganizationsApi extends runtime.BaseAPI { + + /** + * Get a customer portal\'s organization by slug. + * Get Organization + */ + async getRaw(requestParameters: CustomerPortalOrganizationsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['slug'] == null) { + throw new runtime.RequiredError( + 'slug', + 'Required parameter "slug" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/customer-portal/organizations/{slug}`.replace(`{${"slug"}}`, encodeURIComponent(String(requestParameters['slug']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a customer portal\'s organization by slug. + * Get Organization + */ + async get(requestParameters: CustomerPortalOrganizationsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomerPortalSubscriptionsApi.ts b/clients/packages/sdk/src/client/apis/CustomerPortalSubscriptionsApi.ts new file mode 100644 index 0000000000..e0fbd94f8d --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomerPortalSubscriptionsApi.ts @@ -0,0 +1,292 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + AlreadyCanceledSubscription, + CustomerSubscription, + CustomerSubscriptionSortProperty, + CustomerSubscriptionUpdate, + HTTPValidationError, + ListResourceCustomerSubscription, + OrganizationIDFilter, + ProductIDFilter, + ResourceNotFound, +} from '../models/index'; + +export interface CustomerPortalSubscriptionsApiCancelRequest { + id: string; +} + +export interface CustomerPortalSubscriptionsApiGetRequest { + id: string; +} + +export interface CustomerPortalSubscriptionsApiListRequest { + organizationId?: OrganizationIDFilter; + productId?: ProductIDFilter; + active?: boolean; + query?: string; + page?: number; + limit?: number; + sorting?: Array; +} + +export interface CustomerPortalSubscriptionsApiUpdateRequest { + id: string; + body: CustomerSubscriptionUpdate; +} + +/** + * + */ +export class CustomerPortalSubscriptionsApi extends runtime.BaseAPI { + + /** + * Cancel a subscription of the authenticated customer or user. + * Cancel Subscription + */ + async cancelRaw(requestParameters: CustomerPortalSubscriptionsApiCancelRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling cancel().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/subscriptions/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Cancel a subscription of the authenticated customer or user. + * Cancel Subscription + */ + async cancel(requestParameters: CustomerPortalSubscriptionsApiCancelRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.cancelRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Get a subscription for the authenticated customer or user. + * Get Subscription + */ + async getRaw(requestParameters: CustomerPortalSubscriptionsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/subscriptions/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a subscription for the authenticated customer or user. + * Get Subscription + */ + async get(requestParameters: CustomerPortalSubscriptionsApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List subscriptions of the authenticated customer or user. + * List Subscriptions + */ + async listRaw(requestParameters: CustomerPortalSubscriptionsApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['productId'] != null) { + queryParameters['product_id'] = requestParameters['productId']; + } + + if (requestParameters['active'] != null) { + queryParameters['active'] = requestParameters['active']; + } + + if (requestParameters['query'] != null) { + queryParameters['query'] = requestParameters['query']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + if (requestParameters['sorting'] != null) { + queryParameters['sorting'] = requestParameters['sorting']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/subscriptions/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List subscriptions of the authenticated customer or user. + * List Subscriptions + */ + async list(requestParameters: CustomerPortalSubscriptionsApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Update a subscription of the authenticated customer or user. + * Update Subscription + */ + async updateRaw(requestParameters: CustomerPortalSubscriptionsApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling update().' + ); + } + + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling update().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("customer_session", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customer-portal/subscriptions/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'PATCH', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Update a subscription of the authenticated customer or user. + * Update Subscription + */ + async update(requestParameters: CustomerPortalSubscriptionsApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/CustomersApi.ts b/clients/packages/sdk/src/client/apis/CustomersApi.ts new file mode 100644 index 0000000000..c8e7a41f3e --- /dev/null +++ b/clients/packages/sdk/src/client/apis/CustomersApi.ts @@ -0,0 +1,298 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Polar API + * Read the docs at https://docs.polar.sh/api + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import type { + Customer, + CustomerCreate, + CustomerSortProperty, + CustomerUpdate, + HTTPValidationError, + ListResourceCustomer, + OrganizationIDFilter, + ResourceNotFound, +} from '../models/index'; + +export interface CustomersApiCreateRequest { + body: CustomerCreate; +} + +export interface CustomersApiDeleteRequest { + id: string; +} + +export interface CustomersApiGetRequest { + id: string; +} + +export interface CustomersApiListRequest { + organizationId?: OrganizationIDFilter; + query?: string; + page?: number; + limit?: number; + sorting?: Array; +} + +export interface CustomersApiUpdateRequest { + id: string; + body: CustomerUpdate; +} + +/** + * + */ +export class CustomersApi extends runtime.BaseAPI { + + /** + * Create a customer. + * Create Customer + */ + async createRaw(requestParameters: CustomersApiCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling create().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customers/`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Create a customer. + * Create Customer + */ + async create(requestParameters: CustomersApiCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.createRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Delete a customer. Immediately cancels any active subscriptions and revokes any active benefits. + * Delete Customer + */ + async deleteRaw(requestParameters: CustomersApiDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling delete().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customers/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Delete a customer. Immediately cancels any active subscriptions and revokes any active benefits. + * Delete Customer + */ + async delete(requestParameters: CustomersApiDeleteRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.deleteRaw(requestParameters, initOverrides); + } + + /** + * Get a customer by ID. + * Get Customer + */ + async getRaw(requestParameters: CustomersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling get().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customers/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get a customer by ID. + * Get Customer + */ + async get(requestParameters: CustomersApiGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * List customers. + * List Customers + */ + async listRaw(requestParameters: CustomersApiListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const queryParameters: any = {}; + + if (requestParameters['organizationId'] != null) { + queryParameters['organization_id'] = requestParameters['organizationId']; + } + + if (requestParameters['query'] != null) { + queryParameters['query'] = requestParameters['query']; + } + + if (requestParameters['page'] != null) { + queryParameters['page'] = requestParameters['page']; + } + + if (requestParameters['limit'] != null) { + queryParameters['limit'] = requestParameters['limit']; + } + + if (requestParameters['sorting'] != null) { + queryParameters['sorting'] = requestParameters['sorting']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customers/`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * List customers. + * List Customers + */ + async list(requestParameters: CustomersApiListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.listRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Update a customer. + * Update Customer + */ + async updateRaw(requestParameters: CustomersApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['id'] == null) { + throw new runtime.RequiredError( + 'id', + 'Required parameter "id" was null or undefined when calling update().' + ); + } + + if (requestParameters['body'] == null) { + throw new runtime.RequiredError( + 'body', + 'Required parameter "body" was null or undefined when calling update().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("pat", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/v1/customers/{id}`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + method: 'PATCH', + headers: headerParameters, + query: queryParameters, + body: requestParameters['body'], + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Update a customer. + * Update Customer + */ + async update(requestParameters: CustomersApiUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/clients/packages/sdk/src/client/apis/LicenseKeysApi.ts b/clients/packages/sdk/src/client/apis/LicenseKeysApi.ts index 0cee609368..937a7590ab 100644 --- a/clients/packages/sdk/src/client/apis/LicenseKeysApi.ts +++ b/clients/packages/sdk/src/client/apis/LicenseKeysApi.ts @@ -15,7 +15,7 @@ import * as runtime from '../runtime'; import type { - BenefitIDFilter2, + BenefitIDFilter1, HTTPValidationError, LicenseKeyActivationRead, LicenseKeyRead, @@ -38,7 +38,7 @@ export interface LicenseKeysApiGetActivationRequest { export interface LicenseKeysApiListRequest { organizationId?: OrganizationIDFilter; - benefitId?: BenefitIDFilter2; + benefitId?: BenefitIDFilter1; page?: number; limit?: number; } diff --git a/clients/packages/sdk/src/client/apis/OrdersApi.ts b/clients/packages/sdk/src/client/apis/OrdersApi.ts index 9684024d72..782f26e35a 100644 --- a/clients/packages/sdk/src/client/apis/OrdersApi.ts +++ b/clients/packages/sdk/src/client/apis/OrdersApi.ts @@ -15,6 +15,7 @@ import * as runtime from '../runtime'; import type { + CustomerIDFilter, DiscountIDFilter1, HTTPValidationError, ListResourceOrder, @@ -25,7 +26,6 @@ import type { ProductIDFilter, ProductPriceTypeFilter, ResourceNotFound, - UserIDFilter, } from '../models/index'; export interface OrdersApiGetRequest { @@ -41,7 +41,7 @@ export interface OrdersApiListRequest { productId?: ProductIDFilter; productPriceType?: ProductPriceTypeFilter; discountId?: DiscountIDFilter1; - userId?: UserIDFilter; + customerId?: CustomerIDFilter; page?: number; limit?: number; sorting?: Array; @@ -161,8 +161,8 @@ export class OrdersApi extends runtime.BaseAPI { queryParameters['discount_id'] = requestParameters['discountId']; } - if (requestParameters['userId'] != null) { - queryParameters['user_id'] = requestParameters['userId']; + if (requestParameters['customerId'] != null) { + queryParameters['customer_id'] = requestParameters['customerId']; } if (requestParameters['page'] != null) { diff --git a/clients/packages/sdk/src/client/apis/ProductsApi.ts b/clients/packages/sdk/src/client/apis/ProductsApi.ts index 191549fed4..4b57660373 100644 --- a/clients/packages/sdk/src/client/apis/ProductsApi.ts +++ b/clients/packages/sdk/src/client/apis/ProductsApi.ts @@ -15,7 +15,7 @@ import * as runtime from '../runtime'; import type { - BenefitIDFilter1, + BenefitIDFilter, HTTPValidationError, ListResourceProduct, NotPermitted, @@ -41,7 +41,7 @@ export interface ProductsApiListRequest { query?: string; isArchived?: boolean; isRecurring?: boolean; - benefitId?: BenefitIDFilter1; + benefitId?: BenefitIDFilter; page?: number; limit?: number; sorting?: Array; diff --git a/clients/packages/sdk/src/client/apis/SubscriptionsApi.ts b/clients/packages/sdk/src/client/apis/SubscriptionsApi.ts index e69df34d4d..df4b77053b 100644 --- a/clients/packages/sdk/src/client/apis/SubscriptionsApi.ts +++ b/clients/packages/sdk/src/client/apis/SubscriptionsApi.ts @@ -15,6 +15,7 @@ import * as runtime from '../runtime'; import type { + CustomerIDFilter, DiscountIDFilter, HTTPValidationError, ListResourceSubscription, @@ -31,6 +32,7 @@ export interface SubscriptionsApiExportRequest { export interface SubscriptionsApiListRequest { organizationId?: OrganizationIDFilter; productId?: ProductIDFilter; + customerId?: CustomerIDFilter; discountId?: DiscountIDFilter; active?: boolean; page?: number; @@ -102,6 +104,10 @@ export class SubscriptionsApi extends runtime.BaseAPI { queryParameters['product_id'] = requestParameters['productId']; } + if (requestParameters['customerId'] != null) { + queryParameters['customer_id'] = requestParameters['customerId']; + } + if (requestParameters['discountId'] != null) { queryParameters['discount_id'] = requestParameters['discountId']; } diff --git a/clients/packages/sdk/src/client/apis/TransactionsApi.ts b/clients/packages/sdk/src/client/apis/TransactionsApi.ts index 256fca6186..79ef8c5c87 100644 --- a/clients/packages/sdk/src/client/apis/TransactionsApi.ts +++ b/clients/packages/sdk/src/client/apis/TransactionsApi.ts @@ -49,8 +49,9 @@ export interface TransactionsApiLookupTransactionRequest { export interface TransactionsApiSearchTransactionsRequest { type?: TransactionType; accountId?: string; - paymentUserId?: string; + paymentCustomerId?: string; paymentOrganizationId?: string; + paymentUserId?: string; excludePlatformFees?: boolean; page?: number; limit?: number; @@ -300,14 +301,18 @@ export class TransactionsApi extends runtime.BaseAPI { queryParameters['account_id'] = requestParameters['accountId']; } - if (requestParameters['paymentUserId'] != null) { - queryParameters['payment_user_id'] = requestParameters['paymentUserId']; + if (requestParameters['paymentCustomerId'] != null) { + queryParameters['payment_customer_id'] = requestParameters['paymentCustomerId']; } if (requestParameters['paymentOrganizationId'] != null) { queryParameters['payment_organization_id'] = requestParameters['paymentOrganizationId']; } + if (requestParameters['paymentUserId'] != null) { + queryParameters['payment_user_id'] = requestParameters['paymentUserId']; + } + if (requestParameters['excludePlatformFees'] != null) { queryParameters['exclude_platform_fees'] = requestParameters['excludePlatformFees']; } diff --git a/clients/packages/sdk/src/client/apis/index.ts b/clients/packages/sdk/src/client/apis/index.ts index 0356288947..7370326bc0 100644 --- a/clients/packages/sdk/src/client/apis/index.ts +++ b/clients/packages/sdk/src/client/apis/index.ts @@ -9,6 +9,16 @@ export * from './CheckoutLinksApi'; export * from './CheckoutsApi'; export * from './CheckoutsCustomApi'; export * from './CustomFieldsApi'; +export * from './CustomerPortalBenefitGrantsApi'; +export * from './CustomerPortalCustomerSessionApi'; +export * from './CustomerPortalCustomersApi'; +export * from './CustomerPortalDownloadablesApi'; +export * from './CustomerPortalLicenseKeysApi'; +export * from './CustomerPortalOauthAccountsApi'; +export * from './CustomerPortalOrdersApi'; +export * from './CustomerPortalOrganizationsApi'; +export * from './CustomerPortalSubscriptionsApi'; +export * from './CustomersApi'; export * from './DashboardApi'; export * from './DiscountsApi'; export * from './EmbedsApi'; @@ -38,10 +48,4 @@ export * from './StorefrontsApi'; export * from './SubscriptionsApi'; export * from './TransactionsApi'; export * from './UsersApi'; -export * from './UsersAdvertisementsApi'; -export * from './UsersBenefitsApi'; -export * from './UsersDownloadablesApi'; -export * from './UsersLicenseKeysApi'; -export * from './UsersOrdersApi'; -export * from './UsersSubscriptionsApi'; export * from './WebhooksApi'; diff --git a/clients/packages/sdk/src/client/models/index.ts b/clients/packages/sdk/src/client/models/index.ts index e991ceb335..d30d2b9564 100644 --- a/clients/packages/sdk/src/client/models/index.ts +++ b/clients/packages/sdk/src/client/models/index.ts @@ -1159,6 +1159,19 @@ export interface AuthorizeOrganization { */ avatar_url: string | null; } +/** + * + * @export + * @interface AuthorizeResponse + */ +export interface AuthorizeResponse { + /** + * + * @type {string} + * @memberof AuthorizeResponse + */ + url: string; +} /** * * @export @@ -1300,6 +1313,8 @@ export const AvailableScope = { FILESWRITE: 'files:write', SUBSCRIPTIONSREAD: 'subscriptions:read', SUBSCRIPTIONSWRITE: 'subscriptions:write', + CUSTOMERSREAD: 'customers:read', + CUSTOMERSWRITE: 'customers:write', ORDERSREAD: 'orders:read', METRICSREAD: 'metrics:read', WEBHOOKSREAD: 'webhooks:read', @@ -1311,14 +1326,8 @@ export const AvailableScope = { REPOSITORIESWRITE: 'repositories:write', ISSUESREAD: 'issues:read', ISSUESWRITE: 'issues:write', - USERBENEFITSREAD: 'user:benefits:read', - USERORDERSREAD: 'user:orders:read', - USERSUBSCRIPTIONSREAD: 'user:subscriptions:read', - USERSUBSCRIPTIONSWRITE: 'user:subscriptions:write', - USERDOWNLOADABLESREAD: 'user:downloadables:read', - USERLICENSE_KEYSREAD: 'user:license_keys:read', - USERADVERTISEMENT_CAMPAIGNSREAD: 'user:advertisement_campaigns:read', - USERADVERTISEMENT_CAMPAIGNSWRITE: 'user:advertisement_campaigns:write' + CUSTOMER_PORTALREAD: 'customer_portal:read', + CUSTOMER_PORTALWRITE: 'customer_portal:write' } as const; export type AvailableScope = typeof AvailableScope[keyof typeof AvailableScope]; @@ -1803,12 +1812,6 @@ export interface BenefitAdsSubscriber { * @memberof BenefitAdsSubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitAdsSubscriber - */ - grants: Array; /** * * @type {Organization} @@ -2071,7 +2074,7 @@ export interface BenefitCustomCreateProperties { } /** * @type BenefitCustomCreatePropertiesNote - * Private note to be shared with users who have this benefit granted. + * Private note to be shared with customers who have this benefit granted. * @export */ export type BenefitCustomCreatePropertiesNote = string; @@ -2143,12 +2146,6 @@ export interface BenefitCustomSubscriber { * @memberof BenefitCustomSubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitCustomSubscriber - */ - grants: Array; /** * * @type {Organization} @@ -2432,12 +2429,6 @@ export interface BenefitDiscordSubscriber { * @memberof BenefitDiscordSubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitDiscordSubscriber - */ - grants: Array; /** * * @type {Organization} @@ -2713,12 +2704,6 @@ export interface BenefitDownloadablesSubscriber { * @memberof BenefitDownloadablesSubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitDownloadablesSubscriber - */ - grants: Array; /** * * @type {Organization} @@ -2911,23 +2896,17 @@ export type BenefitGitHubRepositoryCreateTypeEnum = typeof BenefitGitHubReposito */ export interface BenefitGitHubRepositoryCreateProperties { /** - * - * @type {string} - * @memberof BenefitGitHubRepositoryCreateProperties - */ - repository_id?: string | null; - /** - * + * The owner of the repository. * @type {string} * @memberof BenefitGitHubRepositoryCreateProperties */ - repository_owner?: string | null; + repository_owner: string; /** - * + * The name of the repository. * @type {string} * @memberof BenefitGitHubRepositoryCreateProperties */ - repository_name?: string | null; + repository_name: string; /** * The permission level to grant. Read more about roles and their permissions on [GitHub documentation](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization#permissions-for-each-role). * @type {string} @@ -2955,12 +2934,6 @@ export type BenefitGitHubRepositoryCreatePropertiesPermissionEnum = typeof Benef * @interface BenefitGitHubRepositoryProperties */ export interface BenefitGitHubRepositoryProperties { - /** - * - * @type {string} - * @memberof BenefitGitHubRepositoryProperties - */ - repository_id: string | null; /** * The owner of the repository. * @type {string} @@ -3048,12 +3021,6 @@ export interface BenefitGitHubRepositorySubscriber { * @memberof BenefitGitHubRepositorySubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitGitHubRepositorySubscriber - */ - grants: Array; /** * * @type {Organization} @@ -3192,102 +3159,30 @@ export interface BenefitGrant { */ order_id: string | null; /** - * The ID of the user concerned by this grant. - * @type {string} - * @memberof BenefitGrant - */ - user_id: string; - /** - * The ID of the benefit concerned by this grant. + * The ID of the customer concerned by this grant. * @type {string} * @memberof BenefitGrant */ - benefit_id: string; - /** - * - * @type {Properties} - * @memberof BenefitGrant - */ - properties: Properties; -} -/** - * - * @export - * @interface BenefitGrantAds - */ -export interface BenefitGrantAds { - /** - * Creation timestamp of the object. - * @type {string} - * @memberof BenefitGrantAds - */ - created_at: string; - /** - * - * @type {string} - * @memberof BenefitGrantAds - */ - modified_at: string | null; - /** - * The ID of the grant. - * @type {string} - * @memberof BenefitGrantAds - */ - id: string; - /** - * - * @type {string} - * @memberof BenefitGrantAds - */ - granted_at?: string | null; - /** - * Whether the benefit is granted. - * @type {boolean} - * @memberof BenefitGrantAds - */ - is_granted: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantAds - */ - revoked_at?: string | null; - /** - * Whether the benefit is revoked. - * @type {boolean} - * @memberof BenefitGrantAds - */ - is_revoked: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantAds - */ - subscription_id: string | null; + customer_id: string; /** * * @type {string} - * @memberof BenefitGrantAds - */ - order_id: string | null; - /** - * The ID of the user concerned by this grant. - * @type {string} - * @memberof BenefitGrantAds + * @memberof BenefitGrant + * @deprecated */ user_id: string; /** * The ID of the benefit concerned by this grant. * @type {string} - * @memberof BenefitGrantAds + * @memberof BenefitGrant */ benefit_id: string; /** * - * @type {BenefitGrantAdsSubscriberProperties} - * @memberof BenefitGrantAds + * @type {Properties} + * @memberof BenefitGrant */ - properties: BenefitGrantAdsSubscriberProperties; + properties: Properties; } /** * @@ -3302,19 +3197,6 @@ export interface BenefitGrantAdsProperties { */ advertisement_campaign_id: string; } -/** - * - * @export - * @interface BenefitGrantAdsSubscriberProperties - */ -export interface BenefitGrantAdsSubscriberProperties { - /** - * - * @type {string} - * @memberof BenefitGrantAdsSubscriberProperties - */ - advertisement_campaign_id?: string | null; -} /** * * @export @@ -3326,19 +3208,19 @@ export interface BenefitGrantDiscordProperties { * @type {string} * @memberof BenefitGrantDiscordProperties */ - guild_id?: string; + account_id?: string; /** * * @type {string} * @memberof BenefitGrantDiscordProperties */ - role_id?: string; + guild_id?: string; /** * * @type {string} * @memberof BenefitGrantDiscordProperties */ - account_id?: string; + role_id?: string; } /** * @@ -3364,7 +3246,7 @@ export interface BenefitGrantGitHubRepositoryProperties { * @type {string} * @memberof BenefitGrantGitHubRepositoryProperties */ - repository_id?: string | null; + account_id?: string; /** * * @type {string} @@ -3401,364 +3283,219 @@ export type BenefitGrantGitHubRepositoryPropertiesPermissionEnum = typeof Benefi /** * * @export - * @interface BenefitGrantLicenseKeys + * @interface BenefitGrantLicenseKeysProperties + */ +export interface BenefitGrantLicenseKeysProperties { + /** + * + * @type {string} + * @memberof BenefitGrantLicenseKeysProperties + */ + license_key_id?: string; + /** + * + * @type {string} + * @memberof BenefitGrantLicenseKeysProperties + */ + display_key?: string; +} +/** + * + * @export + * @interface BenefitGrantWebhook */ -export interface BenefitGrantLicenseKeys { +export interface BenefitGrantWebhook { /** * Creation timestamp of the object. * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ created_at: string; /** * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ modified_at: string | null; /** * The ID of the grant. * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ id: string; /** * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ granted_at?: string | null; /** * Whether the benefit is granted. * @type {boolean} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ is_granted: boolean; /** * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ revoked_at?: string | null; /** * Whether the benefit is revoked. * @type {boolean} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ is_revoked: boolean; /** * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ subscription_id: string | null; /** * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ order_id: string | null; /** - * The ID of the user concerned by this grant. + * The ID of the customer concerned by this grant. + * @type {string} + * @memberof BenefitGrantWebhook + */ + customer_id: string; + /** + * * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook + * @deprecated */ user_id: string; /** * The ID of the benefit concerned by this grant. * @type {string} - * @memberof BenefitGrantLicenseKeys + * @memberof BenefitGrantWebhook */ benefit_id: string; /** * - * @type {BenefitGrantLicenseKeysProperties} - * @memberof BenefitGrantLicenseKeys + * @type {Properties} + * @memberof BenefitGrantWebhook */ - properties: BenefitGrantLicenseKeysProperties; + properties: Properties; + /** + * + * @type {Benefit} + * @memberof BenefitGrantWebhook + */ + benefit: Benefit; + /** + * + * @type {PreviousProperties} + * @memberof BenefitGrantWebhook + */ + previous_properties?: PreviousProperties | null; +} +/** + * @type BenefitIDFilter + * Filter products granting specific benefit. + * @export + */ +export type BenefitIDFilter = Array | string; + +/** + * @type BenefitIDFilter1 + * Filter by benefit ID. + * @export + */ +export type BenefitIDFilter1 = Array | string; + +/** + * @type BenefitIDFilter2 + * Filter by benefit ID. + * @export + */ +export type BenefitIDFilter2 = Array | string; + +/** + * + * @export + * @interface BenefitLicenseKeyActivationProperties + */ +export interface BenefitLicenseKeyActivationProperties { + /** + * + * @type {number} + * @memberof BenefitLicenseKeyActivationProperties + */ + limit: number; + /** + * + * @type {boolean} + * @memberof BenefitLicenseKeyActivationProperties + */ + enable_customer_admin: boolean; } /** * * @export - * @interface BenefitGrantLicenseKeysProperties + * @interface BenefitLicenseKeyExpirationProperties */ -export interface BenefitGrantLicenseKeysProperties { +export interface BenefitLicenseKeyExpirationProperties { /** * - * @type {string} - * @memberof BenefitGrantLicenseKeysProperties + * @type {number} + * @memberof BenefitLicenseKeyExpirationProperties */ - license_key_id?: string; + ttl: number; /** * * @type {string} - * @memberof BenefitGrantLicenseKeysProperties + * @memberof BenefitLicenseKeyExpirationProperties */ - display_key?: string; + timeframe: BenefitLicenseKeyExpirationPropertiesTimeframeEnum; } + + +/** + * @export + */ +export const BenefitLicenseKeyExpirationPropertiesTimeframeEnum = { + YEAR: 'year', + MONTH: 'month', + DAY: 'day' +} as const; +export type BenefitLicenseKeyExpirationPropertiesTimeframeEnum = typeof BenefitLicenseKeyExpirationPropertiesTimeframeEnum[keyof typeof BenefitLicenseKeyExpirationPropertiesTimeframeEnum]; + /** * * @export - * @interface BenefitGrantSubscriber + * @interface BenefitLicenseKeys */ -export interface BenefitGrantSubscriber { +export interface BenefitLicenseKeys { /** * Creation timestamp of the object. * @type {string} - * @memberof BenefitGrantSubscriber + * @memberof BenefitLicenseKeys */ created_at: string; /** * * @type {string} - * @memberof BenefitGrantSubscriber + * @memberof BenefitLicenseKeys */ modified_at: string | null; /** - * The ID of the grant. + * The ID of the benefit. * @type {string} - * @memberof BenefitGrantSubscriber + * @memberof BenefitLicenseKeys */ id: string; /** * * @type {string} - * @memberof BenefitGrantSubscriber - */ - granted_at?: string | null; - /** - * Whether the benefit is granted. - * @type {boolean} - * @memberof BenefitGrantSubscriber - */ - is_granted: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantSubscriber - */ - revoked_at?: string | null; - /** - * Whether the benefit is revoked. - * @type {boolean} - * @memberof BenefitGrantSubscriber - */ - is_revoked: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantSubscriber - */ - subscription_id: string | null; - /** - * - * @type {string} - * @memberof BenefitGrantSubscriber - */ - order_id: string | null; - /** - * The ID of the user concerned by this grant. - * @type {string} - * @memberof BenefitGrantSubscriber - */ - user_id: string; - /** - * The ID of the benefit concerned by this grant. - * @type {string} - * @memberof BenefitGrantSubscriber - */ - benefit_id: string; -} -/** - * - * @export - * @interface BenefitGrantWebhook - */ -export interface BenefitGrantWebhook { - /** - * Creation timestamp of the object. - * @type {string} - * @memberof BenefitGrantWebhook - */ - created_at: string; - /** - * - * @type {string} - * @memberof BenefitGrantWebhook - */ - modified_at: string | null; - /** - * The ID of the grant. - * @type {string} - * @memberof BenefitGrantWebhook - */ - id: string; - /** - * - * @type {string} - * @memberof BenefitGrantWebhook - */ - granted_at?: string | null; - /** - * Whether the benefit is granted. - * @type {boolean} - * @memberof BenefitGrantWebhook - */ - is_granted: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantWebhook - */ - revoked_at?: string | null; - /** - * Whether the benefit is revoked. - * @type {boolean} - * @memberof BenefitGrantWebhook - */ - is_revoked: boolean; - /** - * - * @type {string} - * @memberof BenefitGrantWebhook - */ - subscription_id: string | null; - /** - * - * @type {string} - * @memberof BenefitGrantWebhook - */ - order_id: string | null; - /** - * The ID of the user concerned by this grant. - * @type {string} - * @memberof BenefitGrantWebhook - */ - user_id: string; - /** - * The ID of the benefit concerned by this grant. - * @type {string} - * @memberof BenefitGrantWebhook - */ - benefit_id: string; - /** - * - * @type {Properties} - * @memberof BenefitGrantWebhook - */ - properties: Properties; - /** - * - * @type {Benefit} - * @memberof BenefitGrantWebhook - */ - benefit: Benefit; - /** - * - * @type {PreviousProperties} - * @memberof BenefitGrantWebhook - */ - previous_properties?: PreviousProperties | null; -} -/** - * @type BenefitIDFilter - * Filter by given benefit ID. - * @export - */ -export type BenefitIDFilter = Array | string; - -/** - * @type BenefitIDFilter1 - * Filter products granting specific benefit. - * @export - */ -export type BenefitIDFilter1 = Array | string; - -/** - * @type BenefitIDFilter2 - * Filter by benefit ID. - * @export - */ -export type BenefitIDFilter2 = Array | string; - -/** - * - * @export - * @interface BenefitLicenseKeyActivationProperties - */ -export interface BenefitLicenseKeyActivationProperties { - /** - * - * @type {number} - * @memberof BenefitLicenseKeyActivationProperties - */ - limit: number; - /** - * - * @type {boolean} - * @memberof BenefitLicenseKeyActivationProperties - */ - enable_user_admin: boolean; -} -/** - * - * @export - * @interface BenefitLicenseKeyExpirationProperties - */ -export interface BenefitLicenseKeyExpirationProperties { - /** - * - * @type {number} - * @memberof BenefitLicenseKeyExpirationProperties - */ - ttl: number; - /** - * - * @type {string} - * @memberof BenefitLicenseKeyExpirationProperties - */ - timeframe: BenefitLicenseKeyExpirationPropertiesTimeframeEnum; -} - - -/** - * @export - */ -export const BenefitLicenseKeyExpirationPropertiesTimeframeEnum = { - YEAR: 'year', - MONTH: 'month', - DAY: 'day' -} as const; -export type BenefitLicenseKeyExpirationPropertiesTimeframeEnum = typeof BenefitLicenseKeyExpirationPropertiesTimeframeEnum[keyof typeof BenefitLicenseKeyExpirationPropertiesTimeframeEnum]; - -/** - * - * @export - * @interface BenefitLicenseKeys - */ -export interface BenefitLicenseKeys { - /** - * Creation timestamp of the object. - * @type {string} - * @memberof BenefitLicenseKeys - */ - created_at: string; - /** - * - * @type {string} - * @memberof BenefitLicenseKeys - */ - modified_at: string | null; - /** - * The ID of the benefit. - * @type {string} - * @memberof BenefitLicenseKeys - */ - id: string; - /** - * - * @type {string} - * @memberof BenefitLicenseKeys + * @memberof BenefitLicenseKeys */ type: BenefitLicenseKeysTypeEnum; /** @@ -3959,12 +3696,6 @@ export interface BenefitLicenseKeysSubscriber { * @memberof BenefitLicenseKeysSubscriber */ organization_id: string; - /** - * - * @type {Array} - * @memberof BenefitLicenseKeysSubscriber - */ - grants: Array; /** * * @type {Organization} @@ -4054,96 +3785,6 @@ export const BenefitLicenseKeysUpdateTypeEnum = { } as const; export type BenefitLicenseKeysUpdateTypeEnum = typeof BenefitLicenseKeysUpdateTypeEnum[keyof typeof BenefitLicenseKeysUpdateTypeEnum]; -/** - * - * @export - * @interface BenefitPreconditionErrorNotification - */ -export interface BenefitPreconditionErrorNotification { - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotification - */ - id: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotification - */ - created_at: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotification - */ - type: BenefitPreconditionErrorNotificationTypeEnum; - /** - * - * @type {BenefitPreconditionErrorNotificationPayload} - * @memberof BenefitPreconditionErrorNotification - */ - payload: BenefitPreconditionErrorNotificationPayload; -} - - -/** - * @export - */ -export const BenefitPreconditionErrorNotificationTypeEnum = { - BENEFIT_PRECONDITION_ERROR_NOTIFICATION: 'BenefitPreconditionErrorNotification' -} as const; -export type BenefitPreconditionErrorNotificationTypeEnum = typeof BenefitPreconditionErrorNotificationTypeEnum[keyof typeof BenefitPreconditionErrorNotificationTypeEnum]; - -/** - * - * @export - * @interface BenefitPreconditionErrorNotificationPayload - */ -export interface BenefitPreconditionErrorNotificationPayload { - /** - * - * @type {object} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - extra_context?: object; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - subject_template: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - body_template: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - scope_name: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - benefit_id: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - benefit_description: string; - /** - * - * @type {string} - * @memberof BenefitPreconditionErrorNotificationPayload - */ - organization_name: string; -} /** * @@ -4719,6 +4360,13 @@ export interface CheckoutDiscountPercentageRepeatDuration { } +/** + * @type CheckoutIDFilter + * Filter by checkout ID. + * @export + */ +export type CheckoutIDFilter = Array | string; + /** * A checkout session. * @export @@ -5227,6 +4875,12 @@ export interface CheckoutPriceCreate { * @memberof CheckoutPriceCreate */ amount?: number | null; + /** + * + * @type {string} + * @memberof CheckoutPriceCreate + */ + customer_id?: string | null; /** * Name of the customer. * @type {string} @@ -5419,6 +5073,12 @@ export interface CheckoutProductCreate { * @memberof CheckoutProductCreate */ amount?: number | null; + /** + * + * @type {string} + * @memberof CheckoutProductCreate + */ + customer_id?: string | null; /** * Name of the customer. * @type {string} @@ -5715,6 +5375,254 @@ export interface CheckoutPublic { } +/** + * Checkout session data retrieved using the client secret after confirmation. + * + * It contains a customer session token to retrieve order information + * right after the checkout. + * @export + * @interface CheckoutPublicConfirmed + */ +export interface CheckoutPublicConfirmed { + /** + * Creation timestamp of the object. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + created_at: string; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + id: string; + /** + * Key-value object storing custom field values. + * @type {object} + * @memberof CheckoutPublicConfirmed + */ + custom_field_data?: object; + /** + * + * @type {PolarEnumsPaymentProcessor} + * @memberof CheckoutPublicConfirmed + */ + payment_processor: PolarEnumsPaymentProcessor; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + status: CheckoutPublicConfirmedStatusEnum; + /** + * Client secret used to update and complete the checkout session from the client. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + client_secret: string; + /** + * URL where the customer can access the checkout session. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + url: string; + /** + * Expiration date and time of the checkout session. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + expires_at: string; + /** + * URL where the customer will be redirected after a successful payment. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + success_url: string; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + embed_origin: string | null; + /** + * Amount to pay in cents. Only useful for custom prices, it'll be ignored for fixed and free prices. + * @type {number} + * @memberof CheckoutPublicConfirmed + */ + amount: number | null; + /** + * + * @type {number} + * @memberof CheckoutPublicConfirmed + */ + tax_amount: number | null; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + currency: string | null; + /** + * + * @type {number} + * @memberof CheckoutPublicConfirmed + */ + subtotal_amount: number | null; + /** + * + * @type {number} + * @memberof CheckoutPublicConfirmed + */ + total_amount: number | null; + /** + * ID of the product to checkout. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + product_id: string; + /** + * ID of the product price to checkout. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + product_price_id: string; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + discount_id: string | null; + /** + * Whether to allow the customer to apply discount codes. If you apply a discount through `discount_id`, it'll still be applied, but the customer won't be able to change it. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + allow_discount_codes: boolean; + /** + * Whether the discount is applicable to the checkout. Typically, free and custom prices are not discountable. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + is_discount_applicable: boolean; + /** + * Whether the product price is free, regardless of discounts. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + is_free_product_price: boolean; + /** + * Whether the checkout requires payment, e.g. in case of free products or discounts that cover the total amount. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + is_payment_required: boolean; + /** + * Whether the checkout requires setting up a payment method, regardless of the amount, e.g. subscriptions that have first free cycles. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + is_payment_setup_required: boolean; + /** + * Whether the checkout requires a payment form, whether because of a payment or payment method setup. + * @type {boolean} + * @memberof CheckoutPublicConfirmed + */ + is_payment_form_required: boolean; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_id: string | null; + /** + * Name of the customer. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_name: string | null; + /** + * Email address of the customer. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_email: string | null; + /** + * IP address of the customer. Used to detect tax location. + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_ip_address: string | null; + /** + * + * @type {Address} + * @memberof CheckoutPublicConfirmed + */ + customer_billing_address: Address | null; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_tax_id: string | null; + /** + * + * @type {object} + * @memberof CheckoutPublicConfirmed + */ + payment_processor_metadata: object; + /** + * + * @type {CheckoutProduct} + * @memberof CheckoutPublicConfirmed + */ + product: CheckoutProduct; + /** + * + * @type {ProductPrice} + * @memberof CheckoutPublicConfirmed + */ + product_price: ProductPrice; + /** + * + * @type {CheckoutDiscount} + * @memberof CheckoutPublicConfirmed + */ + discount: CheckoutDiscount | null; + /** + * + * @type {Organization} + * @memberof CheckoutPublicConfirmed + */ + organization: Organization; + /** + * + * @type {Array} + * @memberof CheckoutPublicConfirmed + */ + attached_custom_fields: Array; + /** + * + * @type {string} + * @memberof CheckoutPublicConfirmed + */ + customer_session_token: string; +} + + +/** + * @export + */ +export const CheckoutPublicConfirmedStatusEnum = { + CONFIRMED: 'confirmed' +} as const; +export type CheckoutPublicConfirmedStatusEnum = typeof CheckoutPublicConfirmedStatusEnum[keyof typeof CheckoutPublicConfirmedStatusEnum]; + /** * @@ -7138,11619 +7046,13011 @@ export const CustomFieldUpdateTextTypeEnum = { export type CustomFieldUpdateTextTypeEnum = typeof CustomFieldUpdateTextTypeEnum[keyof typeof CustomFieldUpdateTextTypeEnum]; /** - * + * A customer in an organization. * @export * @interface Customer */ export interface Customer { /** - * + * Creation timestamp of the object. * @type {string} * @memberof Customer */ - public_name: string; + created_at: string; /** * * @type {string} * @memberof Customer */ - github_username: string | null; + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof Customer + */ + id: string; + /** + * + * @type {{ [key: string]: MetadataValue; }} + * @memberof Customer + */ + metadata: { [key: string]: MetadataValue; }; /** * * @type {string} * @memberof Customer */ - avatar_url: string | null; -} -/** - * - * @export - * @interface Customers - */ -export interface Customers { + email: string; /** * - * @type {number} - * @memberof Customers + * @type {boolean} + * @memberof Customer */ - total: number; + email_verified: boolean; /** * - * @type {Array} - * @memberof Customers + * @type {string} + * @memberof Customer */ - customers: Array; -} -/** - * - * @export - * @interface DiscordGuild - */ -export interface DiscordGuild { + name: string | null; + /** + * + * @type {Address} + * @memberof Customer + */ + billing_address: Address | null; + /** + * + * @type {Array} + * @memberof Customer + */ + tax_id: Array | null; /** * * @type {string} - * @memberof DiscordGuild + * @memberof Customer */ - name: string; + organization_id: string; /** * - * @type {Array} - * @memberof DiscordGuild + * @type {string} + * @memberof Customer */ - roles: Array; + readonly avatar_url: string; } +/** + * @type CustomerBenefitGrant + * @export + */ +export type CustomerBenefitGrant = CustomerBenefitGrantAds | CustomerBenefitGrantCustom | CustomerBenefitGrantDiscord | CustomerBenefitGrantDownloadables | CustomerBenefitGrantGitHubRepository | CustomerBenefitGrantLicenseKeys; + /** * * @export - * @interface DiscordGuildRole + * @interface CustomerBenefitGrantAds */ -export interface DiscordGuildRole { +export interface CustomerBenefitGrantAds { + /** + * Creation timestamp of the object. + * @type {string} + * @memberof CustomerBenefitGrantAds + */ + created_at: string; /** * * @type {string} - * @memberof DiscordGuildRole + * @memberof CustomerBenefitGrantAds + */ + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof CustomerBenefitGrantAds */ id: string; /** * * @type {string} - * @memberof DiscordGuildRole + * @memberof CustomerBenefitGrantAds */ - name: string; + granted_at: string | null; /** * - * @type {number} - * @memberof DiscordGuildRole + * @type {string} + * @memberof CustomerBenefitGrantAds */ - position: number; + revoked_at: string | null; /** * - * @type {boolean} - * @memberof DiscordGuildRole + * @type {string} + * @memberof CustomerBenefitGrantAds */ - is_polar_bot: boolean; + customer_id: string; /** * * @type {string} - * @memberof DiscordGuildRole + * @memberof CustomerBenefitGrantAds */ - color: string; + benefit_id: string; + /** + * + * @type {string} + * @memberof CustomerBenefitGrantAds + */ + subscription_id: string | null; + /** + * + * @type {string} + * @memberof CustomerBenefitGrantAds + */ + order_id: string | null; + /** + * + * @type {boolean} + * @memberof CustomerBenefitGrantAds + */ + is_granted: boolean; + /** + * + * @type {boolean} + * @memberof CustomerBenefitGrantAds + */ + is_revoked: boolean; + /** + * + * @type {BenefitAdsSubscriber} + * @memberof CustomerBenefitGrantAds + */ + benefit: BenefitAdsSubscriber; + /** + * + * @type {BenefitGrantAdsProperties} + * @memberof CustomerBenefitGrantAds + */ + properties: BenefitGrantAdsProperties; } /** - * @type Discount - * - * @export - */ -export type Discount = DiscountFixedOnceForeverDuration | DiscountFixedRepeatDuration | DiscountPercentageOnceForeverDuration | DiscountPercentageRepeatDuration; -/** - * @type DiscountCreate * * @export + * @interface CustomerBenefitGrantAdsUpdate */ -export type DiscountCreate = DiscountFixedOnceForeverDurationCreate | DiscountFixedRepeatDurationCreate | DiscountPercentageOnceForeverDurationCreate | DiscountPercentageRepeatDurationCreate; +export interface CustomerBenefitGrantAdsUpdate { + /** + * + * @type {string} + * @memberof CustomerBenefitGrantAdsUpdate + */ + benefit_type: CustomerBenefitGrantAdsUpdateBenefitTypeEnum; +} + /** - * * @export */ -export const DiscountDuration = { - ONCE: 'once', - FOREVER: 'forever', - REPEATING: 'repeating' +export const CustomerBenefitGrantAdsUpdateBenefitTypeEnum = { + ADS: 'ads' } as const; -export type DiscountDuration = typeof DiscountDuration[keyof typeof DiscountDuration]; +export type CustomerBenefitGrantAdsUpdateBenefitTypeEnum = typeof CustomerBenefitGrantAdsUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantAdsUpdateBenefitTypeEnum]; /** - * Schema for a fixed amount discount that is applied once or forever. + * * @export - * @interface DiscountFixedOnceForeverDuration + * @interface CustomerBenefitGrantCustom */ -export interface DiscountFixedOnceForeverDuration { - /** - * - * @type {DiscountDuration} - * @memberof DiscountFixedOnceForeverDuration - */ - duration: DiscountDuration; - /** - * - * @type {DiscountType} - * @memberof DiscountFixedOnceForeverDuration - */ - type: DiscountType; - /** - * - * @type {number} - * @memberof DiscountFixedOnceForeverDuration - */ - amount: number; - /** - * - * @type {string} - * @memberof DiscountFixedOnceForeverDuration - */ - currency: string; +export interface CustomerBenefitGrantCustom { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ created_at: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountFixedOnceForeverDuration - */ - metadata: { [key: string]: MetadataValue; }; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ - name: string; + granted_at: string | null; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ - code: string | null; + revoked_at: string | null; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ - starts_at: string | null; + customer_id: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ - ends_at: string | null; + benefit_id: string; /** * - * @type {number} - * @memberof DiscountFixedOnceForeverDuration - */ - max_redemptions: number | null; - /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountFixedOnceForeverDuration + * @type {string} + * @memberof CustomerBenefitGrantCustom */ - redemptions_count: number; + subscription_id: string | null; /** - * The organization ID. + * * @type {string} - * @memberof DiscountFixedOnceForeverDuration + * @memberof CustomerBenefitGrantCustom */ - organization_id: string; + order_id: string | null; /** * - * @type {Array} - * @memberof DiscountFixedOnceForeverDuration + * @type {boolean} + * @memberof CustomerBenefitGrantCustom */ - products: Array; -} - - -/** - * - * @export - * @interface DiscountFixedOnceForeverDurationBase - */ -export interface DiscountFixedOnceForeverDurationBase { + is_granted: boolean; /** * - * @type {DiscountDuration} - * @memberof DiscountFixedOnceForeverDurationBase + * @type {boolean} + * @memberof CustomerBenefitGrantCustom */ - duration: DiscountDuration; + is_revoked: boolean; /** * - * @type {DiscountType} - * @memberof DiscountFixedOnceForeverDurationBase + * @type {BenefitCustomSubscriber} + * @memberof CustomerBenefitGrantCustom */ - type: DiscountType; + benefit: BenefitCustomSubscriber; /** * - * @type {number} - * @memberof DiscountFixedOnceForeverDurationBase + * @type {object} + * @memberof CustomerBenefitGrantCustom */ - amount: number; + properties: object; +} +/** + * + * @export + * @interface CustomerBenefitGrantCustomUpdate + */ +export interface CustomerBenefitGrantCustomUpdate { /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantCustomUpdate */ - currency: string; + benefit_type: CustomerBenefitGrantCustomUpdateBenefitTypeEnum; +} + + +/** + * @export + */ +export const CustomerBenefitGrantCustomUpdateBenefitTypeEnum = { + CUSTOM: 'custom' +} as const; +export type CustomerBenefitGrantCustomUpdateBenefitTypeEnum = typeof CustomerBenefitGrantCustomUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantCustomUpdateBenefitTypeEnum]; + +/** + * + * @export + * @interface CustomerBenefitGrantDiscord + */ +export interface CustomerBenefitGrantDiscord { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ created_at: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountFixedOnceForeverDurationBase + * @type {string} + * @memberof CustomerBenefitGrantDiscord */ - metadata: { [key: string]: MetadataValue; }; + granted_at: string | null; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ - name: string; + revoked_at: string | null; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ - code: string | null; + customer_id: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ - starts_at: string | null; + benefit_id: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * @memberof CustomerBenefitGrantDiscord */ - ends_at: string | null; + subscription_id: string | null; /** * - * @type {number} - * @memberof DiscountFixedOnceForeverDurationBase + * @type {string} + * @memberof CustomerBenefitGrantDiscord */ - max_redemptions: number | null; + order_id: string | null; /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountFixedOnceForeverDurationBase + * + * @type {boolean} + * @memberof CustomerBenefitGrantDiscord */ - redemptions_count: number; + is_granted: boolean; /** - * The organization ID. - * @type {string} - * @memberof DiscountFixedOnceForeverDurationBase + * + * @type {boolean} + * @memberof CustomerBenefitGrantDiscord */ - organization_id: string; + is_revoked: boolean; + /** + * + * @type {BenefitDiscordSubscriber} + * @memberof CustomerBenefitGrantDiscord + */ + benefit: BenefitDiscordSubscriber; + /** + * + * @type {BenefitGrantDiscordProperties} + * @memberof CustomerBenefitGrantDiscord + */ + properties: BenefitGrantDiscordProperties; } - - /** - * Schema to create a fixed amount discount that is applied once or forever. + * * @export - * @interface DiscountFixedOnceForeverDurationCreate + * @interface CustomerBenefitGrantDiscordPropertiesUpdate */ -export interface DiscountFixedOnceForeverDurationCreate { +export interface CustomerBenefitGrantDiscordPropertiesUpdate { /** * - * @type {DiscountDuration} - * @memberof DiscountFixedOnceForeverDurationCreate + * @type {string} + * @memberof CustomerBenefitGrantDiscordPropertiesUpdate */ - duration: DiscountDuration; + account_id: string; +} +/** + * + * @export + * @interface CustomerBenefitGrantDiscordUpdate + */ +export interface CustomerBenefitGrantDiscordUpdate { /** * - * @type {DiscountType} - * @memberof DiscountFixedOnceForeverDurationCreate + * @type {string} + * @memberof CustomerBenefitGrantDiscordUpdate */ - type: DiscountType; + benefit_type: CustomerBenefitGrantDiscordUpdateBenefitTypeEnum; /** - * Fixed amount to discount from the invoice total. - * @type {number} - * @memberof DiscountFixedOnceForeverDurationCreate + * + * @type {CustomerBenefitGrantDiscordPropertiesUpdate} + * @memberof CustomerBenefitGrantDiscordUpdate */ - amount: number; + properties: CustomerBenefitGrantDiscordPropertiesUpdate; +} + + +/** + * @export + */ +export const CustomerBenefitGrantDiscordUpdateBenefitTypeEnum = { + DISCORD: 'discord' +} as const; +export type CustomerBenefitGrantDiscordUpdateBenefitTypeEnum = typeof CustomerBenefitGrantDiscordUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantDiscordUpdateBenefitTypeEnum]; + +/** + * + * @export + * @interface CustomerBenefitGrantDownloadables + */ +export interface CustomerBenefitGrantDownloadables { /** - * The currency. Currently, only `usd` is supported. + * Creation timestamp of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - currency?: string; + created_at: string; /** - * Key-value object allowing you to store additional information. - * - * The key must be a string with a maximum length of **40 characters**. - * The value must be either: - * - * * A string with a maximum length of **500 characters** - * * An integer - * * A boolean * - * You can store up to **50 key-value pairs**. - * @type {{ [key: string]: MetadataValue1; }} - * @memberof DiscountFixedOnceForeverDurationCreate + * @type {string} + * @memberof CustomerBenefitGrantDownloadables */ - metadata?: { [key: string]: MetadataValue1; }; + modified_at: string | null; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * The ID of the object. * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - name: string; + id: string; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - code?: string | null; + granted_at: string | null; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - starts_at?: string | null; + revoked_at: string | null; /** * * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - ends_at?: string | null; + customer_id: string; /** * - * @type {number} - * @memberof DiscountFixedOnceForeverDurationCreate + * @type {string} + * @memberof CustomerBenefitGrantDownloadables */ - max_redemptions?: number | null; + benefit_id: string; /** - * List of product IDs the discount can be applied to. - * @type {Array} - * @memberof DiscountFixedOnceForeverDurationCreate + * + * @type {string} + * @memberof CustomerBenefitGrantDownloadables */ - products?: Array | null; + subscription_id: string | null; /** - * The organization ID. + * * @type {string} - * @memberof DiscountFixedOnceForeverDurationCreate + * @memberof CustomerBenefitGrantDownloadables */ - organization_id?: string | null; -} - - -/** - * Schema for a fixed amount discount that is applied on every invoice - * for a certain number of months. - * @export - * @interface DiscountFixedRepeatDuration - */ -export interface DiscountFixedRepeatDuration { + order_id: string | null; /** * - * @type {DiscountDuration} - * @memberof DiscountFixedRepeatDuration + * @type {boolean} + * @memberof CustomerBenefitGrantDownloadables */ - duration: DiscountDuration; + is_granted: boolean; /** * - * @type {number} - * @memberof DiscountFixedRepeatDuration + * @type {boolean} + * @memberof CustomerBenefitGrantDownloadables */ - duration_in_months: number; + is_revoked: boolean; /** * - * @type {DiscountType} - * @memberof DiscountFixedRepeatDuration + * @type {BenefitDownloadablesSubscriber} + * @memberof CustomerBenefitGrantDownloadables */ - type: DiscountType; + benefit: BenefitDownloadablesSubscriber; /** * - * @type {number} - * @memberof DiscountFixedRepeatDuration + * @type {BenefitGrantDownloadablesProperties} + * @memberof CustomerBenefitGrantDownloadables */ - amount: number; + properties: BenefitGrantDownloadablesProperties; +} +/** + * + * @export + * @interface CustomerBenefitGrantDownloadablesUpdate + */ +export interface CustomerBenefitGrantDownloadablesUpdate { /** * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantDownloadablesUpdate */ - currency: string; + benefit_type: CustomerBenefitGrantDownloadablesUpdateBenefitTypeEnum; +} + + +/** + * @export + */ +export const CustomerBenefitGrantDownloadablesUpdateBenefitTypeEnum = { + DOWNLOADABLES: 'downloadables' +} as const; +export type CustomerBenefitGrantDownloadablesUpdateBenefitTypeEnum = typeof CustomerBenefitGrantDownloadablesUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantDownloadablesUpdateBenefitTypeEnum]; + +/** + * + * @export + * @interface CustomerBenefitGrantGitHubRepository + */ +export interface CustomerBenefitGrantGitHubRepository { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ created_at: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountFixedRepeatDuration + * @type {string} + * @memberof CustomerBenefitGrantGitHubRepository */ - metadata: { [key: string]: MetadataValue; }; + granted_at: string | null; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ - name: string; + revoked_at: string | null; /** * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ - code: string | null; + customer_id: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ - starts_at: string | null; + benefit_id: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDuration + * @memberof CustomerBenefitGrantGitHubRepository */ - ends_at: string | null; + subscription_id: string | null; /** * - * @type {number} - * @memberof DiscountFixedRepeatDuration + * @type {string} + * @memberof CustomerBenefitGrantGitHubRepository */ - max_redemptions: number | null; + order_id: string | null; /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountFixedRepeatDuration + * + * @type {boolean} + * @memberof CustomerBenefitGrantGitHubRepository */ - redemptions_count: number; + is_granted: boolean; /** - * The organization ID. - * @type {string} - * @memberof DiscountFixedRepeatDuration + * + * @type {boolean} + * @memberof CustomerBenefitGrantGitHubRepository */ - organization_id: string; + is_revoked: boolean; /** * - * @type {Array} - * @memberof DiscountFixedRepeatDuration + * @type {BenefitGitHubRepositorySubscriber} + * @memberof CustomerBenefitGrantGitHubRepository */ - products: Array; + benefit: BenefitGitHubRepositorySubscriber; + /** + * + * @type {BenefitGrantGitHubRepositoryProperties} + * @memberof CustomerBenefitGrantGitHubRepository + */ + properties: BenefitGrantGitHubRepositoryProperties; } - - /** * * @export - * @interface DiscountFixedRepeatDurationBase + * @interface CustomerBenefitGrantGitHubRepositoryPropertiesUpdate */ -export interface DiscountFixedRepeatDurationBase { - /** - * - * @type {DiscountDuration} - * @memberof DiscountFixedRepeatDurationBase - */ - duration: DiscountDuration; - /** - * - * @type {number} - * @memberof DiscountFixedRepeatDurationBase - */ - duration_in_months: number; +export interface CustomerBenefitGrantGitHubRepositoryPropertiesUpdate { /** * - * @type {DiscountType} - * @memberof DiscountFixedRepeatDurationBase + * @type {string} + * @memberof CustomerBenefitGrantGitHubRepositoryPropertiesUpdate */ - type: DiscountType; + account_id: string; +} +/** + * + * @export + * @interface CustomerBenefitGrantGitHubRepositoryUpdate + */ +export interface CustomerBenefitGrantGitHubRepositoryUpdate { /** * - * @type {number} - * @memberof DiscountFixedRepeatDurationBase + * @type {string} + * @memberof CustomerBenefitGrantGitHubRepositoryUpdate */ - amount: number; + benefit_type: CustomerBenefitGrantGitHubRepositoryUpdateBenefitTypeEnum; /** * - * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @type {CustomerBenefitGrantGitHubRepositoryPropertiesUpdate} + * @memberof CustomerBenefitGrantGitHubRepositoryUpdate */ - currency: string; + properties: CustomerBenefitGrantGitHubRepositoryPropertiesUpdate; +} + + +/** + * @export + */ +export const CustomerBenefitGrantGitHubRepositoryUpdateBenefitTypeEnum = { + GITHUB_REPOSITORY: 'github_repository' +} as const; +export type CustomerBenefitGrantGitHubRepositoryUpdateBenefitTypeEnum = typeof CustomerBenefitGrantGitHubRepositoryUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantGitHubRepositoryUpdateBenefitTypeEnum]; + +/** + * + * @export + * @interface CustomerBenefitGrantLicenseKeys + */ +export interface CustomerBenefitGrantLicenseKeys { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ created_at: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountFixedRepeatDurationBase + * @type {string} + * @memberof CustomerBenefitGrantLicenseKeys */ - metadata: { [key: string]: MetadataValue; }; + granted_at: string | null; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ - name: string; + revoked_at: string | null; /** * * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ - code: string | null; + customer_id: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ - starts_at: string | null; + benefit_id: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ - ends_at: string | null; + subscription_id: string | null; /** * - * @type {number} - * @memberof DiscountFixedRepeatDurationBase - */ - max_redemptions: number | null; - /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountFixedRepeatDurationBase - */ - redemptions_count: number; - /** - * The organization ID. * @type {string} - * @memberof DiscountFixedRepeatDurationBase + * @memberof CustomerBenefitGrantLicenseKeys */ - organization_id: string; -} - - -/** - * Schema to create a fixed amount discount that is applied on every invoice - * for a certain number of months. - * @export - * @interface DiscountFixedRepeatDurationCreate - */ -export interface DiscountFixedRepeatDurationCreate { + order_id: string | null; /** * - * @type {DiscountDuration} - * @memberof DiscountFixedRepeatDurationCreate + * @type {boolean} + * @memberof CustomerBenefitGrantLicenseKeys */ - duration: DiscountDuration; + is_granted: boolean; /** - * Number of months the discount should be applied. * - * For this to work on yearly pricing, you should multiply this by 12. - * For example, to apply the discount for 2 years, set this to 24. - * @type {number} - * @memberof DiscountFixedRepeatDurationCreate + * @type {boolean} + * @memberof CustomerBenefitGrantLicenseKeys */ - duration_in_months: number; + is_revoked: boolean; /** * - * @type {DiscountType} - * @memberof DiscountFixedRepeatDurationCreate - */ - type: DiscountType; - /** - * Fixed amount to discount from the invoice total. - * @type {number} - * @memberof DiscountFixedRepeatDurationCreate - */ - amount: number; - /** - * The currency. Currently, only `usd` is supported. - * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @type {BenefitLicenseKeysSubscriber} + * @memberof CustomerBenefitGrantLicenseKeys */ - currency?: string; + benefit: BenefitLicenseKeysSubscriber; /** - * Key-value object allowing you to store additional information. - * - * The key must be a string with a maximum length of **40 characters**. - * The value must be either: - * - * * A string with a maximum length of **500 characters** - * * An integer - * * A boolean * - * You can store up to **50 key-value pairs**. - * @type {{ [key: string]: MetadataValue1; }} - * @memberof DiscountFixedRepeatDurationCreate - */ - metadata?: { [key: string]: MetadataValue1; }; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. - * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @type {BenefitGrantLicenseKeysProperties} + * @memberof CustomerBenefitGrantLicenseKeys */ - name: string; + properties: BenefitGrantLicenseKeysProperties; +} +/** + * + * @export + * @interface CustomerBenefitGrantLicenseKeysUpdate + */ +export interface CustomerBenefitGrantLicenseKeysUpdate { /** * * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @memberof CustomerBenefitGrantLicenseKeysUpdate */ - code?: string | null; + benefit_type: CustomerBenefitGrantLicenseKeysUpdateBenefitTypeEnum; +} + + +/** + * @export + */ +export const CustomerBenefitGrantLicenseKeysUpdateBenefitTypeEnum = { + LICENSE_KEYS: 'license_keys' +} as const; +export type CustomerBenefitGrantLicenseKeysUpdateBenefitTypeEnum = typeof CustomerBenefitGrantLicenseKeysUpdateBenefitTypeEnum[keyof typeof CustomerBenefitGrantLicenseKeysUpdateBenefitTypeEnum]; + + +/** + * + * @export + */ +export const CustomerBenefitGrantSortProperty = { + GRANTED_AT: 'granted_at', + GRANTED_AT2: '-granted_at', + TYPE: 'type', + TYPE2: '-type', + ORGANIZATION: 'organization', + ORGANIZATION2: '-organization' +} as const; +export type CustomerBenefitGrantSortProperty = typeof CustomerBenefitGrantSortProperty[keyof typeof CustomerBenefitGrantSortProperty]; + +/** + * @type CustomerBenefitGrantUpdate + * + * @export + */ +export type CustomerBenefitGrantUpdate = { benefit_type: 'ads' } & CustomerBenefitGrantAdsUpdate | { benefit_type: 'custom' } & CustomerBenefitGrantCustomUpdate | { benefit_type: 'discord' } & CustomerBenefitGrantDiscordUpdate | { benefit_type: 'downloadables' } & CustomerBenefitGrantDownloadablesUpdate | { benefit_type: 'github_repository' } & CustomerBenefitGrantGitHubRepositoryUpdate | { benefit_type: 'license_keys' } & CustomerBenefitGrantLicenseKeysUpdate; +/** + * + * @export + * @interface CustomerCreate + */ +export interface CustomerCreate { /** * * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @memberof CustomerCreate */ - starts_at?: string | null; + email: string; /** * * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @memberof CustomerCreate */ - ends_at?: string | null; + name?: string | null; /** * - * @type {number} - * @memberof DiscountFixedRepeatDurationCreate + * @type {Address} + * @memberof CustomerCreate */ - max_redemptions?: number | null; + billing_address?: Address | null; /** - * List of product IDs the discount can be applied to. + * * @type {Array} - * @memberof DiscountFixedRepeatDurationCreate + * @memberof CustomerCreate */ - products?: Array | null; + tax_id?: Array | null; /** * The organization ID. * @type {string} - * @memberof DiscountFixedRepeatDurationCreate + * @memberof CustomerCreate */ organization_id?: string | null; } - +/** + * @type CustomerIDFilter + * Filter by customer ID. + * @export + */ +export type CustomerIDFilter = Array | string; /** - * @type DiscountIDFilter - * Filter by discount ID. + * @type CustomerIDFilter1 + * Filter by customer. * @export */ -export type DiscountIDFilter = Array | string; +export type CustomerIDFilter1 = Array | string; + /** - * @type DiscountIDFilter1 - * Filter by discount ID. + * * @export */ -export type DiscountIDFilter1 = Array | string; +export const CustomerOAuthPlatform = { + GITHUB: 'github', + DISCORD: 'discord' +} as const; +export type CustomerOAuthPlatform = typeof CustomerOAuthPlatform[keyof typeof CustomerOAuthPlatform]; /** - * Schema for a percentage discount that is applied once or forever. + * * @export - * @interface DiscountPercentageOnceForeverDuration + * @interface CustomerOrder */ -export interface DiscountPercentageOnceForeverDuration { - /** - * - * @type {DiscountDuration} - * @memberof DiscountPercentageOnceForeverDuration - */ - duration: DiscountDuration; - /** - * - * @type {DiscountType} - * @memberof DiscountPercentageOnceForeverDuration - */ - type: DiscountType; - /** - * - * @type {number} - * @memberof DiscountPercentageOnceForeverDuration - */ - basis_points: number; +export interface CustomerOrder { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ created_at: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ modified_at: string | null; /** - * The ID of the object. + * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountPercentageOnceForeverDuration + * @type {number} + * @memberof CustomerOrder */ - metadata: { [key: string]: MetadataValue; }; + amount: number; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. - * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * + * @type {number} + * @memberof CustomerOrder */ - name: string; + tax_amount: number; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ - code: string | null; + currency: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ - starts_at: string | null; + customer_id: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder */ - ends_at: string | null; + product_id: string; /** * - * @type {number} - * @memberof DiscountPercentageOnceForeverDuration + * @type {string} + * @memberof CustomerOrder */ - max_redemptions: number | null; + product_price_id: string; /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountPercentageOnceForeverDuration + * + * @type {string} + * @memberof CustomerOrder */ - redemptions_count: number; + subscription_id: string | null; /** - * The organization ID. + * * @type {string} - * @memberof DiscountPercentageOnceForeverDuration + * @memberof CustomerOrder + * @deprecated */ - organization_id: string; + user_id: string; /** * - * @type {Array} - * @memberof DiscountPercentageOnceForeverDuration + * @type {CustomerOrderProduct} + * @memberof CustomerOrder */ - products: Array; -} - - -/** - * - * @export - * @interface DiscountPercentageOnceForeverDurationBase - */ -export interface DiscountPercentageOnceForeverDurationBase { + product: CustomerOrderProduct; /** * - * @type {DiscountDuration} - * @memberof DiscountPercentageOnceForeverDurationBase + * @type {ProductPrice} + * @memberof CustomerOrder */ - duration: DiscountDuration; + product_price: ProductPrice; /** * - * @type {DiscountType} - * @memberof DiscountPercentageOnceForeverDurationBase + * @type {CustomerOrderSubscription} + * @memberof CustomerOrder */ - type: DiscountType; + subscription: CustomerOrderSubscription | null; +} +/** + * Order's invoice data. + * @export + * @interface CustomerOrderInvoice + */ +export interface CustomerOrderInvoice { /** - * - * @type {number} - * @memberof DiscountPercentageOnceForeverDurationBase + * The URL to the invoice. + * @type {string} + * @memberof CustomerOrderInvoice */ - basis_points: number; + url: string; +} +/** + * + * @export + * @interface CustomerOrderProduct + */ +export interface CustomerOrderProduct { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ created_at: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ modified_at: string | null; /** - * The ID of the object. + * The ID of the product. * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ id: string; /** - * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountPercentageOnceForeverDurationBase - */ - metadata: { [key: string]: MetadataValue; }; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * The name of the product. * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ name: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ - code: string | null; + description: string | null; /** - * - * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * Whether the product is a subscription tier. + * @type {boolean} + * @memberof CustomerOrderProduct */ - starts_at: string | null; + is_recurring: boolean; /** - * + * Whether the product is archived and no longer available. + * @type {boolean} + * @memberof CustomerOrderProduct + */ + is_archived: boolean; + /** + * The ID of the organization owning the product. * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * @memberof CustomerOrderProduct */ - ends_at: string | null; + organization_id: string; /** - * - * @type {number} - * @memberof DiscountPercentageOnceForeverDurationBase + * List of prices for this product. + * @type {Array} + * @memberof CustomerOrderProduct */ - max_redemptions: number | null; + prices: Array; /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountPercentageOnceForeverDurationBase + * List of benefits granted by the product. + * @type {Array} + * @memberof CustomerOrderProduct */ - redemptions_count: number; + benefits: Array; /** - * The organization ID. - * @type {string} - * @memberof DiscountPercentageOnceForeverDurationBase + * List of medias associated to the product. + * @type {Array} + * @memberof CustomerOrderProduct */ - organization_id: string; + medias: Array; + /** + * + * @type {Organization} + * @memberof CustomerOrderProduct + */ + organization: Organization; } +/** + * + * @export + */ +export const CustomerOrderSortProperty = { + CREATED_AT: 'created_at', + CREATED_AT2: '-created_at', + AMOUNT: 'amount', + AMOUNT2: '-amount', + ORGANIZATION: 'organization', + ORGANIZATION2: '-organization', + PRODUCT: 'product', + PRODUCT2: '-product', + SUBSCRIPTION: 'subscription', + SUBSCRIPTION2: '-subscription' +} as const; +export type CustomerOrderSortProperty = typeof CustomerOrderSortProperty[keyof typeof CustomerOrderSortProperty]; /** - * Schema to create a percentage discount that is applied once or forever. + * * @export - * @interface DiscountPercentageOnceForeverDurationCreate + * @interface CustomerOrderSubscription */ -export interface DiscountPercentageOnceForeverDurationCreate { +export interface CustomerOrderSubscription { /** - * - * @type {DiscountDuration} - * @memberof DiscountPercentageOnceForeverDurationCreate + * Creation timestamp of the object. + * @type {string} + * @memberof CustomerOrderSubscription */ - duration: DiscountDuration; + created_at: string; /** * - * @type {DiscountType} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @type {string} + * @memberof CustomerOrderSubscription */ - type: DiscountType; + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof CustomerOrderSubscription + */ + id: string; /** - * Discount percentage in basis points. * - * A basis point is 1/100th of a percent. - * For example, to create a 25.5% discount, set this to 2550. * @type {number} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @memberof CustomerOrderSubscription */ - basis_points: number; + amount: number | null; /** - * Key-value object allowing you to store additional information. - * - * The key must be a string with a maximum length of **40 characters**. - * The value must be either: * - * * A string with a maximum length of **500 characters** - * * An integer - * * A boolean + * @type {string} + * @memberof CustomerOrderSubscription + */ + currency: string | null; + /** * - * You can store up to **50 key-value pairs**. - * @type {{ [key: string]: MetadataValue1; }} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @type {SubscriptionRecurringInterval} + * @memberof CustomerOrderSubscription */ - metadata?: { [key: string]: MetadataValue1; }; + recurring_interval: SubscriptionRecurringInterval; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. - * @type {string} - * @memberof DiscountPercentageOnceForeverDurationCreate + * + * @type {SubscriptionStatus} + * @memberof CustomerOrderSubscription */ - name: string; + status: SubscriptionStatus; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @memberof CustomerOrderSubscription */ - code?: string | null; + current_period_start: string; /** * * @type {string} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @memberof CustomerOrderSubscription */ - starts_at?: string | null; + current_period_end: string | null; /** * - * @type {string} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @type {boolean} + * @memberof CustomerOrderSubscription */ - ends_at?: string | null; + cancel_at_period_end: boolean; /** * - * @type {number} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @type {string} + * @memberof CustomerOrderSubscription */ - max_redemptions?: number | null; + started_at: string | null; /** - * List of product IDs the discount can be applied to. - * @type {Array} - * @memberof DiscountPercentageOnceForeverDurationCreate + * + * @type {string} + * @memberof CustomerOrderSubscription */ - products?: Array | null; + ended_at: string | null; /** - * The organization ID. + * * @type {string} - * @memberof DiscountPercentageOnceForeverDurationCreate + * @memberof CustomerOrderSubscription */ - organization_id?: string | null; -} - - -/** - * Schema for a percentage discount that is applied on every invoice - * for a certain number of months. - * @export - * @interface DiscountPercentageRepeatDuration - */ -export interface DiscountPercentageRepeatDuration { + customer_id: string; /** * - * @type {DiscountDuration} - * @memberof DiscountPercentageRepeatDuration + * @type {string} + * @memberof CustomerOrderSubscription */ - duration: DiscountDuration; + product_id: string; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDuration + * @type {string} + * @memberof CustomerOrderSubscription */ - duration_in_months: number; + price_id: string; /** * - * @type {DiscountType} - * @memberof DiscountPercentageRepeatDuration + * @type {string} + * @memberof CustomerOrderSubscription */ - type: DiscountType; + discount_id: string | null; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDuration + * @type {string} + * @memberof CustomerOrderSubscription */ - basis_points: number; + checkout_id: string | null; +} + + +/** + * + * @export + * @interface CustomerPortalCustomer + */ +export interface CustomerPortalCustomer { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalCustomer */ created_at: string; /** * * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalCustomer */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalCustomer */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountPercentageRepeatDuration - */ - metadata: { [key: string]: MetadataValue; }; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalCustomer */ - name: string; + email: string; /** * - * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @type {boolean} + * @memberof CustomerPortalCustomer */ - code: string | null; + email_verified: boolean; /** * * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalCustomer */ - starts_at: string | null; + name: string | null; /** * - * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @type {Address} + * @memberof CustomerPortalCustomer */ - ends_at: string | null; + billing_address: Address | null; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDuration + * @type {Array} + * @memberof CustomerPortalCustomer */ - max_redemptions: number | null; + tax_id: Array | null; /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountPercentageRepeatDuration + * + * @type {{ [key: string]: CustomerPortalOAuthAccount; }} + * @memberof CustomerPortalCustomer */ - redemptions_count: number; + oauth_accounts: { [key: string]: CustomerPortalOAuthAccount; }; +} +/** + * + * @export + * @interface CustomerPortalOAuthAccount + */ +export interface CustomerPortalOAuthAccount { /** - * The organization ID. + * * @type {string} - * @memberof DiscountPercentageRepeatDuration + * @memberof CustomerPortalOAuthAccount */ - organization_id: string; + account_id: string; /** * - * @type {Array} - * @memberof DiscountPercentageRepeatDuration + * @type {string} + * @memberof CustomerPortalOAuthAccount */ - products: Array; + account_username: string | null; } - - /** * * @export - * @interface DiscountPercentageRepeatDurationBase + * @interface CustomerSessionCodeAuthenticateRequest */ -export interface DiscountPercentageRepeatDurationBase { +export interface CustomerSessionCodeAuthenticateRequest { /** * - * @type {DiscountDuration} - * @memberof DiscountPercentageRepeatDurationBase + * @type {string} + * @memberof CustomerSessionCodeAuthenticateRequest */ - duration: DiscountDuration; + code: string; +} +/** + * + * @export + * @interface CustomerSessionCodeAuthenticateResponse + */ +export interface CustomerSessionCodeAuthenticateResponse { /** * - * @type {number} - * @memberof DiscountPercentageRepeatDurationBase + * @type {string} + * @memberof CustomerSessionCodeAuthenticateResponse */ - duration_in_months: number; + token: string; +} +/** + * + * @export + * @interface CustomerSessionCodeRequest + */ +export interface CustomerSessionCodeRequest { /** * - * @type {DiscountType} - * @memberof DiscountPercentageRepeatDurationBase + * @type {string} + * @memberof CustomerSessionCodeRequest */ - type: DiscountType; + email: string; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDurationBase + * @type {string} + * @memberof CustomerSessionCodeRequest */ - basis_points: number; + organization_id: string; +} + +/** + * + * @export + */ +export const CustomerSortProperty = { + CREATED_AT: 'created_at', + CREATED_AT2: '-created_at', + EMAIL: 'email', + EMAIL2: '-email', + NAME: 'name', + NAME2: '-name' +} as const; +export type CustomerSortProperty = typeof CustomerSortProperty[keyof typeof CustomerSortProperty]; + +/** + * + * @export + * @interface CustomerSubscription + */ +export interface CustomerSubscription { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ created_at: string; /** * * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ id: string; /** * - * @type {{ [key: string]: MetadataValue; }} - * @memberof DiscountPercentageRepeatDurationBase + * @type {number} + * @memberof CustomerSubscription */ - metadata: { [key: string]: MetadataValue; }; + amount: number | null; /** - * Name of the discount. Will be displayed to the customer when the discount is applied. + * * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ - name: string; + currency: string | null; /** * - * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @type {SubscriptionRecurringInterval} + * @memberof CustomerSubscription */ - code: string | null; + recurring_interval: SubscriptionRecurringInterval; /** * - * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @type {SubscriptionStatus} + * @memberof CustomerSubscription */ - starts_at: string | null; + status: SubscriptionStatus; /** * * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ - ends_at: string | null; + current_period_start: string; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDurationBase - */ - max_redemptions: number | null; - /** - * Number of times the discount has been redeemed. - * @type {number} - * @memberof DiscountPercentageRepeatDurationBase - */ - redemptions_count: number; - /** - * The organization ID. * @type {string} - * @memberof DiscountPercentageRepeatDurationBase + * @memberof CustomerSubscription */ - organization_id: string; -} - - -/** - * Schema to create a percentage discount that is applied on every invoice - * for a certain number of months. - * @export - * @interface DiscountPercentageRepeatDurationCreate - */ -export interface DiscountPercentageRepeatDurationCreate { + current_period_end: string | null; /** * - * @type {DiscountDuration} - * @memberof DiscountPercentageRepeatDurationCreate + * @type {boolean} + * @memberof CustomerSubscription */ - duration: DiscountDuration; + cancel_at_period_end: boolean; /** - * Number of months the discount should be applied. * - * For this to work on yearly pricing, you should multiply this by 12. - * For example, to apply the discount for 2 years, set this to 24. - * @type {number} - * @memberof DiscountPercentageRepeatDurationCreate + * @type {string} + * @memberof CustomerSubscription */ - duration_in_months: number; + started_at: string | null; /** * - * @type {DiscountType} - * @memberof DiscountPercentageRepeatDurationCreate + * @type {string} + * @memberof CustomerSubscription */ - type: DiscountType; + ended_at: string | null; /** - * Discount percentage in basis points. * - * A basis point is 1/100th of a percent. - * For example, to create a 25.5% discount, set this to 2550. - * @type {number} - * @memberof DiscountPercentageRepeatDurationCreate + * @type {string} + * @memberof CustomerSubscription */ - basis_points: number; + customer_id: string; /** - * Key-value object allowing you to store additional information. * - * The key must be a string with a maximum length of **40 characters**. - * The value must be either: - * - * * A string with a maximum length of **500 characters** - * * An integer - * * A boolean - * - * You can store up to **50 key-value pairs**. - * @type {{ [key: string]: MetadataValue1; }} - * @memberof DiscountPercentageRepeatDurationCreate - */ - metadata?: { [key: string]: MetadataValue1; }; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DiscountPercentageRepeatDurationCreate + * @memberof CustomerSubscription */ - name: string; + product_id: string; /** * * @type {string} - * @memberof DiscountPercentageRepeatDurationCreate + * @memberof CustomerSubscription */ - code?: string | null; + price_id: string; /** * * @type {string} - * @memberof DiscountPercentageRepeatDurationCreate + * @memberof CustomerSubscription */ - starts_at?: string | null; + discount_id: string | null; /** * * @type {string} - * @memberof DiscountPercentageRepeatDurationCreate + * @memberof CustomerSubscription */ - ends_at?: string | null; + checkout_id: string | null; /** * - * @type {number} - * @memberof DiscountPercentageRepeatDurationCreate + * @type {string} + * @memberof CustomerSubscription + * @deprecated */ - max_redemptions?: number | null; + user_id: string; /** - * List of product IDs the discount can be applied to. - * @type {Array} - * @memberof DiscountPercentageRepeatDurationCreate + * + * @type {CustomerSubscriptionProduct} + * @memberof CustomerSubscription */ - products?: Array | null; + product: CustomerSubscriptionProduct; /** - * The organization ID. - * @type {string} - * @memberof DiscountPercentageRepeatDurationCreate + * + * @type {ProductPrice} + * @memberof CustomerSubscription */ - organization_id?: string | null; + price: ProductPrice; } /** - * A product that a discount can be applied to. + * * @export - * @interface DiscountProduct + * @interface CustomerSubscriptionProduct */ -export interface DiscountProduct { +export interface CustomerSubscriptionProduct { /** * Creation timestamp of the object. * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ created_at: string; /** * * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ modified_at: string | null; /** * The ID of the product. * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ id: string; /** * The name of the product. * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ name: string; /** * * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ description: string | null; /** * Whether the product is a subscription tier. * @type {boolean} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ is_recurring: boolean; /** * Whether the product is archived and no longer available. * @type {boolean} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ is_archived: boolean; /** * The ID of the organization owning the product. * @type {string} - * @memberof DiscountProduct + * @memberof CustomerSubscriptionProduct */ organization_id: string; + /** + * List of prices for this product. + * @type {Array} + * @memberof CustomerSubscriptionProduct + */ + prices: Array; + /** + * List of benefits granted by the product. + * @type {Array} + * @memberof CustomerSubscriptionProduct + */ + benefits: Array; + /** + * List of medias associated to the product. + * @type {Array} + * @memberof CustomerSubscriptionProduct + */ + medias: Array; + /** + * + * @type {Organization} + * @memberof CustomerSubscriptionProduct + */ + organization: Organization; } /** * * @export */ -export const DiscountSortProperty = { - CREATED_AT: 'created_at', - CREATED_AT2: '-created_at', - NAME: 'name', - NAME2: '-name', - CODE: 'code', - CODE2: '-code', - REDEMPTIONS_COUNT: 'redemptions_count', - REDEMPTIONS_COUNT2: '-redemptions_count' +export const CustomerSubscriptionSortProperty = { + STARTED_AT: 'started_at', + STARTED_AT2: '-started_at', + AMOUNT: 'amount', + AMOUNT2: '-amount', + STATUS: 'status', + STATUS2: '-status', + ORGANIZATION: 'organization', + ORGANIZATION2: '-organization', + PRODUCT: 'product', + PRODUCT2: '-product' } as const; -export type DiscountSortProperty = typeof DiscountSortProperty[keyof typeof DiscountSortProperty]; - +export type CustomerSubscriptionSortProperty = typeof CustomerSubscriptionSortProperty[keyof typeof CustomerSubscriptionSortProperty]; /** * * @export + * @interface CustomerSubscriptionUpdate */ -export const DiscountType = { - FIXED: 'fixed', - PERCENTAGE: 'percentage' -} as const; -export type DiscountType = typeof DiscountType[keyof typeof DiscountType]; - +export interface CustomerSubscriptionUpdate { + /** + * + * @type {string} + * @memberof CustomerSubscriptionUpdate + */ + product_price_id: string; +} /** - * Schema to update a discount. + * * @export - * @interface DiscountUpdate + * @interface CustomerUpdate */ -export interface DiscountUpdate { +export interface CustomerUpdate { /** * - * @type {{ [key: string]: MetadataValue1; }} - * @memberof DiscountUpdate - */ - metadata?: { [key: string]: MetadataValue1; } | null; - /** - * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DiscountUpdate + * @memberof CustomerUpdate */ - name?: string | null; + email?: string | null; /** * - * @type {DiscountUpdateCode} - * @memberof DiscountUpdate + * @type {string} + * @memberof CustomerUpdate */ - code?: DiscountUpdateCode | null; + name?: string | null; /** * - * @type {DiscountUpdateStartsAt} - * @memberof DiscountUpdate + * @type {Address} + * @memberof CustomerUpdate */ - starts_at?: DiscountUpdateStartsAt | null; + billing_address?: Address | null; /** * - * @type {DiscountUpdateEndsAt} - * @memberof DiscountUpdate + * @type {Array} + * @memberof CustomerUpdate */ - ends_at?: DiscountUpdateEndsAt | null; + tax_id?: Array | null; +} +/** + * + * @export + * @interface DiscordGuild + */ +export interface DiscordGuild { /** * - * @type {DiscountUpdateMaxRedemptions} - * @memberof DiscountUpdate + * @type {string} + * @memberof DiscordGuild */ - max_redemptions?: DiscountUpdateMaxRedemptions | null; + name: string; /** * - * @type {DiscountDuration} - * @memberof DiscountUpdate + * @type {Array} + * @memberof DiscordGuild */ - duration?: DiscountDuration | null; + roles: Array; +} +/** + * + * @export + * @interface DiscordGuildRole + */ +export interface DiscordGuildRole { /** - * Number of months the discount should be applied. * - * For this to work on yearly pricing, you should multiply this by 12. - * For example, to apply the discount for 2 years, set this to 24. - * @type {number} - * @memberof DiscountUpdate + * @type {string} + * @memberof DiscordGuildRole */ - duration_in_months?: number | null; + id: string; /** * - * @type {DiscountType} - * @memberof DiscountUpdate + * @type {string} + * @memberof DiscordGuildRole */ - type?: DiscountType | null; + name: string; /** - * Fixed amount to discount from the invoice total. + * * @type {number} - * @memberof DiscountUpdate - */ - amount?: number | null; - /** - * The currency. Currently, only `usd` is supported. - * @type {string} - * @memberof DiscountUpdate + * @memberof DiscordGuildRole */ - currency?: string | null; + position: number; /** - * Discount percentage in basis points. * - * A basis point is 1/100th of a percent. - * For example, to create a 25.5% discount, set this to 2550. - * @type {number} - * @memberof DiscountUpdate + * @type {boolean} + * @memberof DiscordGuildRole */ - basis_points?: number | null; + is_polar_bot: boolean; /** - * List of product IDs the discount can be applied to. - * @type {Array} - * @memberof DiscountUpdate + * + * @type {string} + * @memberof DiscordGuildRole */ - products?: Array | null; + color: string; } - - -/** - * @type DiscountUpdateCode - * Code customers can use to apply the discount during checkout. Must be between 3 and 256 characters long and contain only alphanumeric characters.If not provided, the discount can only be applied via the API. - * @export - */ -export type DiscountUpdateCode = string; - /** - * @type DiscountUpdateEndsAt - * Optional timestamp after which the discount is no longer redeemable. + * @type Discount + * * @export */ -export type DiscountUpdateEndsAt = string; - +export type Discount = DiscountFixedOnceForeverDuration | DiscountFixedRepeatDuration | DiscountPercentageOnceForeverDuration | DiscountPercentageRepeatDuration; /** - * @type DiscountUpdateMaxRedemptions - * Optional maximum number of times the discount can be redeemed. + * @type DiscountCreate + * * @export */ -export type DiscountUpdateMaxRedemptions = number; +export type DiscountCreate = DiscountFixedOnceForeverDurationCreate | DiscountFixedRepeatDurationCreate | DiscountPercentageOnceForeverDurationCreate | DiscountPercentageRepeatDurationCreate; /** - * @type DiscountUpdateStartsAt - * Optional timestamp after which the discount is redeemable. + * * @export */ -export type DiscountUpdateStartsAt = string; +export const DiscountDuration = { + ONCE: 'once', + FOREVER: 'forever', + REPEATING: 'repeating' +} as const; +export type DiscountDuration = typeof DiscountDuration[keyof typeof DiscountDuration]; /** - * Schema to create a file to be associated with the downloadables benefit. + * Schema for a fixed amount discount that is applied once or forever. * @export - * @interface DownloadableFileCreate + * @interface DiscountFixedOnceForeverDuration */ -export interface DownloadableFileCreate { - /** - * The organization ID. - * @type {string} - * @memberof DownloadableFileCreate - */ - organization_id?: string | null; +export interface DiscountFixedOnceForeverDuration { /** * - * @type {string} - * @memberof DownloadableFileCreate + * @type {DiscountDuration} + * @memberof DiscountFixedOnceForeverDuration */ - name: string; + duration: DiscountDuration; /** * - * @type {string} - * @memberof DownloadableFileCreate + * @type {DiscountType} + * @memberof DiscountFixedOnceForeverDuration */ - mime_type: string; + type: DiscountType; /** * * @type {number} - * @memberof DownloadableFileCreate + * @memberof DiscountFixedOnceForeverDuration */ - size: number; + amount: number; /** * * @type {string} - * @memberof DownloadableFileCreate - */ - checksum_sha256_base64?: string | null; - /** - * - * @type {S3FileCreateMultipart} - * @memberof DownloadableFileCreate + * @memberof DiscountFixedOnceForeverDuration */ - upload: S3FileCreateMultipart; + currency: string; /** - * + * Creation timestamp of the object. * @type {string} - * @memberof DownloadableFileCreate + * @memberof DiscountFixedOnceForeverDuration */ - service: DownloadableFileCreateServiceEnum; + created_at: string; /** * * @type {string} - * @memberof DownloadableFileCreate + * @memberof DiscountFixedOnceForeverDuration */ - version?: string | null; -} - - -/** - * @export - */ -export const DownloadableFileCreateServiceEnum = { - DOWNLOADABLE: 'downloadable' -} as const; -export type DownloadableFileCreateServiceEnum = typeof DownloadableFileCreateServiceEnum[keyof typeof DownloadableFileCreateServiceEnum]; - -/** - * File to be associated with the downloadables benefit. - * @export - * @interface DownloadableFileRead - */ -export interface DownloadableFileRead { + modified_at: string | null; /** * The ID of the object. * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ id: string; /** * + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountFixedOnceForeverDuration + */ + metadata: { [key: string]: MetadataValue; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - organization_id: string; + name: string; /** * * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - name: string; + code: string | null; /** * * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - path: string; + starts_at: string | null; /** * * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - mime_type: string; + ends_at: string | null; /** * * @type {number} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - size: number; + max_redemptions: number | null; /** - * + * Number of times the discount has been redeemed. + * @type {number} + * @memberof DiscountFixedOnceForeverDuration + */ + redemptions_count: number; + /** + * The organization ID. * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDuration */ - storage_version: string | null; + organization_id: string; /** * - * @type {string} - * @memberof DownloadableFileRead + * @type {Array} + * @memberof DiscountFixedOnceForeverDuration */ - checksum_etag: string | null; + products: Array; +} + + +/** + * + * @export + * @interface DiscountFixedOnceForeverDurationBase + */ +export interface DiscountFixedOnceForeverDurationBase { /** * - * @type {string} - * @memberof DownloadableFileRead + * @type {DiscountDuration} + * @memberof DiscountFixedOnceForeverDurationBase */ - checksum_sha256_base64: string | null; + duration: DiscountDuration; /** * - * @type {string} - * @memberof DownloadableFileRead + * @type {DiscountType} + * @memberof DiscountFixedOnceForeverDurationBase */ - checksum_sha256_hex: string | null; + type: DiscountType; /** * - * @type {string} - * @memberof DownloadableFileRead + * @type {number} + * @memberof DiscountFixedOnceForeverDurationBase */ - last_modified_at: string | null; + amount: number; /** * * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDurationBase */ - version: string | null; + currency: string; /** - * + * Creation timestamp of the object. * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDurationBase */ - service: DownloadableFileReadServiceEnum; + created_at: string; /** * - * @type {boolean} - * @memberof DownloadableFileRead + * @type {string} + * @memberof DiscountFixedOnceForeverDurationBase */ - is_uploaded: boolean; + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof DiscountFixedOnceForeverDurationBase + */ + id: string; /** * + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountFixedOnceForeverDurationBase + */ + metadata: { [key: string]: MetadataValue; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDurationBase */ - created_at: string; + name: string; /** * * @type {string} - * @memberof DownloadableFileRead + * @memberof DiscountFixedOnceForeverDurationBase */ - readonly size_readable: string; -} - - -/** - * @export - */ -export const DownloadableFileReadServiceEnum = { - DOWNLOADABLE: 'downloadable' -} as const; -export type DownloadableFileReadServiceEnum = typeof DownloadableFileReadServiceEnum[keyof typeof DownloadableFileReadServiceEnum]; - -/** - * - * @export - * @interface DownloadableRead - */ -export interface DownloadableRead { + code: string | null; /** * * @type {string} - * @memberof DownloadableRead + * @memberof DiscountFixedOnceForeverDurationBase */ - id: string; + starts_at: string | null; /** * * @type {string} - * @memberof DownloadableRead + * @memberof DiscountFixedOnceForeverDurationBase */ - benefit_id: string; + ends_at: string | null; /** * - * @type {FileDownload} - * @memberof DownloadableRead + * @type {number} + * @memberof DiscountFixedOnceForeverDurationBase */ - file: FileDownload; + max_redemptions: number | null; + /** + * Number of times the discount has been redeemed. + * @type {number} + * @memberof DiscountFixedOnceForeverDurationBase + */ + redemptions_count: number; + /** + * The organization ID. + * @type {string} + * @memberof DiscountFixedOnceForeverDurationBase + */ + organization_id: string; } + + /** - * + * Schema to create a fixed amount discount that is applied once or forever. * @export - * @interface Entry + * @interface DiscountFixedOnceForeverDurationCreate */ -export interface Entry { +export interface DiscountFixedOnceForeverDurationCreate { /** * - * @type {string} - * @memberof Entry + * @type {DiscountDuration} + * @memberof DiscountFixedOnceForeverDurationCreate */ - type: string; + duration: DiscountDuration; /** * - * @type {Id} - * @memberof Entry + * @type {DiscountType} + * @memberof DiscountFixedOnceForeverDurationCreate */ - id: Id; + type: DiscountType; + /** + * Fixed amount to discount from the invoice total. + * @type {number} + * @memberof DiscountFixedOnceForeverDurationCreate + */ + amount: number; + /** + * The currency. Currently, only `usd` is supported. + * @type {string} + * @memberof DiscountFixedOnceForeverDurationCreate + */ + currency?: string; /** + * Key-value object allowing you to store additional information. * - * @type {Issue} - * @memberof Entry + * The key must be a string with a maximum length of **40 characters**. + * The value must be either: + * + * * A string with a maximum length of **500 characters** + * * An integer + * * A boolean + * + * You can store up to **50 key-value pairs**. + * @type {{ [key: string]: MetadataValue1; }} + * @memberof DiscountFixedOnceForeverDurationCreate */ - attributes: Issue; + metadata?: { [key: string]: MetadataValue1; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. + * @type {string} + * @memberof DiscountFixedOnceForeverDurationCreate + */ + name: string; /** * - * @type {Array} - * @memberof Entry + * @type {string} + * @memberof DiscountFixedOnceForeverDurationCreate */ - rewards: Array | null; + code?: string | null; /** * - * @type {PledgesTypeSummaries} - * @memberof Entry + * @type {string} + * @memberof DiscountFixedOnceForeverDurationCreate */ - pledges_summary: PledgesTypeSummaries | null; + starts_at?: string | null; /** * - * @type {Array} - * @memberof Entry + * @type {string} + * @memberof DiscountFixedOnceForeverDurationCreate */ - pledges: Array | null; -} -/** - * A price that already exists for this product. - * - * Useful when updating a product if you want to keep an existing price. - * @export - * @interface ExistingProductPrice - */ -export interface ExistingProductPrice { + ends_at?: string | null; /** * + * @type {number} + * @memberof DiscountFixedOnceForeverDurationCreate + */ + max_redemptions?: number | null; + /** + * List of product IDs the discount can be applied to. + * @type {Array} + * @memberof DiscountFixedOnceForeverDurationCreate + */ + products?: Array | null; + /** + * The organization ID. * @type {string} - * @memberof ExistingProductPrice + * @memberof DiscountFixedOnceForeverDurationCreate */ - id: string; + organization_id?: string | null; } + + /** - * + * Schema for a fixed amount discount that is applied on every invoice + * for a certain number of months. * @export - * @interface ExternalOrganization + * @interface DiscountFixedRepeatDuration */ -export interface ExternalOrganization { +export interface DiscountFixedRepeatDuration { /** * - * @type {string} - * @memberof ExternalOrganization + * @type {DiscountDuration} + * @memberof DiscountFixedRepeatDuration */ - id: string; + duration: DiscountDuration; /** * - * @type {Platforms} - * @memberof ExternalOrganization + * @type {number} + * @memberof DiscountFixedRepeatDuration */ - platform: Platforms; + duration_in_months: number; /** * - * @type {string} - * @memberof ExternalOrganization + * @type {DiscountType} + * @memberof DiscountFixedRepeatDuration */ - name: string; + type: DiscountType; /** * - * @type {string} - * @memberof ExternalOrganization + * @type {number} + * @memberof DiscountFixedRepeatDuration */ - avatar_url: string; + amount: number; /** * - * @type {boolean} - * @memberof ExternalOrganization + * @type {string} + * @memberof DiscountFixedRepeatDuration */ - is_personal: boolean; + currency: string; /** - * + * Creation timestamp of the object. * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - bio: string | null; + created_at: string; /** * * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - pretty_name: string | null; + modified_at: string | null; /** - * + * The ID of the object. * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - company: string | null; + id: string; /** * + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountFixedRepeatDuration + */ + metadata: { [key: string]: MetadataValue; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - blog: string | null; + name: string; /** * * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - location: string | null; + code: string | null; /** * * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - email: string | null; + starts_at: string | null; /** * * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - twitter_username: string | null; + ends_at: string | null; + /** + * + * @type {number} + * @memberof DiscountFixedRepeatDuration + */ + max_redemptions: number | null; + /** + * Number of times the discount has been redeemed. + * @type {number} + * @memberof DiscountFixedRepeatDuration + */ + redemptions_count: number; /** * The organization ID. * @type {string} - * @memberof ExternalOrganization + * @memberof DiscountFixedRepeatDuration */ - organization_id: string | null; + organization_id: string; + /** + * + * @type {Array} + * @memberof DiscountFixedRepeatDuration + */ + products: Array; } -/** - * @type ExternalOrganizationNameFilter - * Filter by external organization name. - * @export - */ -export type ExternalOrganizationNameFilter = Array | string; - - /** * * @export + * @interface DiscountFixedRepeatDurationBase */ -export const ExternalOrganizationSortProperty = { - CREATED_AT: 'created_at', - CREATED_AT2: '-created_at', - NAME: 'name', - NAME2: '-name' -} as const; -export type ExternalOrganizationSortProperty = typeof ExternalOrganizationSortProperty[keyof typeof ExternalOrganizationSortProperty]; - -/** - * @type FileCreate - * - * @export - */ -export type FileCreate = { service: 'downloadable' } & DownloadableFileCreate | { service: 'organization_avatar' } & OrganizationAvatarFileCreate | { service: 'product_media' } & ProductMediaFileCreate; -/** - * - * @export - * @interface FileDownload - */ -export interface FileDownload { - /** - * The ID of the object. - * @type {string} - * @memberof FileDownload - */ - id: string; - /** - * - * @type {string} - * @memberof FileDownload - */ - organization_id: string; +export interface DiscountFixedRepeatDurationBase { /** * - * @type {string} - * @memberof FileDownload + * @type {DiscountDuration} + * @memberof DiscountFixedRepeatDurationBase */ - name: string; + duration: DiscountDuration; /** * - * @type {string} - * @memberof FileDownload + * @type {number} + * @memberof DiscountFixedRepeatDurationBase */ - path: string; + duration_in_months: number; /** * - * @type {string} - * @memberof FileDownload + * @type {DiscountType} + * @memberof DiscountFixedRepeatDurationBase */ - mime_type: string; + type: DiscountType; /** * * @type {number} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - size: number; + amount: number; /** * * @type {string} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - storage_version: string | null; + currency: string; /** - * + * Creation timestamp of the object. * @type {string} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - checksum_etag: string | null; + created_at: string; /** * * @type {string} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - checksum_sha256_base64: string | null; + modified_at: string | null; /** - * + * The ID of the object. * @type {string} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - checksum_sha256_hex: string | null; + id: string; /** * - * @type {string} - * @memberof FileDownload + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountFixedRepeatDurationBase */ - last_modified_at: string | null; + metadata: { [key: string]: MetadataValue; }; /** - * - * @type {S3DownloadURL} - * @memberof FileDownload + * Name of the discount. Will be displayed to the customer when the discount is applied. + * @type {string} + * @memberof DiscountFixedRepeatDurationBase */ - download: S3DownloadURL; + name: string; /** * * @type {string} - * @memberof FileDownload + * @memberof DiscountFixedRepeatDurationBase */ - version: string | null; + code: string | null; /** * - * @type {boolean} - * @memberof FileDownload + * @type {string} + * @memberof DiscountFixedRepeatDurationBase */ - is_uploaded: boolean; + starts_at: string | null; /** * - * @type {FileServiceTypes} - * @memberof FileDownload + * @type {string} + * @memberof DiscountFixedRepeatDurationBase */ - service: FileServiceTypes; + ends_at: string | null; /** * - * @type {string} - * @memberof FileDownload + * @type {number} + * @memberof DiscountFixedRepeatDurationBase */ - readonly size_readable: string; -} - - -/** - * - * @export - * @interface FilePatch - */ -export interface FilePatch { + max_redemptions: number | null; /** - * - * @type {string} - * @memberof FilePatch + * Number of times the discount has been redeemed. + * @type {number} + * @memberof DiscountFixedRepeatDurationBase */ - name?: string | null; + redemptions_count: number; /** - * + * The organization ID. * @type {string} - * @memberof FilePatch + * @memberof DiscountFixedRepeatDurationBase */ - version?: string | null; + organization_id: string; } -/** - * @type FileRead - * - * @export - */ -export type FileRead = { service: 'downloadable' } & DownloadableFileRead | { service: 'organization_avatar' } & OrganizationAvatarFileRead | { service: 'product_media' } & ProductMediaFileRead; -/** - * - * @export - */ -export const FileServiceTypes = { - DOWNLOADABLE: 'downloadable', - PRODUCT_MEDIA: 'product_media', - ORGANIZATION_AVATAR: 'organization_avatar' -} as const; -export type FileServiceTypes = typeof FileServiceTypes[keyof typeof FileServiceTypes]; /** - * + * Schema to create a fixed amount discount that is applied on every invoice + * for a certain number of months. * @export - * @interface FileUpload + * @interface DiscountFixedRepeatDurationCreate */ -export interface FileUpload { - /** - * The ID of the object. - * @type {string} - * @memberof FileUpload - */ - id: string; - /** - * - * @type {string} - * @memberof FileUpload - */ - organization_id: string; +export interface DiscountFixedRepeatDurationCreate { /** * - * @type {string} - * @memberof FileUpload + * @type {DiscountDuration} + * @memberof DiscountFixedRepeatDurationCreate */ - name: string; + duration: DiscountDuration; /** + * Number of months the discount should be applied. * - * @type {string} - * @memberof FileUpload + * For this to work on yearly pricing, you should multiply this by 12. + * For example, to apply the discount for 2 years, set this to 24. + * @type {number} + * @memberof DiscountFixedRepeatDurationCreate */ - path: string; + duration_in_months: number; /** * - * @type {string} - * @memberof FileUpload + * @type {DiscountType} + * @memberof DiscountFixedRepeatDurationCreate */ - mime_type: string; + type: DiscountType; /** - * + * Fixed amount to discount from the invoice total. * @type {number} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - size: number; + amount: number; /** - * + * The currency. Currently, only `usd` is supported. * @type {string} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - storage_version: string | null; + currency?: string; /** + * Key-value object allowing you to store additional information. * - * @type {string} - * @memberof FileUpload - */ - checksum_etag: string | null; - /** + * The key must be a string with a maximum length of **40 characters**. + * The value must be either: * - * @type {string} - * @memberof FileUpload + * * A string with a maximum length of **500 characters** + * * An integer + * * A boolean + * + * You can store up to **50 key-value pairs**. + * @type {{ [key: string]: MetadataValue1; }} + * @memberof DiscountFixedRepeatDurationCreate */ - checksum_sha256_base64: string | null; + metadata?: { [key: string]: MetadataValue1; }; /** - * + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - checksum_sha256_hex: string | null; + name: string; /** * * @type {string} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - last_modified_at: string | null; + code?: string | null; /** * - * @type {S3FileUploadMultipart} - * @memberof FileUpload + * @type {string} + * @memberof DiscountFixedRepeatDurationCreate */ - upload: S3FileUploadMultipart; + starts_at?: string | null; /** * * @type {string} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - version: string | null; + ends_at?: string | null; /** * - * @type {boolean} - * @memberof FileUpload + * @type {number} + * @memberof DiscountFixedRepeatDurationCreate */ - is_uploaded?: boolean; + max_redemptions?: number | null; /** - * - * @type {FileServiceTypes} - * @memberof FileUpload + * List of product IDs the discount can be applied to. + * @type {Array} + * @memberof DiscountFixedRepeatDurationCreate */ - service: FileServiceTypes; + products?: Array | null; /** - * + * The organization ID. * @type {string} - * @memberof FileUpload + * @memberof DiscountFixedRepeatDurationCreate */ - readonly size_readable: string; + organization_id?: string | null; } /** - * - * @export - * @interface FileUploadCompleted + * @type DiscountIDFilter + * Filter by discount ID. + * @export */ -export interface FileUploadCompleted { - /** - * - * @type {string} - * @memberof FileUploadCompleted - */ - id: string; - /** - * - * @type {string} - * @memberof FileUploadCompleted - */ - path: string; - /** - * - * @type {Array} - * @memberof FileUploadCompleted - */ - parts: Array; -} +export type DiscountIDFilter = Array | string; + /** - * + * @type DiscountIDFilter1 + * Filter by discount ID. * @export - * @interface Funding */ -export interface Funding { - /** - * - * @type {CurrencyAmount} - * @memberof Funding - */ - funding_goal?: CurrencyAmount | null; - /** - * - * @type {CurrencyAmount} - * @memberof Funding - */ - pledges_sum?: CurrencyAmount | null; -} +export type DiscountIDFilter1 = Array | string; + /** - * + * Schema for a percentage discount that is applied once or forever. * @export - * @interface GitHubInvitesBenefitOrganization + * @interface DiscountPercentageOnceForeverDuration */ -export interface GitHubInvitesBenefitOrganization { +export interface DiscountPercentageOnceForeverDuration { /** * - * @type {string} - * @memberof GitHubInvitesBenefitOrganization + * @type {DiscountDuration} + * @memberof DiscountPercentageOnceForeverDuration */ - name: string; + duration: DiscountDuration; /** * - * @type {boolean} - * @memberof GitHubInvitesBenefitOrganization + * @type {DiscountType} + * @memberof DiscountPercentageOnceForeverDuration */ - is_personal: boolean; + type: DiscountType; /** * + * @type {number} + * @memberof DiscountPercentageOnceForeverDuration + */ + basis_points: number; + /** + * Creation timestamp of the object. * @type {string} - * @memberof GitHubInvitesBenefitOrganization + * @memberof DiscountPercentageOnceForeverDuration */ - plan_name: string; + created_at: string; /** * - * @type {boolean} - * @memberof GitHubInvitesBenefitOrganization + * @type {string} + * @memberof DiscountPercentageOnceForeverDuration */ - is_free: boolean; -} -/** - * - * @export - * @interface GitHubInvitesBenefitRepositories - */ -export interface GitHubInvitesBenefitRepositories { + modified_at: string | null; /** - * - * @type {Array} - * @memberof GitHubInvitesBenefitRepositories + * The ID of the object. + * @type {string} + * @memberof DiscountPercentageOnceForeverDuration */ - repositories: Array; + id: string; /** * - * @type {Array} - * @memberof GitHubInvitesBenefitRepositories + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountPercentageOnceForeverDuration */ - organizations: Array; -} -/** - * - * @export - * @interface GitHubInvitesBenefitRepository - */ -export interface GitHubInvitesBenefitRepository { + metadata: { [key: string]: MetadataValue; }; /** - * + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof GitHubInvitesBenefitRepository + * @memberof DiscountPercentageOnceForeverDuration */ - repository_owner: string; + name: string; /** * * @type {string} - * @memberof GitHubInvitesBenefitRepository + * @memberof DiscountPercentageOnceForeverDuration */ - repository_name: string; -} -/** - * - * @export - * @interface GithubUser - */ -export interface GithubUser { + code: string | null; /** * * @type {string} - * @memberof GithubUser + * @memberof DiscountPercentageOnceForeverDuration */ - username: string; + starts_at: string | null; /** * * @type {string} - * @memberof GithubUser + * @memberof DiscountPercentageOnceForeverDuration */ - avatar_url: string; -} -/** - * - * @export - * @interface HTTPValidationError - */ -export interface HTTPValidationError { + ends_at: string | null; /** * - * @type {Array} - * @memberof HTTPValidationError + * @type {number} + * @memberof DiscountPercentageOnceForeverDuration */ - detail?: Array; -} -/** - * @type Id - * @export - */ -export type Id = string; - -/** - * - * @export - * @interface InstallationCreate - */ -export interface InstallationCreate { + max_redemptions: number | null; /** - * + * Number of times the discount has been redeemed. * @type {number} - * @memberof InstallationCreate + * @memberof DiscountPercentageOnceForeverDuration */ - installation_id: number; + redemptions_count: number; /** * The organization ID. * @type {string} - * @memberof InstallationCreate + * @memberof DiscountPercentageOnceForeverDuration */ organization_id: string; + /** + * + * @type {Array} + * @memberof DiscountPercentageOnceForeverDuration + */ + products: Array; } -/** - * - * @export - */ -export const Interval = { - YEAR: 'year', - MONTH: 'month', - WEEK: 'week', - DAY: 'day', - HOUR: 'hour' -} as const; -export type Interval = typeof Interval[keyof typeof Interval]; /** * * @export - * @interface IntrospectTokenResponse + * @interface DiscountPercentageOnceForeverDurationBase */ -export interface IntrospectTokenResponse { +export interface DiscountPercentageOnceForeverDurationBase { /** * - * @type {boolean} - * @memberof IntrospectTokenResponse + * @type {DiscountDuration} + * @memberof DiscountPercentageOnceForeverDurationBase */ - active: boolean; + duration: DiscountDuration; /** * - * @type {string} - * @memberof IntrospectTokenResponse + * @type {DiscountType} + * @memberof DiscountPercentageOnceForeverDurationBase */ - client_id: string; + type: DiscountType; /** * + * @type {number} + * @memberof DiscountPercentageOnceForeverDurationBase + */ + basis_points: number; + /** + * Creation timestamp of the object. * @type {string} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - token_type: IntrospectTokenResponseTokenTypeEnum; + created_at: string; /** * * @type {string} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - scope: string; + modified_at: string | null; + /** + * The ID of the object. + * @type {string} + * @memberof DiscountPercentageOnceForeverDurationBase + */ + id: string; /** * - * @type {SubType} - * @memberof IntrospectTokenResponse + * @type {{ [key: string]: MetadataValue; }} + * @memberof DiscountPercentageOnceForeverDurationBase */ - sub_type: SubType; + metadata: { [key: string]: MetadataValue; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. + * @type {string} + * @memberof DiscountPercentageOnceForeverDurationBase + */ + name: string; /** * * @type {string} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - sub: string; + code: string | null; /** * * @type {string} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - aud: string; + starts_at: string | null; /** * * @type {string} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - iss: string; + ends_at: string | null; /** * * @type {number} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - exp: number; + max_redemptions: number | null; /** - * + * Number of times the discount has been redeemed. * @type {number} - * @memberof IntrospectTokenResponse + * @memberof DiscountPercentageOnceForeverDurationBase */ - iat: number; -} - + redemptions_count: number; + /** + * The organization ID. + * @type {string} + * @memberof DiscountPercentageOnceForeverDurationBase + */ + organization_id: string; +} -/** - * @export - */ -export const IntrospectTokenResponseTokenTypeEnum = { - ACCESS_TOKEN: 'access_token', - REFRESH_TOKEN: 'refresh_token' -} as const; -export type IntrospectTokenResponseTokenTypeEnum = typeof IntrospectTokenResponseTokenTypeEnum[keyof typeof IntrospectTokenResponseTokenTypeEnum]; /** - * + * Schema to create a percentage discount that is applied once or forever. * @export - * @interface Issue + * @interface DiscountPercentageOnceForeverDurationCreate */ -export interface Issue { +export interface DiscountPercentageOnceForeverDurationCreate { /** * - * @type {string} - * @memberof Issue + * @type {DiscountDuration} + * @memberof DiscountPercentageOnceForeverDurationCreate */ - id: string; + duration: DiscountDuration; /** * - * @type {Platforms} - * @memberof Issue + * @type {DiscountType} + * @memberof DiscountPercentageOnceForeverDurationCreate */ - platform: Platforms; + type: DiscountType; /** - * GitHub #number + * Discount percentage in basis points. + * + * A basis point is 1/100th of a percent. + * For example, to create a 25.5% discount, set this to 2550. * @type {number} - * @memberof Issue + * @memberof DiscountPercentageOnceForeverDurationCreate */ - number: number; + basis_points: number; /** - * GitHub issue title + * Key-value object allowing you to store additional information. + * + * The key must be a string with a maximum length of **40 characters**. + * The value must be either: + * + * * A string with a maximum length of **500 characters** + * * An integer + * * A boolean + * + * You can store up to **50 key-value pairs**. + * @type {{ [key: string]: MetadataValue1; }} + * @memberof DiscountPercentageOnceForeverDurationCreate + */ + metadata?: { [key: string]: MetadataValue1; }; + /** + * Name of the discount. Will be displayed to the customer when the discount is applied. * @type {string} - * @memberof Issue + * @memberof DiscountPercentageOnceForeverDurationCreate */ - title: string; + name: string; /** * * @type {string} - * @memberof Issue + * @memberof DiscountPercentageOnceForeverDurationCreate */ - body?: string | null; + code?: string | null; /** * - * @type {number} - * @memberof Issue + * @type {string} + * @memberof DiscountPercentageOnceForeverDurationCreate */ - comments?: number | null; + starts_at?: string | null; /** * - * @type {Array