B2B-88: add starter kit structure and elements

This commit is contained in:
devmc-ee
2025-06-08 16:18:30 +03:00
parent 657a36a298
commit e7b25600cb
1280 changed files with 77893 additions and 5688 deletions

View File

@@ -0,0 +1,33 @@
import 'server-only';
import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@kit/supabase/database';
import { createBillingGatewayService } from './billing-gateway.service';
/**
* @description This function retrieves the billing provider from the database and returns a
* new instance of the `BillingGatewayService` class. This class is used to interact with the server actions
* defined in the host application.
*/
export async function getBillingGatewayProvider(
client: SupabaseClient<Database>,
) {
const provider = await getBillingProvider(client);
return createBillingGatewayService(provider);
}
async function getBillingProvider(client: SupabaseClient<Database>) {
const { data, error } = await client
.from('config')
.select('billing_provider')
.single();
if (error ?? !data.billing_provider) {
throw error;
}
return data.billing_provider;
}

View File

@@ -0,0 +1,34 @@
import 'server-only';
import { z } from 'zod';
import {
type BillingProviderSchema,
BillingStrategyProviderService,
} from '@kit/billing';
import { createRegistry } from '@kit/shared/registry';
// Create a registry for billing strategy providers
export const billingStrategyRegistry = createRegistry<
BillingStrategyProviderService,
z.infer<typeof BillingProviderSchema>
>();
// Register the Stripe billing strategy
billingStrategyRegistry.register('stripe', async () => {
const { StripeBillingStrategyService } = await import('@kit/stripe');
return new StripeBillingStrategyService();
});
// Register the Lemon Squeezy billing strategy
billingStrategyRegistry.register('lemon-squeezy', async () => {
const { LemonSqueezyBillingStrategyService } = await import(
'@kit/lemon-squeezy'
);
return new LemonSqueezyBillingStrategyService();
});
// Register Paddle billing strategy (not implemented yet)
billingStrategyRegistry.register('paddle', () => {
throw new Error('Paddle is not supported yet');
});

View File

@@ -0,0 +1,143 @@
import { z } from 'zod';
import type { BillingProviderSchema } from '@kit/billing';
import {
CancelSubscriptionParamsSchema,
CreateBillingCheckoutSchema,
CreateBillingPortalSessionSchema,
QueryBillingUsageSchema,
ReportBillingUsageSchema,
RetrieveCheckoutSessionSchema,
UpdateSubscriptionParamsSchema,
} from '@kit/billing/schema';
import { billingStrategyRegistry } from './billing-gateway-registry';
export function createBillingGatewayService(
provider: z.infer<typeof BillingProviderSchema>,
) {
return new BillingGatewayService(provider);
}
/**
* @description The billing gateway service to interact with the billing provider of choice (e.g. Stripe)
* @class BillingGatewayService
* @param {BillingProvider} provider - The billing provider to use
* @example
*
* const provider = 'stripe';
* const billingGatewayService = new BillingGatewayService(provider);
*/
class BillingGatewayService {
constructor(
private readonly provider: z.infer<typeof BillingProviderSchema>,
) {}
/**
* Creates a checkout session for billing.
*
* @param {CreateBillingCheckoutSchema} params - The parameters for creating the checkout session.
*
*/
async createCheckoutSession(
params: z.infer<typeof CreateBillingCheckoutSchema>,
) {
const strategy = await this.getStrategy();
const payload = CreateBillingCheckoutSchema.parse(params);
return strategy.createCheckoutSession(payload);
}
/**
* Retrieves the checkout session from the specified provider.
*
* @param {RetrieveCheckoutSessionSchema} params - The parameters to retrieve the checkout session.
*/
async retrieveCheckoutSession(
params: z.infer<typeof RetrieveCheckoutSessionSchema>,
) {
const strategy = await this.getStrategy();
const payload = RetrieveCheckoutSessionSchema.parse(params);
return strategy.retrieveCheckoutSession(payload);
}
/**
* Creates a billing portal session for the specified parameters.
*
* @param {CreateBillingPortalSessionSchema} params - The parameters to create the billing portal session.
*/
async createBillingPortalSession(
params: z.infer<typeof CreateBillingPortalSessionSchema>,
) {
const strategy = await this.getStrategy();
const payload = CreateBillingPortalSessionSchema.parse(params);
return strategy.createBillingPortalSession(payload);
}
/**
* Cancels a subscription.
*
* @param {CancelSubscriptionParamsSchema} params - The parameters for cancelling the subscription.
*/
async cancelSubscription(
params: z.infer<typeof CancelSubscriptionParamsSchema>,
) {
const strategy = await this.getStrategy();
const payload = CancelSubscriptionParamsSchema.parse(params);
return strategy.cancelSubscription(payload);
}
/**
* Reports the usage of the billing.
* @description This is used to report the usage of the billing to the provider.
* @param params
*/
async reportUsage(params: z.infer<typeof ReportBillingUsageSchema>) {
const strategy = await this.getStrategy();
const payload = ReportBillingUsageSchema.parse(params);
return strategy.reportUsage(payload);
}
/**
* @name queryUsage
* @description Queries the usage of the metered billing.
* @param params
*/
async queryUsage(params: z.infer<typeof QueryBillingUsageSchema>) {
const strategy = await this.getStrategy();
const payload = QueryBillingUsageSchema.parse(params);
return strategy.queryUsage(payload);
}
/**
* Updates a subscription with the specified parameters.
* @param params
*/
async updateSubscriptionItem(
params: z.infer<typeof UpdateSubscriptionParamsSchema>,
) {
const strategy = await this.getStrategy();
const payload = UpdateSubscriptionParamsSchema.parse(params);
return strategy.updateSubscriptionItem(payload);
}
/**
* Retrieves a subscription from the provider.
* @param subscriptionId
*/
async getSubscription(subscriptionId: string) {
const strategy = await this.getStrategy();
return strategy.getSubscription(subscriptionId);
}
private getStrategy() {
return billingStrategyRegistry.get(this.provider);
}
}