Refactor code and improve usage of package dependencies
This commit updates the naming convention of icons from Lucide-React, moving some package dependencies to "peerDependencies" in 'team-accounts', 'admin' and 'auth'. Additionally, it includes tweaks to the development server command in apps/web package.json and adds a logger reference to the shared package. Furthermore, cleanup work has been performed within the features and UI packages, and new scripts to interact with Stripe have been added to the root package.json.
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
"typecheck": "tsc --noEmit",
|
||||
"start": "docker run --rm -it --name=stripe -v ~/.config/stripe:/root/.config/stripe stripe/stripe-cli:latest listen --forward-to http://host.docker.internal:3000/api/billing/webhook"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
import { invariant } from '@epic-web/invariant';
|
||||
import {
|
||||
EmbeddedCheckout,
|
||||
EmbeddedCheckoutProvider,
|
||||
@@ -14,15 +15,10 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@kit/ui/dialog';
|
||||
import { cn } from '@kit/ui/utils';
|
||||
|
||||
const STRIPE_PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;
|
||||
|
||||
if (!STRIPE_PUBLISHABLE_KEY) {
|
||||
throw new Error(
|
||||
'Missing NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY environment variable. Did you forget to add it to your .env file?',
|
||||
);
|
||||
}
|
||||
invariant(STRIPE_PUBLISHABLE_KEY, 'Stripe publishable key is required');
|
||||
|
||||
const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY);
|
||||
|
||||
@@ -52,11 +48,7 @@ function EmbeddedCheckoutPopup({
|
||||
onClose?: () => void;
|
||||
}>) {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
||||
const className = cn({
|
||||
[`bg-white p-4 max-h-[98vh] overflow-y-auto shadow-transparent border border-gray-200 dark:border-dark-700`]:
|
||||
true,
|
||||
});
|
||||
const className = `bg-white p-4 max-h-[98vh] overflow-y-auto shadow-transparent border`;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
||||
@@ -4,20 +4,19 @@ import { StripeServerEnvSchema } from '../schema/stripe-server-env.schema';
|
||||
|
||||
const STRIPE_API_VERSION = '2023-10-16';
|
||||
|
||||
// Parse the environment variables and validate them
|
||||
const stripeServerEnv = StripeServerEnvSchema.parse({
|
||||
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
||||
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
|
||||
/**
|
||||
* @description returns a Stripe instance
|
||||
*/
|
||||
export async function createStripeClient() {
|
||||
const { default: Stripe } = await import('stripe');
|
||||
const key = stripeServerEnv.STRIPE_SECRET_KEY;
|
||||
|
||||
return new Stripe(key, {
|
||||
// Parse the environment variables and validate them
|
||||
const stripeServerEnv = StripeServerEnvSchema.parse({
|
||||
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
||||
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
|
||||
return new Stripe(stripeServerEnv.STRIPE_SECRET_KEY, {
|
||||
apiVersion: STRIPE_API_VERSION,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,9 +29,11 @@ export class StripeWebhookHandlerService
|
||||
*/
|
||||
async verifyWebhookSignature(request: Request) {
|
||||
const body = await request.clone().text();
|
||||
const signature = `stripe-signature`;
|
||||
const signatureKey = `stripe-signature`;
|
||||
const signature = request.headers.get(signatureKey) as string;
|
||||
|
||||
const { STRIPE_WEBHOOK_SECRET } = StripeServerEnvSchema.parse({
|
||||
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
||||
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
|
||||
});
|
||||
|
||||
@@ -109,7 +111,7 @@ export class StripeWebhookHandlerService
|
||||
private async handleCheckoutSessionCompleted(
|
||||
event: Stripe.CheckoutSessionCompletedEvent,
|
||||
onCheckoutCompletedCallback: (
|
||||
data: InsertSubscriptionParams,
|
||||
data: Omit<Subscription['Insert'], 'billing_customer_id'>,
|
||||
customerId: string,
|
||||
) => Promise<unknown>,
|
||||
) {
|
||||
@@ -128,11 +130,11 @@ export class StripeWebhookHandlerService
|
||||
// TODO: convert or store the amount in cents?
|
||||
const amount = session.amount_total ?? 0;
|
||||
|
||||
const payload = this.buildSubscriptionPayload<typeof accountId>({
|
||||
const payload = this.buildSubscriptionPayload({
|
||||
subscription,
|
||||
accountId,
|
||||
amount,
|
||||
});
|
||||
}) as InsertSubscriptionParams;
|
||||
|
||||
return onCheckoutCompletedCallback(payload, customerId);
|
||||
}
|
||||
@@ -149,7 +151,7 @@ export class StripeWebhookHandlerService
|
||||
return (acc + (item.plan.amount ?? 0)) * (item.quantity ?? 1);
|
||||
}, 0);
|
||||
|
||||
const payload = this.buildSubscriptionPayload<undefined>({
|
||||
const payload = this.buildSubscriptionPayload({
|
||||
subscription,
|
||||
amount,
|
||||
});
|
||||
@@ -166,27 +168,27 @@ export class StripeWebhookHandlerService
|
||||
return onSubscriptionDeletedCallback(subscription.id);
|
||||
}
|
||||
|
||||
private buildSubscriptionPayload<
|
||||
AccountId extends string | undefined,
|
||||
>(params: {
|
||||
private buildSubscriptionPayload(params: {
|
||||
subscription: Stripe.Subscription;
|
||||
amount: number;
|
||||
// we only need the account id if we
|
||||
// are creating a subscription for an account
|
||||
accountId?: AccountId;
|
||||
}): AccountId extends string
|
||||
? InsertSubscriptionParams
|
||||
: Subscription['Update'] {
|
||||
accountId?: string;
|
||||
}) {
|
||||
const { subscription } = params;
|
||||
const lineItem = subscription.items.data[0];
|
||||
const price = lineItem?.price;
|
||||
const priceId = price?.id!;
|
||||
const interval = price?.recurring?.interval ?? null;
|
||||
|
||||
const active =
|
||||
subscription.status === 'active' || subscription.status === 'trialing';
|
||||
|
||||
const data = {
|
||||
billing_provider: this.provider,
|
||||
id: subscription.id,
|
||||
status: subscription.status,
|
||||
active,
|
||||
price_amount: params.amount,
|
||||
cancel_at_period_end: subscription.cancel_at_period_end ?? false,
|
||||
interval: interval as string,
|
||||
@@ -194,15 +196,27 @@ export class StripeWebhookHandlerService
|
||||
product_id: price?.product as string,
|
||||
variant_id: priceId,
|
||||
interval_count: price?.recurring?.interval_count ?? 1,
|
||||
};
|
||||
period_starts_at: getISOString(subscription.current_period_start),
|
||||
period_ends_at: getISOString(subscription.current_period_end),
|
||||
trial_starts_at: getISOString(subscription.trial_start),
|
||||
trial_ends_at: getISOString(subscription.trial_end),
|
||||
} satisfies Omit<InsertSubscriptionParams, 'account_id'>;
|
||||
|
||||
// when we are creating a subscription for an account
|
||||
// we need to include the account id
|
||||
if (params.accountId !== undefined) {
|
||||
return {
|
||||
...data,
|
||||
account_id: params.accountId,
|
||||
} satisfies InsertSubscriptionParams;
|
||||
};
|
||||
}
|
||||
|
||||
return data as Subscription['Update'];
|
||||
// otherwise we are updating a subscription
|
||||
// and we only need to return the update payload
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
function getISOString(date: number | null) {
|
||||
return date ? new Date(date * 1000).toISOString() : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user