UNPKG

@coursebuilder/core

Version:

Core package for Course Builder

1 lines 301 kB
{"version":3,"sources":["../src/types.ts","../src/lib/pricing/stripe-checkout.ts","../../../node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.mjs","../src/schemas/stripe/checkout-session-metadata.ts","../src/lib/pricing/format-prices-for-product.ts","../src/lib/pricing/determine-coupon-to-apply.ts"],"sourcesContent":["import { AuthConfig } from '@auth/core'\nimport { NodemailerConfig } from '@auth/core/providers/nodemailer'\nimport { type CoreMessage } from 'ai'\nimport { CookieSerializeOptions } from 'cookie'\nimport { Inngest } from 'inngest'\nimport Stripe from 'stripe'\n\nimport { CourseBuilderAdapter } from './adapters'\nimport {\n\tCheckoutParams,\n\tCheckoutParamsSchema,\n} from './lib/pricing/stripe-checkout'\nimport { Cookie } from './lib/utils/cookie'\nimport { LoggerInstance } from './lib/utils/logger'\nimport { EmailListConfig, ProviderType, TranscriptionConfig } from './providers'\nimport {\n\tCoupon,\n\tMerchantCoupon,\n\tPrice,\n\tProduct,\n\tPurchase,\n\tResourceProgress,\n\tUser,\n} from './schemas'\nimport { PurchaseInfo } from './schemas/purchase-info'\nimport { SubscriptionInfo } from './schemas/subscription-info'\n\nexport type Awaitable<T> = T | PromiseLike<T>\n\nexport interface ResponseInternal<\n\tBody extends string | Record<string, any> | any[] | null = any,\n> {\n\tstatus?: number\n\theaders?: Headers | HeadersInit\n\tbody?: Body\n\tredirect?: string\n\tcookies?: Cookie[]\n}\n\nexport interface CookieOption {\n\tname: string\n\toptions: CookieSerializeOptions\n}\n\nexport type CourseBuilderAction =\n\t| 'webhook'\n\t| 'srt'\n\t| 'session'\n\t| 'subscribe-to-list'\n\t| 'checkout'\n\t| 'redeem'\n\t| 'prices-formatted'\n\t| 'subscriber'\n\t| 'purchases'\n\t| 'lookup'\n\t| 'claimed'\n\t| 'nameUpdate'\n\t| 'transfer'\n\t| 'refund'\n\t| 'create-magic-link'\n\nexport interface RequestInternal {\n\turl: URL\n\tmethod: 'POST' | 'GET'\n\tcookies?: Partial<Record<string, string>>\n\theaders?: Record<string, any>\n\tquery?: Record<string, any>\n\tbody?: Record<string, any>\n\taction: CourseBuilderAction\n\tproviderId?: string\n\terror?: string\n}\n\nexport interface PaymentsProviderConfig {\n\tid: string\n\tname: string\n\ttype: 'payment'\n\toptions: PaymentsProviderConsumerConfig\n\tgetBillingPortalUrl: (\n\t\tcustomerId: string,\n\t\treturnUrl: string,\n\t) => Promise<string>\n\tgetSubscription: (subscriptionId: string) => Promise<Stripe.Subscription>\n\tgetSubscriptionInfo: (\n\t\tcheckoutSessionId: string,\n\t\tadapter: CourseBuilderAdapter,\n\t) => Promise<SubscriptionInfo>\n\tgetPurchaseInfo: (\n\t\tcheckoutSessionId: string,\n\t\tadapter: CourseBuilderAdapter,\n\t) => Promise<PurchaseInfo>\n\tcreateCheckoutSession: (\n\t\tcheckoutParams: CheckoutParams,\n\t\tadapter?: CourseBuilderAdapter,\n\t) => Promise<{ redirect: string; status: number }>\n\trefundCharge: (chargeId: string) => Promise<Stripe.Refund>\n\tgetCustomer: (customerId: string) => Promise<Stripe.Customer>\n\tupdateCustomer: (\n\t\tcustomerId: string,\n\t\tcustomer: { name: string; email: string; metadata?: Record<string, any> },\n\t) => Promise<void>\n\tgetProduct(productId: string): Promise<Stripe.Response<Stripe.Product>>\n\tgetPrice(priceId: string): Promise<Stripe.Response<Stripe.Price>>\n\tupdateProduct<TProductUpdate = Stripe.Product>(\n\t\tproductId: string,\n\t\tproductUpdate: Partial<TProductUpdate>,\n\t): Promise<void>\n\tupdatePrice<TPriceUpdate = Stripe.Price>(\n\t\tpriceId: string,\n\t\tpriceUpdate: Partial<TPriceUpdate>,\n\t): Promise<void>\n\tcreatePrice(\n\t\tprice: Stripe.PriceCreateParams,\n\t): Promise<Stripe.Response<Stripe.Price>>\n\tcreateProduct(\n\t\tproduct: Stripe.ProductCreateParams,\n\t): Promise<Stripe.Response<Stripe.Product>>\n}\n\nexport type PaymentsProviderConsumerConfig = Omit<\n\tPartial<PaymentsProviderConfig>,\n\t'options' | 'type'\n> & {\n\tpaymentsAdapter: PaymentsAdapter\n\terrorRedirectUrl: string\n\tcancelUrl: string\n\tbaseSuccessUrl: string\n}\n\nexport interface PaymentsAdapter {\n\t/**\n\t * Returns the percent off for a given coupon\n\t * @param identifier\n\t */\n\tgetCouponPercentOff(identifier: string): Promise<number>\n\n\t/**\n\t * Returns a coupon id.\n\t *\n\t * TODO: these use the stripe types and we probably want to use an\n\t * internal interface so that we can think about different providers\n\t * in the future.\n\t * @param params\n\t */\n\tcreateCoupon(params: Stripe.CouponCreateParams): Promise<string>\n\n\t/**\n\t * Returns a promotion code.\n\t * @param params\n\t */\n\tcreatePromotionCode(params: Stripe.PromotionCodeCreateParams): Promise<string>\n\n\t/**\n\t * Returns the URL to redirect to for a checkout session.\n\t * @param params\n\t */\n\tcreateCheckoutSession(\n\t\tparams: Stripe.Checkout.SessionCreateParams,\n\t): Promise<string | null>\n\n\tgetCheckoutSession(sessionId: string): Promise<Stripe.Checkout.Session>\n\n\tcreateCustomer(params: Stripe.CustomerCreateParams): Promise<string>\n\tverifyWebhookSignature(rawBody: string, sig: string): Promise<boolean>\n\tgetCustomer(customerId: string): Promise<Stripe.Customer>\n\tupdateCustomer(\n\t\tcustomerId: string,\n\t\tcustomer: { name: string; email: string; metadata?: Record<string, any> },\n\t): Promise<void>\n\trefundCharge(chargeId: string): Promise<Stripe.Refund>\n\tgetProduct(productId: string): Promise<Stripe.Response<Stripe.Product>>\n\tgetPrice(priceId: string): Promise<Stripe.Response<Stripe.Price>>\n\tupdateProduct<TProductUpdate = Stripe.Product>(\n\t\tproductId: string,\n\t\tproduct: Partial<TProductUpdate>,\n\t): Promise<void>\n\tupdatePrice<TPriceUpdate = Stripe.Price>(\n\t\tpriceId: string,\n\t\tpriceUpdate: Partial<TPriceUpdate>,\n\t): Promise<void>\n\tcreatePrice(\n\t\tprice: Stripe.PriceCreateParams,\n\t): Promise<Stripe.Response<Stripe.Price>>\n\tcreateProduct(\n\t\tproduct: Stripe.ProductCreateParams,\n\t): Promise<Stripe.Response<Stripe.Product>>\n\tgetSubscription(subscriptionId: string): Promise<Stripe.Subscription>\n\tgetBillingPortalUrl(customerId: string, returnUrl: string): Promise<string>\n}\n\nexport type InternalProvider<T = ProviderType> = T extends 'transcription'\n\t? TranscriptionConfig\n\t: T extends 'email-list'\n\t\t? EmailListConfig\n\t\t: T extends 'payment'\n\t\t\t? PaymentsProviderConfig\n\t\t\t: T extends 'email'\n\t\t\t\t? NodemailerConfig\n\t\t\t\t: never\n\nexport interface InternalOptions<TProviderType = ProviderType> {\n\tproviders: InternalProvider[]\n\turl: URL\n\taction: CourseBuilderAction\n\tprovider: InternalProvider<TProviderType>\n\tdebug: boolean\n\tlogger: LoggerInstance\n\tadapter: Required<CourseBuilderAdapter> | undefined\n\tcookies: Record<keyof CookiesOptions, CookieOption>\n\tbasePath: string\n\tinngest: Inngest\n\tcallbacks: CallbacksOptions\n\tgetCurrentUser?: () => Promise<User | null>\n\tauthConfig: AuthConfig\n\tbaseUrl: string\n}\n\nexport interface CookieOption {\n\tname: string\n\toptions: CookieSerializeOptions\n}\n\nexport interface CookiesOptions {\n\tck_subscriber_id?: Partial<CookieOption>\n}\n\nexport interface DefaultCourseBuilderSession {}\n\nexport interface CourseBuilderSession extends DefaultCourseBuilderSession {}\n\nexport interface CallbacksOptions {\n\tsession: (\n\t\tparams: any,\n\t) => Awaitable<CourseBuilderSession | DefaultCourseBuilderSession>\n}\n\nexport type FunctionCall = {\n\targuments: Record<string, any>\n\tname: string // function name.\n}\n\nexport type AIMessage = CoreMessage & {\n\tcreatedAt?: Date\n\tid?: string\n}\n\nexport type AIError = { error: string }\n\nexport type AIOutput = AIMessage | AIError\n\nexport interface ProgressWriter {\n\twriteResponseInChunks(\n\t\tstreamingResponse: Response | ReadableStream,\n\t): Promise<AIOutput>\n\tpublishMessage(message: string): Promise<void>\n}\n\ntype MerchantCouponWithCountry = MerchantCoupon & {\n\tcountry?: string | undefined\n}\n\nexport type MinimalMerchantCoupon = Omit<\n\tMerchantCouponWithCountry,\n\t'identifier' | 'merchantAccountId'\n>\n\ntype ProductWithPrices = Product & { prices?: Price[] }\n\nexport type FormattedPrice = {\n\tid: string\n\tquantity: number\n\tunitPrice: number\n\tfullPrice: number\n\tfixedDiscountForUpgrade: number\n\tcalculatedPrice: number\n\tavailableCoupons: Array<\n\t\tOmit<MerchantCouponWithCountry, 'identifier'> | undefined\n\t>\n\tappliedMerchantCoupon?: MinimalMerchantCoupon\n\tupgradeFromPurchaseId?: string\n\tupgradeFromPurchase?: Purchase\n\tupgradedProduct?: ProductWithPrices | null\n\tbulk: boolean\n\tusedCouponId?: string\n\tusedCoupon?: Coupon | null\n\tdefaultCoupon?: Coupon | null\n}\n\nexport type FormatPricesForProductOptions = {\n\tproductId?: string\n\tcountry?: string\n\tquantity?: number\n\tmerchantCouponId?: string\n\tctx: CourseBuilderAdapter\n\tupgradeFromPurchaseId?: string\n\tuserId?: string\n\tautoApplyPPP?: boolean\n\tusedCouponId?: string\n}\n\nexport type CommerceProps = {\n\tcouponIdFromCoupon?: string\n\tcouponFromCode?: CouponForCode\n\tuserId?: string\n\tpurchases?: Purchase[]\n\tproducts?: Product[]\n\tallowPurchase?: boolean\n\tcountry?: string\n}\n\nexport type CouponForCode = Coupon & {\n\tisValid: boolean\n\tisRedeemable: boolean\n}\n\nexport type PricingData = {\n\tformattedPrice?: FormattedPrice | null\n\tpurchaseToUpgrade?: Purchase | null\n\tquantityAvailable: number\n}\n\nexport type PricingOptions = {\n\twithImage: boolean\n\twithTitle: boolean\n\twithGuaranteeBadge: boolean\n\tisLiveEvent: boolean\n\tisCohort: boolean\n\tisPPPEnabled: boolean\n\tteamQuantityLimit: number\n\tallowTeamPurchase: boolean\n\tcancelUrl: string\n}\n\nexport { CheckoutParamsSchema, type CheckoutParams }\n","import { add } from 'date-fns'\nimport { CourseBuilderAdapter } from 'src/adapters'\nimport { CheckoutSessionMetadataSchema } from 'src/schemas/stripe/checkout-session-metadata'\nimport Stripe from 'stripe'\nimport { z } from 'zod'\n\nimport { first, isEmpty } from '@coursebuilder/nodash'\n\nimport { Product, Purchase, UpgradableProduct } from '../../schemas'\nimport { PaymentsAdapter, PaymentsProviderConsumerConfig } from '../../types'\nimport { getFixedDiscountForIndividualUpgrade } from './format-prices-for-product'\nimport { getCalculatedPrice } from './get-calculated-price'\n\nexport const CheckoutParamsSchema = z.object({\n\tip_address: z.string().optional(),\n\tproductId: z.string(),\n\tquantity: z.coerce\n\t\t.number()\n\t\t.optional()\n\t\t.transform((val) => Number(val) || 0),\n\tcountry: z.string().optional(),\n\tcouponId: z.string().optional(),\n\tuserId: z.string().optional(),\n\tupgradeFromPurchaseId: z.string().optional(),\n\tbulk: z.preprocess((val) => {\n\t\treturn val === 'false' ? false : Boolean(val)\n\t}, z.coerce.boolean()),\n\tcancelUrl: z.string(),\n\tusedCouponId: z.string().optional(),\n\torganizationId: z.string().optional(),\n})\n\nexport type CheckoutParams = z.infer<typeof CheckoutParamsSchema>\n\nconst buildSearchParams = (params: object) => {\n\t// implementing this instead of using `URLSearchParams` because that API\n\t// does URL encoding of values in the URL like the curly braces in\n\t// `session_id={CHECKOUT_SESSION_ID}` which needs to get passed to stripe\n\t// as is.\n\tif (isEmpty(params)) {\n\t\treturn ''\n\t} else {\n\t\treturn Object.entries(params)\n\t\t\t.map(([key, value]) => {\n\t\t\t\treturn `${key}=${value}`\n\t\t\t})\n\t\t\t.join('&')\n\t}\n}\n\n/**\n * Given a specific user we want to lookup their Stripe\n * customer ID and if one doesn't exist we will\n * create it.\n * @param userId\n * @param adapter\n * @param paymentsAdapter\n */\nasync function findOrCreateStripeCustomerId(\n\tuserId: string,\n\tadapter: CourseBuilderAdapter,\n\tpaymentsAdapter: PaymentsAdapter,\n) {\n\tconst user = await adapter.getUser?.(userId)\n\n\tif (user) {\n\t\tconst merchantCustomer = await adapter.getMerchantCustomerForUserId(user.id)\n\t\tconst customerId =\n\t\t\tuser && merchantCustomer ? merchantCustomer.identifier : false\n\n\t\tif (customerId) {\n\t\t\treturn customerId\n\t\t} else {\n\t\t\tconst merchantAccount = await adapter.getMerchantAccount({\n\t\t\t\tprovider: 'stripe',\n\t\t\t})\n\t\t\tif (merchantAccount) {\n\t\t\t\tconst customerId = await paymentsAdapter.createCustomer({\n\t\t\t\t\temail: user.email,\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tawait adapter.createMerchantCustomer({\n\t\t\t\t\tidentifier: customerId,\n\t\t\t\t\tmerchantAccountId: merchantAccount.id,\n\t\t\t\t\tuserId,\n\t\t\t\t})\n\t\t\t\treturn customerId\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nexport class CheckoutError extends Error {\n\tcouponId?: string\n\tproductId: string\n\n\tconstructor(message: string, productId: string, couponId?: string) {\n\t\tsuper(message)\n\t\tthis.name = 'CheckoutError'\n\t\tthis.couponId = couponId\n\t\tthis.productId = productId\n\t}\n}\n\nconst buildCouponNameWithProductName = (\n\tpre: string,\n\tproductName: string,\n\tpost: string,\n): string => {\n\t// Calculate the total length without the ellipsis\n\tconst totalLength = pre.length + productName.length + post.length\n\n\t// If total length exceeds 40 characters\n\tif (totalLength > 40) {\n\t\t// Calculate the number of characters to truncate from productName\n\t\tconst excess = totalLength - 40 + 3 // 3 is for the length of ellipsis \"...\"\n\t\tproductName = productName.slice(0, -excess) + '...'\n\t}\n\n\t// Return the concatenated string\n\treturn pre + productName + post\n}\n\nconst buildCouponName = (\n\tupgradeFromPurchase:\n\t\t| (Purchase & {\n\t\t\t\tproduct: Product | null\n\t\t })\n\t\t| null,\n\tproductId: string,\n\tavailableUpgrade: UpgradableProduct | null | undefined,\n\tpurchaseWillBeRestricted: boolean,\n\tstripeCouponPercentOff: number,\n) => {\n\tlet couponName = null\n\n\tif (\n\t\tupgradeFromPurchase?.status === 'Restricted' &&\n\t\t!purchaseWillBeRestricted &&\n\t\tupgradeFromPurchase.productId === productId\n\t) {\n\t\t// if its the same productId and we are going from PPP to Unrestricted\n\t\tcouponName = 'Unrestricted'\n\t} else if (availableUpgrade && upgradeFromPurchase?.status === 'Valid') {\n\t\t// if there is an availableUpgrade (e.g. Core -> Bundle) and the original purchase wasn't region restricted\n\t\tcouponName = buildCouponNameWithProductName(\n\t\t\t'Upgrade from ',\n\t\t\tupgradeFromPurchase.product?.name || '',\n\t\t\t'',\n\t\t)\n\t} else if (\n\t\tavailableUpgrade &&\n\t\tupgradeFromPurchase?.status === 'Restricted' &&\n\t\tpurchaseWillBeRestricted\n\t) {\n\t\t// if there is an availableUpgrade (e.g. Core -> Bundle) and we are staying PPP\n\t\t// betterCouponName = `Upgrade from ${\n\t\t// upgradeFromPurchase.product.name\n\t\t// } + PPP ${stripeCouponPercentOff * 100}% off`\n\t\tcouponName = buildCouponNameWithProductName(\n\t\t\t'Upgrade from ',\n\t\t\tupgradeFromPurchase.product?.name || '',\n\t\t\t` + PPP ${Math.floor(stripeCouponPercentOff * 100)}% off`,\n\t\t)\n\t} else if (\n\t\tavailableUpgrade &&\n\t\tupgradeFromPurchase?.status === 'Restricted' &&\n\t\t!purchaseWillBeRestricted\n\t) {\n\t\t// if there is an availableUpgrade (e.g. Core -> Bundle) and we are going from PPP to Unrestricted\n\t\t// couponName = `Unrestricted Upgrade from ${upgradeFromPurchase.product.name}`\n\t\tcouponName = buildCouponNameWithProductName(\n\t\t\t'Unrestricted Upgrade from ',\n\t\t\tupgradeFromPurchase.product?.name || '',\n\t\t\t'',\n\t\t)\n\t} else {\n\t\t// we don't expect to hit this case\n\t\tcouponName = 'Discount'\n\t}\n\n\treturn couponName\n}\n\nconst LoadedProductSchema = z.object({\n\tid: z.string(),\n})\n\nexport async function stripeCheckout({\n\tparams,\n\tconfig,\n\tadapter,\n}: {\n\tparams: CheckoutParams\n\tconfig: PaymentsProviderConsumerConfig\n\tadapter?: CourseBuilderAdapter\n}): Promise<any> {\n\ttry {\n\t\tif (!adapter) {\n\t\t\tthrow new Error('Adapter is required')\n\t\t}\n\n\t\tconst ip_address = params.ip_address\n\n\t\tlet errorRedirectUrl: string | undefined = undefined\n\n\t\ttry {\n\t\t\tconst {\n\t\t\t\tproductId,\n\t\t\t\tquantity: queryQuantity = 1,\n\t\t\t\tcouponId,\n\t\t\t\tuserId,\n\t\t\t\tupgradeFromPurchaseId,\n\t\t\t\tbulk = false,\n\t\t\t\tusedCouponId,\n\t\t\t} = params\n\n\t\t\terrorRedirectUrl = config.errorRedirectUrl\n\t\t\tconst cancelUrl = params.cancelUrl || config.cancelUrl\n\n\t\t\tconst quantity = Number(queryQuantity)\n\n\t\t\tconst user = userId ? await adapter.getUser?.(userId as string) : false\n\n\t\t\tconsole.log('user', user)\n\n\t\t\tconst upgradeFromPurchase = upgradeFromPurchaseId\n\t\t\t\t? await adapter.getPurchase(upgradeFromPurchaseId)\n\t\t\t\t: null\n\n\t\t\tconst availableUpgrade =\n\t\t\t\tquantity === 1 && upgradeFromPurchase\n\t\t\t\t\t? await adapter.getUpgradableProducts({\n\t\t\t\t\t\t\tupgradableFromId: upgradeFromPurchase.productId,\n\t\t\t\t\t\t\tupgradableToId: productId as string,\n\t\t\t\t\t\t})\n\t\t\t\t\t: null\n\n\t\t\tconst customerId = user\n\t\t\t\t? await findOrCreateStripeCustomerId(\n\t\t\t\t\t\tuser.id,\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tconfig.paymentsAdapter,\n\t\t\t\t\t)\n\t\t\t\t: false\n\n\t\t\tconsole.log('customerId', customerId)\n\n\t\t\tconst loadedProduct = await adapter.getProduct(productId)\n\n\t\t\tconst result = LoadedProductSchema.safeParse(loadedProduct)\n\n\t\t\tif (!result.success) {\n\t\t\t\tconst errorMessages = result.error.errors\n\t\t\t\t\t.map((err) => err.message)\n\t\t\t\t\t.join(', ')\n\n\t\t\t\t// Send `errorMessages` to Sentry so we can deal with it right away.\n\t\t\t\tconsole.error(`No product (${productId}) was found (${errorMessages})`)\n\n\t\t\t\tthrow new CheckoutError(\n\t\t\t\t\t`No product was found`,\n\t\t\t\t\tString(loadedProduct?.id),\n\t\t\t\t\tcouponId as string,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst loadedProductData = result.data\n\n\t\t\tconst merchantProduct = await adapter.getMerchantProductForProductId(\n\t\t\t\tloadedProductData.id,\n\t\t\t)\n\n\t\t\tconst merchantProductIdentifier = merchantProduct?.identifier\n\n\t\t\tif (!merchantProduct) {\n\t\t\t\tthrow new Error('No merchant product found')\n\t\t\t}\n\n\t\t\tconst merchantPrice = await adapter.getMerchantPriceForProductId(\n\t\t\t\tmerchantProduct.id,\n\t\t\t)\n\n\t\t\tconst merchantPriceIdentifier = merchantPrice?.identifier\n\n\t\t\tif (!merchantPriceIdentifier || !merchantProductIdentifier) {\n\t\t\t\tthrow new Error('No merchant price or product found')\n\t\t\t}\n\n\t\t\tconst stripePrice = await config.paymentsAdapter.getPrice(\n\t\t\t\tmerchantPriceIdentifier,\n\t\t\t)\n\n\t\t\tconst isRecurring = stripePrice?.recurring\n\n\t\t\tconst merchantCoupon = couponId\n\t\t\t\t? await adapter.getMerchantCoupon(couponId as string)\n\t\t\t\t: null\n\n\t\t\tconst stripeCouponPercentOff =\n\t\t\t\tmerchantCoupon && merchantCoupon.identifier\n\t\t\t\t\t? await config.paymentsAdapter.getCouponPercentOff(\n\t\t\t\t\t\t\tmerchantCoupon.identifier,\n\t\t\t\t\t\t)\n\t\t\t\t\t: 0\n\n\t\t\tlet discounts = []\n\t\t\tlet appliedPPPStripeCouponId: string | undefined | null = undefined\n\t\t\tlet upgradedFromPurchaseId: string | undefined | null = undefined\n\n\t\t\tconst isUpgrade = Boolean(\n\t\t\t\t(availableUpgrade || upgradeFromPurchase?.status === 'Restricted') &&\n\t\t\t\t\tupgradeFromPurchase,\n\t\t\t)\n\n\t\t\tconst TWELVE_FOUR_HOURS_FROM_NOW = Math.floor(\n\t\t\t\tadd(new Date(), { hours: 12 }).getTime() / 1000,\n\t\t\t)\n\n\t\t\tif (isUpgrade && upgradeFromPurchase && loadedProduct && customerId) {\n\t\t\t\tconst purchaseWillBeRestricted = merchantCoupon?.type === 'ppp'\n\t\t\t\tappliedPPPStripeCouponId = merchantCoupon?.identifier\n\t\t\t\tupgradedFromPurchaseId = upgradeFromPurchase.id\n\n\t\t\t\tconst fixedDiscountForIndividualUpgrade =\n\t\t\t\t\tawait getFixedDiscountForIndividualUpgrade({\n\t\t\t\t\t\tpurchaseToBeUpgraded: upgradeFromPurchase,\n\t\t\t\t\t\tproductToBePurchased: loadedProduct,\n\t\t\t\t\t\tpurchaseWillBeRestricted,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tctx: adapter,\n\t\t\t\t\t})\n\n\t\t\t\tconst productPrice = await adapter.getPriceForProduct(loadedProduct.id)\n\n\t\t\t\tconst fullPrice = productPrice?.unitAmount || 0\n\t\t\t\tconst calculatedPrice = getCalculatedPrice({\n\t\t\t\t\tunitPrice: fullPrice,\n\t\t\t\t\tpercentOfDiscount: stripeCouponPercentOff,\n\t\t\t\t\tquantity: 1,\n\t\t\t\t\tfixedDiscount: fixedDiscountForIndividualUpgrade,\n\t\t\t\t})\n\n\t\t\t\tconst upgradeFromProduct = await adapter.getProduct(\n\t\t\t\t\tupgradeFromPurchase.productId,\n\t\t\t\t)\n\n\t\t\t\tif (fixedDiscountForIndividualUpgrade > 0) {\n\t\t\t\t\tconst couponName = buildCouponName(\n\t\t\t\t\t\t{ ...upgradeFromPurchase, product: upgradeFromProduct },\n\t\t\t\t\t\tproductId,\n\t\t\t\t\t\tfirst(availableUpgrade),\n\t\t\t\t\t\tpurchaseWillBeRestricted,\n\t\t\t\t\t\tstripeCouponPercentOff,\n\t\t\t\t\t)\n\n\t\t\t\t\tconst amount_off_in_cents = (fullPrice - calculatedPrice) * 100\n\n\t\t\t\t\tconst couponId = await config.paymentsAdapter.createCoupon({\n\t\t\t\t\t\tamount_off: amount_off_in_cents,\n\t\t\t\t\t\tname: couponName,\n\t\t\t\t\t\tmax_redemptions: 1,\n\t\t\t\t\t\tredeem_by: TWELVE_FOUR_HOURS_FROM_NOW,\n\t\t\t\t\t\tcurrency: 'USD',\n\t\t\t\t\t\tapplies_to: {\n\t\t\t\t\t\t\tproducts: [merchantProductIdentifier],\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\n\t\t\t\t\tdiscounts.push({\n\t\t\t\t\t\tcoupon: couponId,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else if (merchantCoupon && merchantCoupon.identifier) {\n\t\t\t\t// no ppp for bulk purchases\n\t\t\t\tconst isNotPPP = merchantCoupon.type !== 'ppp'\n\t\t\t\tif (isNotPPP || quantity === 1) {\n\t\t\t\t\tappliedPPPStripeCouponId =\n\t\t\t\t\t\tmerchantCoupon.type === 'ppp'\n\t\t\t\t\t\t\t? merchantCoupon?.identifier\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\tconst promotionCodeId =\n\t\t\t\t\t\tawait config.paymentsAdapter.createPromotionCode({\n\t\t\t\t\t\t\tcoupon: merchantCoupon.identifier,\n\t\t\t\t\t\t\tmax_redemptions: 1,\n\t\t\t\t\t\t\texpires_at: TWELVE_FOUR_HOURS_FROM_NOW,\n\t\t\t\t\t\t})\n\t\t\t\t\tdiscounts.push({\n\t\t\t\t\t\tpromotion_code: promotionCodeId,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!loadedProduct) {\n\t\t\t\tthrow new Error('No product was found')\n\t\t\t}\n\n\t\t\tlet successUrl: string = (() => {\n\t\t\t\tconst baseQueryParams = {\n\t\t\t\t\tsession_id: '{CHECKOUT_SESSION_ID}',\n\t\t\t\t\tprovider: 'stripe',\n\t\t\t\t}\n\n\t\t\t\tif (isRecurring) {\n\t\t\t\t\tconst queryParamString = buildSearchParams(baseQueryParams)\n\t\t\t\t\treturn `${config.baseSuccessUrl}/thanks/subscription?${queryParamString}`\n\t\t\t\t}\n\n\t\t\t\tif (isUpgrade) {\n\t\t\t\t\tconst queryParamString = buildSearchParams({\n\t\t\t\t\t\t...baseQueryParams,\n\t\t\t\t\t\tupgrade: 'true',\n\t\t\t\t\t})\n\t\t\t\t\treturn `${config.baseSuccessUrl}/welcome?${queryParamString}`\n\t\t\t\t} else {\n\t\t\t\t\tconst queryParamString = buildSearchParams(baseQueryParams)\n\n\t\t\t\t\treturn `${config.baseSuccessUrl}/thanks/purchase?${queryParamString}`\n\t\t\t\t}\n\t\t\t})()\n\n\t\t\tconst metadata = CheckoutSessionMetadataSchema.parse({\n\t\t\t\t...(Boolean(availableUpgrade && upgradeFromPurchase) && {\n\t\t\t\t\tupgradeFromPurchaseId: upgradeFromPurchaseId as string,\n\t\t\t\t}),\n\t\t\t\tbulk: Boolean(bulk) ? 'true' : quantity > 1 ? 'true' : 'false',\n\t\t\t\t...(appliedPPPStripeCouponId && { appliedPPPStripeCouponId }),\n\t\t\t\t...(upgradedFromPurchaseId && { upgradedFromPurchaseId }),\n\t\t\t\tcountry: params.country || process.env.DEFAULT_COUNTRY || 'US',\n\t\t\t\tip_address: ip_address || '',\n\t\t\t\t...(usedCouponId && { usedCouponId }),\n\t\t\t\tproductId: loadedProduct.id,\n\t\t\t\tproduct: loadedProduct.name,\n\t\t\t\t...(user && { userId: user.id }),\n\t\t\t\tsiteName: process.env.NEXT_PUBLIC_APP_NAME as string,\n\t\t\t\t...(params.organizationId && { organizationId: params.organizationId }),\n\t\t\t})\n\n\t\t\tconst sessionUrl = await config.paymentsAdapter.createCheckoutSession({\n\t\t\t\tdiscounts,\n\t\t\t\tline_items: [\n\t\t\t\t\t{\n\t\t\t\t\t\tprice: merchantPriceIdentifier,\n\t\t\t\t\t\tquantity: Number(quantity),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\texpires_at: TWELVE_FOUR_HOURS_FROM_NOW,\n\t\t\t\tmode: isRecurring ? 'subscription' : 'payment',\n\t\t\t\tsuccess_url: successUrl,\n\t\t\t\tcancel_url: cancelUrl,\n\t\t\t\t...(isRecurring\n\t\t\t\t\t? customerId\n\t\t\t\t\t\t? { customer: customerId }\n\t\t\t\t\t\t: user && { customer_email: user.email }\n\t\t\t\t\t: customerId\n\t\t\t\t\t\t? { customer: customerId }\n\t\t\t\t\t\t: { customer_creation: 'always' }),\n\t\t\t\tmetadata,\n\t\t\t\t...(!isRecurring && {\n\t\t\t\t\tpayment_intent_data: {\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tif (sessionUrl) {\n\t\t\t\treturn {\n\t\t\t\t\tredirect: sessionUrl,\n\t\t\t\t\tstatus: 303,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new CheckoutError(\n\t\t\t\t\t'no-stripe-session',\n\t\t\t\t\tloadedProduct.id,\n\t\t\t\t\tcouponId as string,\n\t\t\t\t)\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconsole.error('err', err)\n\t\t\tif (errorRedirectUrl) {\n\t\t\t\treturn {\n\t\t\t\t\tredirect: errorRedirectUrl,\n\t\t\t\t\tstatus: 303,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: { error: true, message: err.message },\n\t\t\t}\n\t\t}\n\t} catch (error: any) {\n\t\treturn {\n\t\t\tstatus: 500,\n\t\t\tbody: { error: true, message: error.message },\n\t\t}\n\t}\n}\n","var util;\n(function (util) {\n util.assertEqual = (val) => val;\n function assertIs(_arg) { }\n util.assertIs = assertIs;\n function assertNever(_x) {\n throw new Error();\n }\n util.assertNever = assertNever;\n util.arrayToEnum = (items) => {\n const obj = {};\n for (const item of items) {\n obj[item] = item;\n }\n return obj;\n };\n util.getValidEnumValues = (obj) => {\n const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== \"number\");\n const filtered = {};\n for (const k of validKeys) {\n filtered[k] = obj[k];\n }\n return util.objectValues(filtered);\n };\n util.objectValues = (obj) => {\n return util.objectKeys(obj).map(function (e) {\n return obj[e];\n });\n };\n util.objectKeys = typeof Object.keys === \"function\" // eslint-disable-line ban/ban\n ? (obj) => Object.keys(obj) // eslint-disable-line ban/ban\n : (object) => {\n const keys = [];\n for (const key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n keys.push(key);\n }\n }\n return keys;\n };\n util.find = (arr, checker) => {\n for (const item of arr) {\n if (checker(item))\n return item;\n }\n return undefined;\n };\n util.isInteger = typeof Number.isInteger === \"function\"\n ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban\n : (val) => typeof val === \"number\" && isFinite(val) && Math.floor(val) === val;\n function joinValues(array, separator = \" | \") {\n return array\n .map((val) => (typeof val === \"string\" ? `'${val}'` : val))\n .join(separator);\n }\n util.joinValues = joinValues;\n util.jsonStringifyReplacer = (_, value) => {\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n return value;\n };\n})(util || (util = {}));\nvar objectUtil;\n(function (objectUtil) {\n objectUtil.mergeShapes = (first, second) => {\n return {\n ...first,\n ...second, // second overwrites first\n };\n };\n})(objectUtil || (objectUtil = {}));\nconst ZodParsedType = util.arrayToEnum([\n \"string\",\n \"nan\",\n \"number\",\n \"integer\",\n \"float\",\n \"boolean\",\n \"date\",\n \"bigint\",\n \"symbol\",\n \"function\",\n \"undefined\",\n \"null\",\n \"array\",\n \"object\",\n \"unknown\",\n \"promise\",\n \"void\",\n \"never\",\n \"map\",\n \"set\",\n]);\nconst getParsedType = (data) => {\n const t = typeof data;\n switch (t) {\n case \"undefined\":\n return ZodParsedType.undefined;\n case \"string\":\n return ZodParsedType.string;\n case \"number\":\n return isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;\n case \"boolean\":\n return ZodParsedType.boolean;\n case \"function\":\n return ZodParsedType.function;\n case \"bigint\":\n return ZodParsedType.bigint;\n case \"symbol\":\n return ZodParsedType.symbol;\n case \"object\":\n if (Array.isArray(data)) {\n return ZodParsedType.array;\n }\n if (data === null) {\n return ZodParsedType.null;\n }\n if (data.then &&\n typeof data.then === \"function\" &&\n data.catch &&\n typeof data.catch === \"function\") {\n return ZodParsedType.promise;\n }\n if (typeof Map !== \"undefined\" && data instanceof Map) {\n return ZodParsedType.map;\n }\n if (typeof Set !== \"undefined\" && data instanceof Set) {\n return ZodParsedType.set;\n }\n if (typeof Date !== \"undefined\" && data instanceof Date) {\n return ZodParsedType.date;\n }\n return ZodParsedType.object;\n default:\n return ZodParsedType.unknown;\n }\n};\n\nconst ZodIssueCode = util.arrayToEnum([\n \"invalid_type\",\n \"invalid_literal\",\n \"custom\",\n \"invalid_union\",\n \"invalid_union_discriminator\",\n \"invalid_enum_value\",\n \"unrecognized_keys\",\n \"invalid_arguments\",\n \"invalid_return_type\",\n \"invalid_date\",\n \"invalid_string\",\n \"too_small\",\n \"too_big\",\n \"invalid_intersection_types\",\n \"not_multiple_of\",\n \"not_finite\",\n]);\nconst quotelessJson = (obj) => {\n const json = JSON.stringify(obj, null, 2);\n return json.replace(/\"([^\"]+)\":/g, \"$1:\");\n};\nclass ZodError extends Error {\n get errors() {\n return this.issues;\n }\n constructor(issues) {\n super();\n this.issues = [];\n this.addIssue = (sub) => {\n this.issues = [...this.issues, sub];\n };\n this.addIssues = (subs = []) => {\n this.issues = [...this.issues, ...subs];\n };\n const actualProto = new.target.prototype;\n if (Object.setPrototypeOf) {\n // eslint-disable-next-line ban/ban\n Object.setPrototypeOf(this, actualProto);\n }\n else {\n this.__proto__ = actualProto;\n }\n this.name = \"ZodError\";\n this.issues = issues;\n }\n format(_mapper) {\n const mapper = _mapper ||\n function (issue) {\n return issue.message;\n };\n const fieldErrors = { _errors: [] };\n const processError = (error) => {\n for (const issue of error.issues) {\n if (issue.code === \"invalid_union\") {\n issue.unionErrors.map(processError);\n }\n else if (issue.code === \"invalid_return_type\") {\n processError(issue.returnTypeError);\n }\n else if (issue.code === \"invalid_arguments\") {\n processError(issue.argumentsError);\n }\n else if (issue.path.length === 0) {\n fieldErrors._errors.push(mapper(issue));\n }\n else {\n let curr = fieldErrors;\n let i = 0;\n while (i < issue.path.length) {\n const el = issue.path[i];\n const terminal = i === issue.path.length - 1;\n if (!terminal) {\n curr[el] = curr[el] || { _errors: [] };\n // if (typeof el === \"string\") {\n // curr[el] = curr[el] || { _errors: [] };\n // } else if (typeof el === \"number\") {\n // const errorArray: any = [];\n // errorArray._errors = [];\n // curr[el] = curr[el] || errorArray;\n // }\n }\n else {\n curr[el] = curr[el] || { _errors: [] };\n curr[el]._errors.push(mapper(issue));\n }\n curr = curr[el];\n i++;\n }\n }\n }\n };\n processError(this);\n return fieldErrors;\n }\n static assert(value) {\n if (!(value instanceof ZodError)) {\n throw new Error(`Not a ZodError: ${value}`);\n }\n }\n toString() {\n return this.message;\n }\n get message() {\n return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);\n }\n get isEmpty() {\n return this.issues.length === 0;\n }\n flatten(mapper = (issue) => issue.message) {\n const fieldErrors = {};\n const formErrors = [];\n for (const sub of this.issues) {\n if (sub.path.length > 0) {\n fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];\n fieldErrors[sub.path[0]].push(mapper(sub));\n }\n else {\n formErrors.push(mapper(sub));\n }\n }\n return { formErrors, fieldErrors };\n }\n get formErrors() {\n return this.flatten();\n }\n}\nZodError.create = (issues) => {\n const error = new ZodError(issues);\n return error;\n};\n\nconst errorMap = (issue, _ctx) => {\n let message;\n switch (issue.code) {\n case ZodIssueCode.invalid_type:\n if (issue.received === ZodParsedType.undefined) {\n message = \"Required\";\n }\n else {\n message = `Expected ${issue.expected}, received ${issue.received}`;\n }\n break;\n case ZodIssueCode.invalid_literal:\n message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;\n break;\n case ZodIssueCode.unrecognized_keys:\n message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, \", \")}`;\n break;\n case ZodIssueCode.invalid_union:\n message = `Invalid input`;\n break;\n case ZodIssueCode.invalid_union_discriminator:\n message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;\n break;\n case ZodIssueCode.invalid_enum_value:\n message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;\n break;\n case ZodIssueCode.invalid_arguments:\n message = `Invalid function arguments`;\n break;\n case ZodIssueCode.invalid_return_type:\n message = `Invalid function return type`;\n break;\n case ZodIssueCode.invalid_date:\n message = `Invalid date`;\n break;\n case ZodIssueCode.invalid_string:\n if (typeof issue.validation === \"object\") {\n if (\"includes\" in issue.validation) {\n message = `Invalid input: must include \"${issue.validation.includes}\"`;\n if (typeof issue.validation.position === \"number\") {\n message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;\n }\n }\n else if (\"startsWith\" in issue.validation) {\n message = `Invalid input: must start with \"${issue.validation.startsWith}\"`;\n }\n else if (\"endsWith\" in issue.validation) {\n message = `Invalid input: must end with \"${issue.validation.endsWith}\"`;\n }\n else {\n util.assertNever(issue.validation);\n }\n }\n else if (issue.validation !== \"regex\") {\n message = `Invalid ${issue.validation}`;\n }\n else {\n message = \"Invalid\";\n }\n break;\n case ZodIssueCode.too_small:\n if (issue.type === \"array\")\n message = `Array must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;\n else if (issue.type === \"string\")\n message = `String must contain ${issue.exact ? \"exactly\" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;\n else if (issue.type === \"number\")\n message = `Number must be ${issue.exact\n ? `exactly equal to `\n : issue.inclusive\n ? `greater than or equal to `\n : `greater than `}${issue.minimum}`;\n else if (issue.type === \"date\")\n message = `Date must be ${issue.exact\n ? `exactly equal to `\n : issue.inclusive\n ? `greater than or equal to `\n : `greater than `}${new Date(Number(issue.minimum))}`;\n else\n message = \"Invalid input\";\n break;\n case ZodIssueCode.too_big:\n if (issue.type === \"array\")\n message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;\n else if (issue.type === \"string\")\n message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;\n else if (issue.type === \"number\")\n message = `Number must be ${issue.exact\n ? `exactly`\n : issue.inclusive\n ? `less than or equal to`\n : `less than`} ${issue.maximum}`;\n else if (issue.type === \"bigint\")\n message = `BigInt must be ${issue.exact\n ? `exactly`\n : issue.inclusive\n ? `less than or equal to`\n : `less than`} ${issue.maximum}`;\n else if (issue.type === \"date\")\n message = `Date must be ${issue.exact\n ? `exactly`\n : issue.inclusive\n ? `smaller than or equal to`\n : `smaller than`} ${new Date(Number(issue.maximum))}`;\n else\n message = \"Invalid input\";\n break;\n case ZodIssueCode.custom:\n message = `Invalid input`;\n break;\n case ZodIssueCode.invalid_intersection_types:\n message = `Intersection results could not be merged`;\n break;\n case ZodIssueCode.not_multiple_of:\n message = `Number must be a multiple of ${issue.multipleOf}`;\n break;\n case ZodIssueCode.not_finite:\n message = \"Number must be finite\";\n break;\n default:\n message = _ctx.defaultError;\n util.assertNever(issue);\n }\n return { message };\n};\n\nlet overrideErrorMap = errorMap;\nfunction setErrorMap(map) {\n overrideErrorMap = map;\n}\nfunction getErrorMap() {\n return overrideErrorMap;\n}\n\nconst makeIssue = (params) => {\n const { data, path, errorMaps, issueData } = params;\n const fullPath = [...path, ...(issueData.path || [])];\n const fullIssue = {\n ...issueData,\n path: fullPath,\n };\n if (issueData.message !== undefined) {\n return {\n ...issueData,\n path: fullPath,\n message: issueData.message,\n };\n }\n let errorMessage = \"\";\n const maps = errorMaps\n .filter((m) => !!m)\n .slice()\n .reverse();\n for (const map of maps) {\n errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;\n }\n return {\n ...issueData,\n path: fullPath,\n message: errorMessage,\n };\n};\nconst EMPTY_PATH = [];\nfunction addIssueToContext(ctx, issueData) {\n const overrideMap = getErrorMap();\n const issue = makeIssue({\n issueData: issueData,\n data: ctx.data,\n path: ctx.path,\n errorMaps: [\n ctx.common.contextualErrorMap, // contextual error map is first priority\n ctx.schemaErrorMap, // then schema-bound map if available\n overrideMap, // then global override map\n overrideMap === errorMap ? undefined : errorMap, // then global default map\n ].filter((x) => !!x),\n });\n ctx.common.issues.push(issue);\n}\nclass ParseStatus {\n constructor() {\n this.value = \"valid\";\n }\n dirty() {\n if (this.value === \"valid\")\n this.value = \"dirty\";\n }\n abort() {\n if (this.value !== \"aborted\")\n this.value = \"aborted\";\n }\n static mergeArray(status, results) {\n const arrayValue = [];\n for (const s of results) {\n if (s.status === \"aborted\")\n return INVALID;\n if (s.status === \"dirty\")\n status.dirty();\n arrayValue.push(s.value);\n }\n return { status: status.value, value: arrayValue };\n }\n static async mergeObjectAsync(status, pairs) {\n const syncPairs = [];\n for (const pair of pairs) {\n const key = await pair.key;\n const value = await pair.value;\n syncPairs.push({\n key,\n value,\n });\n }\n return ParseStatus.mergeObjectSync(status, syncPairs);\n }\n static mergeObjectSync(status, pairs) {\n const finalObject = {};\n for (const pair of pairs) {\n const { key, value } = pair;\n if (key.status === \"aborted\")\n return INVALID;\n if (value.status === \"aborted\")\n return INVALID;\n if (key.status === \"dirty\")\n status.dirty();\n if (value.status === \"dirty\")\n status.dirty();\n if (key.value !== \"__proto__\" &&\n (typeof value.value !== \"undefined\" || pair.alwaysSet)) {\n finalObject[key.value] = value.value;\n }\n }\n return { status: status.value, value: finalObject };\n }\n}\nconst INVALID = Object.freeze({\n status: \"aborted\",\n});\nconst DIRTY = (value) => ({ status: \"dirty\", value });\nconst OK = (value) => ({ status: \"valid\", value });\nconst isAborted = (x) => x.status === \"aborted\";\nconst isDirty = (x) => x.status === \"dirty\";\nconst isValid = (x) => x.status === \"valid\";\nconst isAsync = (x) => typeof Promise !== \"undefined\" && x instanceof Promise;\n\n/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n\r\nfunction __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nfunction __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\ntypeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\n\nvar errorUtil;\n(function (errorUtil) {\n errorUtil.errToObj = (message) => typeof message === \"string\" ? { message } : message || {};\n errorUtil.toString = (message) => typeof message === \"string\" ? message : message === null || message === void 0 ? void 0 : message.message;\n})(errorUtil || (errorUtil = {}));\n\nvar _ZodEnum_cache, _ZodNativeEnum_cache;\nclass ParseInputLazyPath {\n constructor(parent, value, path, key) {\n this._cachedPath = [];\n this.parent = parent;\n this.data = value;\n this._path = path;\n this._key = key;\n }\n get path() {\n if (!this._cachedPath.length) {\n if (this._key instanceof Array) {\n this._cachedPath.push(...this._path, ...this._key);\n }\n else {\n this._cachedPath.push(...this._path, this._key);\n }\n }\n return this._cachedPath;\n }\n}\nconst handleResult = (ctx, result) => {\n if (isValid(result)) {\n return { success: true, data: result.value };\n }\n else {\n if (!ctx.common.issues.length) {\n throw new Error(\"Validation failed but no issues detected.\");\n }\n return {\n success: false,\n get error() {\n if (this._error)\n return this._error;\n const error = new ZodError(ctx.common.issues);\n this._error = error;\n return this._error;\n },\n };\n }\n};\nfunction processCreateParams(params) {\n if (!params)\n return {};\n const { errorMap, invalid_type_error, required_error, description } = params;\n if (errorMap && (invalid_type_error || required_error)) {\n throw new Error(`Can't use \"invalid_type_error\" or \"required_error\" in conjunction with custom error map.`);\n }\n if (errorMap)\n return { errorMap: errorMap, description };\n const customMap = (iss, ctx) => {\n var _a, _b;\n const { message } = params;\n if (iss.code === \"invalid_enum_value\") {\n return { message: message !== null && message !== void 0 ? message : ctx.defaultError };\n }\n if (typeof ctx.data === \"undefined\") {\n return { message: (_a = message !== null && message !== void 0 ? message : required_error) !== null && _a !== void 0 ? _a : ctx.defaultError };\n }\n if (iss.code !== \"invalid_type\")\n return { message: ctx.defaultError };\n return { message: (_b = message !== null && message !== void 0 ? message : invalid_type_error) !== null && _b !== void 0 ? _b : ctx.defaultError };\n };\n return { errorMap: customMap, description };\n}\nclass ZodType {\n get description() {\n return this._def.description;\n }\n _getType(input) {\n return getParsedType(input.data);\n }\n _getOrReturnCtx(input, ctx) {\n return (ctx || {\n common: input.parent.common,\n data: input.data,\n parsedType: getParsedType(input.data),\n schemaErrorMap: this._def.errorMap,\n path: input.path,\n parent: input.parent,\n });\n }\n _processInputParams(input) {\n return {\n status: new ParseStatus(),\n ctx: {\n common: input.parent.common,\n data: input.data,\n parsedType: getParsedType(input.data),\n schemaErrorMap: this._def.errorMap,\n path: input.path,\n parent: input.parent,\n },\n };\n }\n _parseSync(input) {\n const result = this._parse(input);\n if (isAsync(result)) {\n throw new Error(\"Synchronous parse encountered promise.\");\n }\n return result;\n }\n _parseAsync(input) {\n const result = this._parse(input);\n return Promise.resolve(result);\n }\n parse(data, params) {\n const result = this.safeParse(data, params);\n if (result.success)\n return result.data;\n throw result.error;\n }\n safeParse(data, params) {\n var _a;\n const ctx = {\n common: {\n