diff --git a/apps/web/app/(dashboard)/home/(user)/billing/_lib/server/user-billing.service.ts b/apps/web/app/(dashboard)/home/(user)/billing/_lib/server/user-billing.service.ts index 1c75e945b..df1863870 100644 --- a/apps/web/app/(dashboard)/home/(user)/billing/_lib/server/user-billing.service.ts +++ b/apps/web/app/(dashboard)/home/(user)/billing/_lib/server/user-billing.service.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import { getProductPlanPair } from '@kit/billing'; import { getBillingGatewayProvider } from '@kit/billing-gateway'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client'; @@ -51,8 +51,9 @@ export class UserBillingService { } const { plan } = getProductPlanPair(billingConfig, planId); + const logger = await getLogger(); - Logger.info( + logger.info( { name: `billing.personal-account`, planId, @@ -73,7 +74,7 @@ export class UserBillingService { variantQuantities: [], }); - Logger.info( + logger.info( { userId: user.id, }, @@ -86,7 +87,7 @@ export class UserBillingService { checkoutToken, }; } catch (error) { - Logger.error( + logger.error( { name: `billing.personal-account`, planId, @@ -118,7 +119,9 @@ export class UserBillingService { throw new Error('Customer not found'); } - Logger.info( + const logger = await getLogger(); + + logger.info( { name: `billing.personal-account`, customerId, @@ -137,7 +140,7 @@ export class UserBillingService { url = session.url; } catch (error) { - Logger.error( + logger.error( { error, customerId, @@ -151,7 +154,7 @@ export class UserBillingService { ); } - Logger.info( + logger.info( { name: `billing.personal-account`, customerId, @@ -167,6 +170,14 @@ export class UserBillingService { async function getCustomerIdFromAccountId(accountId: string) { const client = getSupabaseServerActionClient(); + const logger = await getLogger(); + + logger.info( + { + accountId, + }, + `Getting customer ID for account ${accountId}...`, + ); const { data, error } = await client .from('billing_customers') @@ -175,6 +186,14 @@ async function getCustomerIdFromAccountId(accountId: string) { .maybeSingle(); if (error) { + logger.error( + { + accountId, + error, + }, + `Failed to get customer ID`, + ); + throw error; } diff --git a/apps/web/app/(dashboard)/home/[account]/_lib/server/team-billing.service.ts b/apps/web/app/(dashboard)/home/[account]/_lib/server/team-billing.service.ts index 1319c2950..2f950c805 100644 --- a/apps/web/app/(dashboard)/home/[account]/_lib/server/team-billing.service.ts +++ b/apps/web/app/(dashboard)/home/[account]/_lib/server/team-billing.service.ts @@ -5,7 +5,7 @@ import { z } from 'zod'; import { LineItemSchema } from '@kit/billing'; import { getBillingGatewayProvider } from '@kit/billing-gateway'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client'; @@ -35,8 +35,9 @@ export class TeamBillingService { const userId = user.id; const accountId = params.accountId; + const logger = await getLogger(); - Logger.info( + logger.info( { userId, accountId, @@ -54,7 +55,7 @@ export class TeamBillingService { // if the user does not have permission to manage billing for the account // then we should not proceed if (!hasPermission) { - Logger.warn( + logger.warn( { userId, accountId, @@ -90,7 +91,7 @@ export class TeamBillingService { accountId, ); - Logger.info( + logger.info( { userId, accountId, @@ -117,7 +118,7 @@ export class TeamBillingService { checkoutToken, }; } catch (error) { - Logger.error( + logger.error( { name: this.namespace, error, @@ -145,8 +146,9 @@ export class TeamBillingService { slug: string; }) { const client = getSupabaseServerActionClient(); + const logger = await getLogger(); - Logger.info( + logger.info( { accountId, name: this.namespace, @@ -171,7 +173,7 @@ export class TeamBillingService { // if the user does not have permission to manage billing for the account // then we should not proceed if (!hasPermission) { - Logger.warn( + logger.warn( { userId, accountId, @@ -190,7 +192,7 @@ export class TeamBillingService { throw new Error('Customer not found'); } - Logger.info( + logger.info( { userId, customerId, @@ -211,7 +213,7 @@ export class TeamBillingService { // redirect the user to the billing portal return url; } catch (error) { - Logger.error( + logger.error( { userId, customerId, @@ -260,7 +262,9 @@ export class TeamBillingService { .eq('account_id', accountId); if (error) { - Logger.error( + const logger = await getLogger(); + + logger.error( { accountId, error, diff --git a/apps/web/app/(dashboard)/home/[account]/billing/return/page.tsx b/apps/web/app/(dashboard)/home/[account]/billing/return/page.tsx index fccface0f..617eb25a8 100644 --- a/apps/web/app/(dashboard)/home/[account]/billing/return/page.tsx +++ b/apps/web/app/(dashboard)/home/[account]/billing/return/page.tsx @@ -68,7 +68,7 @@ async function ReturnCheckoutSessionPage({ searchParams }: SessionPageProps) { export default withI18n(ReturnCheckoutSessionPage); -export async function loadCheckoutSession(sessionId: string) { +async function loadCheckoutSession(sessionId: string) { const client = getSupabaseServerComponentClient(); const { error } = await requireUser(client); diff --git a/apps/web/app/admin/accounts/[account]/page.tsx b/apps/web/app/admin/accounts/[account]/page.tsx index e69de29bb..01cd60637 100644 --- a/apps/web/app/admin/accounts/[account]/page.tsx +++ b/apps/web/app/admin/accounts/[account]/page.tsx @@ -0,0 +1,3 @@ +export default function AccountPage() { + return
; +} diff --git a/apps/web/app/api/billing/webhook/route.ts b/apps/web/app/api/billing/webhook/route.ts index 38a79abd9..0b6c97207 100644 --- a/apps/web/app/api/billing/webhook/route.ts +++ b/apps/web/app/api/billing/webhook/route.ts @@ -1,5 +1,5 @@ import { getBillingEventHandlerService } from '@kit/billing-gateway'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { getSupabaseRouteHandlerClient } from '@kit/supabase/route-handler-client'; import billingConfig from '~/config/billing.config'; @@ -9,8 +9,9 @@ import billingConfig from '~/config/billing.config'; */ export async function POST(request: Request) { const provider = billingConfig.provider; + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.webhook', provider, @@ -30,7 +31,7 @@ export async function POST(request: Request) { try { await service.handleWebhookEvent(request); - Logger.info( + logger.info( { name: 'billing.webhook', }, @@ -39,7 +40,7 @@ export async function POST(request: Request) { return new Response('OK', { status: 200 }); } catch (e) { - Logger.error( + logger.error( { name: 'billing', error: e, diff --git a/apps/web/app/auth/callback/route.ts b/apps/web/app/auth/callback/route.ts index 125b40e04..ac73b1b19 100644 --- a/apps/web/app/auth/callback/route.ts +++ b/apps/web/app/auth/callback/route.ts @@ -1,7 +1,7 @@ import { redirect } from 'next/navigation'; import type { NextRequest } from 'next/server'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { getSupabaseRouteHandlerClient } from '@kit/supabase/route-handler-client'; import pathsConfig from '~/config/paths.config'; @@ -38,9 +38,12 @@ export async function GET(request: NextRequest) { return onError({ error: error.message }); } } catch (error) { - Logger.error( + const logger = await getLogger(); + + logger.error( { error, + name: `auth.callback`, }, `An error occurred while exchanging code for session`, ); @@ -58,12 +61,14 @@ export async function GET(request: NextRequest) { return redirect(nextUrl); } -function onError({ error }: { error: string }) { +async function onError({ error }: { error: string }) { const errorMessage = getAuthErrorMessage(error); + const logger = await getLogger(); - Logger.error( + logger.error( { error, + name: `auth.callback`, }, `An error occurred while signing user in`, ); diff --git a/apps/web/app/join/page.tsx b/apps/web/app/join/page.tsx index 879c1071a..3aed506cb 100644 --- a/apps/web/app/join/page.tsx +++ b/apps/web/app/join/page.tsx @@ -63,9 +63,10 @@ async function JoinTeamAccountPage({ searchParams }: Context) { ); if (isInAccount) { - const { Logger } = await import('@kit/shared/logger'); + const { getLogger } = await import('@kit/shared/logger'); + const logger = await getLogger(); - Logger.warn( + logger.warn( { name: 'join-team-account', accountId: invitation.account.id, diff --git a/apps/web/instrumentation.ts b/apps/web/instrumentation.ts index ca20f6ef0..f1fd5d496 100644 --- a/apps/web/instrumentation.ts +++ b/apps/web/instrumentation.ts @@ -1,7 +1,12 @@ -import { registerInstrumentation } from '@kit/monitoring'; +/** + * This file is used to register monitoring instrumentation + * for your Next.js application. + */ +export async function register() { + // only run in nodejs runtime + if (process.env.NEXT_RUNTIME === 'nodejs') { + const { registerInstrumentation } = await import('@kit/monitoring'); -export function register() { - if (process.env.NEXT_RUNTIME !== 'nodejs') { // Register monitoring instrumentation based on the // MONITORING_INSTRUMENTATION_PROVIDER environment variable. return registerInstrumentation(); diff --git a/apps/web/package.json b/apps/web/package.json index b74214080..06178fdb1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -45,7 +45,7 @@ "i18next": "^23.10.1", "i18next-resources-to-backend": "^1.2.0", "lucide-react": "^0.363.0", - "next": "14.2.0-canary.61", + "next": "14.2.0-canary.62", "next-sitemap": "^4.2.3", "next-themes": "0.3.0", "react": "18.2.0", diff --git a/packages/billing/gateway/src/server/services/billing-event-handler/billing-event-handler.service.ts b/packages/billing/gateway/src/server/services/billing-event-handler/billing-event-handler.service.ts index 1aad51da2..e30c07858 100644 --- a/packages/billing/gateway/src/server/services/billing-event-handler/billing-event-handler.service.ts +++ b/packages/billing/gateway/src/server/services/billing-event-handler/billing-event-handler.service.ts @@ -1,7 +1,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import { BillingWebhookHandlerService } from '@kit/billing'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; export class BillingEventHandlerService { @@ -22,10 +22,11 @@ export class BillingEventHandlerService { return this.strategy.handleWebhookEvent(event, { onSubscriptionDeleted: async (subscriptionId: string) => { const client = this.clientProvider(); + const logger = await getLogger(); // Handle the subscription deleted event // here we delete the subscription from the database - Logger.info( + logger.info( { namespace: this.namespace, subscriptionId, @@ -42,7 +43,7 @@ export class BillingEventHandlerService { throw new Error('Failed to delete subscription'); } - Logger.info( + logger.info( { namespace: this.namespace, subscriptionId, @@ -52,6 +53,7 @@ export class BillingEventHandlerService { }, onSubscriptionUpdated: async (subscription) => { const client = this.clientProvider(); + const logger = await getLogger(); const ctx = { namespace: this.namespace, @@ -61,14 +63,14 @@ export class BillingEventHandlerService { customerId: subscription.target_customer_id, }; - Logger.info(ctx, 'Processing subscription updated event'); + logger.info(ctx, 'Processing subscription updated event'); // Handle the subscription updated event // here we update the subscription in the database const { error } = await client.rpc('upsert_subscription', subscription); if (error) { - Logger.error( + logger.error( { error, ...ctx, @@ -79,12 +81,13 @@ export class BillingEventHandlerService { throw new Error('Failed to update subscription'); } - Logger.info(ctx, 'Successfully updated subscription'); + logger.info(ctx, 'Successfully updated subscription'); }, onCheckoutSessionCompleted: async (payload) => { // Handle the checkout session completed event // here we add the subscription to the database const client = this.clientProvider(); + const logger = await getLogger(); // Check if the payload contains an order_id // if it does, we add an order, otherwise we add a subscription @@ -97,17 +100,17 @@ export class BillingEventHandlerService { customerId: payload.target_customer_id, }; - Logger.info(ctx, 'Processing order completed event...'); + logger.info(ctx, 'Processing order completed event...'); const { error } = await client.rpc('upsert_order', payload); if (error) { - Logger.error({ ...ctx, error }, 'Failed to add order'); + logger.error({ ...ctx, error }, 'Failed to add order'); throw new Error('Failed to add order'); } - Logger.info(ctx, 'Successfully added order'); + logger.info(ctx, 'Successfully added order'); } else { const ctx = { namespace: this.namespace, @@ -117,25 +120,26 @@ export class BillingEventHandlerService { customerId: payload.target_customer_id, }; - Logger.info(ctx, 'Processing checkout session completed event...'); + logger.info(ctx, 'Processing checkout session completed event...'); const { error } = await client.rpc('upsert_subscription', payload); if (error) { - Logger.error({ ...ctx, error }, 'Failed to add subscription'); + logger.error({ ...ctx, error }, 'Failed to add subscription'); throw new Error('Failed to add subscription'); } - Logger.info(ctx, 'Successfully added subscription'); + logger.info(ctx, 'Successfully added subscription'); } }, onPaymentSucceeded: async (sessionId: string) => { const client = this.clientProvider(); + const logger = await getLogger(); // Handle the payment succeeded event // here we update the payment status in the database - Logger.info( + logger.info( { namespace: this.namespace, sessionId, @@ -152,7 +156,7 @@ export class BillingEventHandlerService { throw new Error('Failed to update payment status'); } - Logger.info( + logger.info( { namespace: this.namespace, sessionId, @@ -162,10 +166,11 @@ export class BillingEventHandlerService { }, onPaymentFailed: async (sessionId: string) => { const client = this.clientProvider(); + const logger = await getLogger(); // Handle the payment failed event // here we update the payment status in the database - Logger.info( + logger.info( { namespace: this.namespace, sessionId, @@ -182,7 +187,7 @@ export class BillingEventHandlerService { throw new Error('Failed to update payment status'); } - Logger.info( + logger.info( { namespace: this.namespace, sessionId, diff --git a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts index 95a98e939..019f840f5 100644 --- a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts +++ b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-billing-strategy.service.ts @@ -16,7 +16,7 @@ import { RetrieveCheckoutSessionSchema, UpdateSubscriptionParamsSchema, } from '@kit/billing/schema'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { createLemonSqueezyBillingPortalSession } from './create-lemon-squeezy-billing-portal-session'; import { createLemonSqueezyCheckout } from './create-lemon-squeezy-checkout'; @@ -27,13 +27,12 @@ export class LemonSqueezyBillingStrategyService async createCheckoutSession( params: z.infer, ) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: 'billing.lemon-squeezy', - customerId: params.customerId, - accountId: params.accountId, - returnUrl: params.returnUrl, - trialDays: params.trialDays, + ...params, }, 'Creating checkout session...', ); @@ -43,7 +42,7 @@ export class LemonSqueezyBillingStrategyService if (error ?? !response?.data.id) { console.log(error); - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', customerId: params.customerId, @@ -56,7 +55,7 @@ export class LemonSqueezyBillingStrategyService throw new Error('Failed to create checkout session'); } - Logger.info( + logger.info( { name: 'billing.lemon-squeezy', customerId: params.customerId, @@ -73,7 +72,9 @@ export class LemonSqueezyBillingStrategyService async createBillingPortalSession( params: z.infer, ) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: 'billing.lemon-squeezy', customerId: params.customerId, @@ -85,7 +86,7 @@ export class LemonSqueezyBillingStrategyService await createLemonSqueezyBillingPortalSession(params); if (error ?? !data) { - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', customerId: params.customerId, @@ -97,7 +98,7 @@ export class LemonSqueezyBillingStrategyService throw new Error('Failed to create billing portal session'); } - Logger.info( + logger.info( { name: 'billing.lemon-squeezy', customerId: params.customerId, @@ -111,7 +112,9 @@ export class LemonSqueezyBillingStrategyService async cancelSubscription( params: z.infer, ) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: 'billing.lemon-squeezy', subscriptionId: params.subscriptionId, @@ -123,7 +126,7 @@ export class LemonSqueezyBillingStrategyService const { error } = await cancelSubscription(params.subscriptionId); if (error) { - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', subscriptionId: params.subscriptionId, @@ -135,7 +138,7 @@ export class LemonSqueezyBillingStrategyService throw error; } - Logger.info( + logger.info( { name: 'billing.lemon-squeezy', subscriptionId: params.subscriptionId, @@ -145,7 +148,7 @@ export class LemonSqueezyBillingStrategyService return { success: true }; } catch (error) { - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', subscriptionId: params.subscriptionId, @@ -161,7 +164,9 @@ export class LemonSqueezyBillingStrategyService async retrieveCheckoutSession( params: z.infer, ) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: 'billing.lemon-squeezy', sessionId: params.sessionId, @@ -172,7 +177,7 @@ export class LemonSqueezyBillingStrategyService const { data: session, error } = await getCheckout(params.sessionId); if (error ?? !session?.data) { - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', sessionId: params.sessionId, @@ -184,7 +189,7 @@ export class LemonSqueezyBillingStrategyService throw new Error('Failed to retrieve checkout session'); } - Logger.info( + logger.info( { name: 'billing.lemon-squeezy', sessionId: params.sessionId, @@ -205,7 +210,9 @@ export class LemonSqueezyBillingStrategyService } async reportUsage(params: z.infer) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: 'billing.lemon-squeezy', subscriptionItemId: params.subscriptionItemId, @@ -220,11 +227,11 @@ export class LemonSqueezyBillingStrategyService }); if (error) { - Logger.error( + logger.error( { name: 'billing.lemon-squeezy', subscriptionItemId: params.subscriptionItemId, - error: error.message, + error, }, 'Failed to report usage', ); @@ -232,7 +239,7 @@ export class LemonSqueezyBillingStrategyService throw new Error('Failed to report usage'); } - Logger.info( + logger.info( { name: 'billing.lemon-squeezy', subscriptionItemId: params.subscriptionItemId, @@ -246,19 +253,21 @@ export class LemonSqueezyBillingStrategyService async updateSubscription( params: z.infer, ) { + const logger = await getLogger(); + const ctx = { name: 'billing.lemon-squeezy', ...params, }; - Logger.info(ctx, 'Updating subscription...'); + logger.info(ctx, 'Updating subscription...'); const { error } = await updateSubscriptionItem(params.subscriptionItemId, { quantity: params.quantity, }); if (error) { - Logger.error( + logger.error( { ...ctx, error, @@ -269,7 +278,7 @@ export class LemonSqueezyBillingStrategyService throw error; } - Logger.info(ctx, 'Subscription updated successfully'); + logger.info(ctx, 'Subscription updated successfully'); return { success: true }; } diff --git a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-sdk.ts b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-sdk.ts index ced371d5e..5ed20968e 100644 --- a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-sdk.ts +++ b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-sdk.ts @@ -1,6 +1,6 @@ import 'server-only'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { getLemonSqueezyEnv } from '../schema/lemon-squeezy-server-env.schema'; @@ -10,11 +10,12 @@ import { getLemonSqueezyEnv } from '../schema/lemon-squeezy-server-env.schema'; export async function initializeLemonSqueezyClient() { const { lemonSqueezySetup } = await import('@lemonsqueezy/lemonsqueezy.js'); const env = getLemonSqueezyEnv(); + const logger = await getLogger(); lemonSqueezySetup({ apiKey: env.secretKey, onError(error) { - Logger.error( + logger.error( { name: `billing.lemon-squeezy`, error: error.message, diff --git a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-webhook-handler.service.ts b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-webhook-handler.service.ts index addf7b8d5..113831ea9 100644 --- a/packages/billing/lemon-squeezy/src/services/lemon-squeezy-webhook-handler.service.ts +++ b/packages/billing/lemon-squeezy/src/services/lemon-squeezy-webhook-handler.service.ts @@ -6,7 +6,7 @@ import { BillingWebhookHandlerService, getLineItemTypeById, } from '@kit/billing'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { getLemonSqueezyEnv } from '../schema/lemon-squeezy-server-env.schema'; @@ -45,6 +45,9 @@ export class LemonSqueezyWebhookHandlerService * @description Verifies the webhook signature - should throw an error if the signature is invalid */ async verifyWebhookSignature(request: Request) { + const logger = await getLogger(); + + // get the event name and signature from the headers const eventName = request.headers.get('x-event-name'); const signature = request.headers.get('x-signature') as string; @@ -53,8 +56,9 @@ export class LemonSqueezyWebhookHandlerService const body = (await request.json()) as SubscriptionWebhook | OrderWebhook; const rawBody = await reqClone.text(); + // if no signature is found, throw an error if (!signature) { - Logger.error( + logger.error( { eventName, }, @@ -64,8 +68,9 @@ export class LemonSqueezyWebhookHandlerService throw new Error('Signature header not found'); } + // if the signature is invalid, throw an error if (!isSigningSecretValid(Buffer.from(rawBody), signature)) { - Logger.error( + logger.error( { eventName, }, @@ -124,7 +129,9 @@ export class LemonSqueezyWebhookHandlerService } default: { - Logger.info( + const logger = await getLogger(); + + logger.info( { eventType: eventName, name: this.namespace, @@ -211,7 +218,9 @@ export class LemonSqueezyWebhookHandlerService const { data: order, error } = await getOrder(orderId); if (error ?? !order) { - Logger.error( + const logger = await getLogger(); + + logger.error( { orderId, subscriptionId, diff --git a/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts b/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts index 1e49ff72f..264571706 100644 --- a/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts +++ b/packages/billing/stripe/src/services/stripe-billing-strategy.service.ts @@ -11,7 +11,7 @@ import { RetrieveCheckoutSessionSchema, UpdateSubscriptionParamsSchema, } from '@kit/billing/schema'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { createStripeBillingPortalSession } from './create-stripe-billing-portal-session'; import { createStripeCheckout } from './create-stripe-checkout'; @@ -24,8 +24,9 @@ export class StripeBillingStrategyService params: z.infer, ) { const stripe = await this.stripeProvider(); + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.stripe', customerId: params.customerId, @@ -37,7 +38,7 @@ export class StripeBillingStrategyService const { client_secret } = await createStripeCheckout(stripe, params); if (!client_secret) { - Logger.error( + logger.error( { name: 'billing.stripe', customerId: params.customerId, @@ -49,7 +50,7 @@ export class StripeBillingStrategyService throw new Error('Failed to create checkout session'); } - Logger.info( + logger.info( { name: 'billing.stripe', customerId: params.customerId, @@ -65,8 +66,9 @@ export class StripeBillingStrategyService params: z.infer, ) { const stripe = await this.stripeProvider(); + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.stripe', customerId: params.customerId, @@ -77,7 +79,7 @@ export class StripeBillingStrategyService const session = await createStripeBillingPortalSession(stripe, params); if (!session?.url) { - Logger.error( + logger.error( { name: 'billing.stripe', customerId: params.customerId, @@ -85,7 +87,7 @@ export class StripeBillingStrategyService 'Failed to create billing portal session', ); } else { - Logger.info( + logger.info( { name: 'billing.stripe', customerId: params.customerId, @@ -101,8 +103,9 @@ export class StripeBillingStrategyService params: z.infer, ) { const stripe = await this.stripeProvider(); + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.stripe', subscriptionId: params.subscriptionId, @@ -115,7 +118,7 @@ export class StripeBillingStrategyService invoice_now: params.invoiceNow ?? true, }); - Logger.info( + logger.info( { name: 'billing.stripe', subscriptionId: params.subscriptionId, @@ -125,7 +128,7 @@ export class StripeBillingStrategyService return { success: true }; } catch (e) { - Logger.error( + logger.error( { name: 'billing.stripe', subscriptionId: params.subscriptionId, @@ -142,8 +145,9 @@ export class StripeBillingStrategyService params: z.infer, ) { const stripe = await this.stripeProvider(); + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.stripe', sessionId: params.sessionId, @@ -155,7 +159,7 @@ export class StripeBillingStrategyService const session = await stripe.checkout.sessions.retrieve(params.sessionId); const isSessionOpen = session.status === 'open'; - Logger.info( + logger.info( { name: 'billing.stripe', sessionId: params.sessionId, @@ -172,7 +176,7 @@ export class StripeBillingStrategyService }, }; } catch (error) { - Logger.error( + logger.error( { name: 'billing.stripe', sessionId: params.sessionId, @@ -203,8 +207,9 @@ export class StripeBillingStrategyService params: z.infer, ) { const stripe = await this.stripeProvider(); + const logger = await getLogger(); - Logger.info( + logger.info( { name: 'billing.stripe', ...params, @@ -222,7 +227,7 @@ export class StripeBillingStrategyService ], }); - Logger.info( + logger.info( { name: 'billing.stripe', ...params, @@ -232,7 +237,7 @@ export class StripeBillingStrategyService return { success: true }; } catch (e) { - Logger.error( + logger.error( { name: 'billing.stripe', ...params, diff --git a/packages/billing/stripe/src/services/stripe-webhook-handler.service.ts b/packages/billing/stripe/src/services/stripe-webhook-handler.service.ts index 2e827c8ac..97d632341 100644 --- a/packages/billing/stripe/src/services/stripe-webhook-handler.service.ts +++ b/packages/billing/stripe/src/services/stripe-webhook-handler.service.ts @@ -5,7 +5,7 @@ import { BillingWebhookHandlerService, getLineItemTypeById, } from '@kit/billing'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { StripeServerEnvSchema } from '../schema/stripe-server-env.schema'; @@ -113,6 +113,8 @@ export class StripeWebhookHandlerService } default: { + const Logger = await getLogger(); + Logger.info( { eventType: event.type, diff --git a/packages/database-webhooks/src/server/services/database-webhook-handler.service.ts b/packages/database-webhooks/src/server/services/database-webhook-handler.service.ts index 6ca8ea259..7dc104199 100644 --- a/packages/database-webhooks/src/server/services/database-webhook-handler.service.ts +++ b/packages/database-webhooks/src/server/services/database-webhook-handler.service.ts @@ -1,6 +1,6 @@ import 'server-only'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { getSupabaseRouteHandlerClient } from '@kit/supabase/route-handler-client'; import { RecordChange, Tables } from '../record-change.type'; @@ -10,10 +10,12 @@ export class DatabaseWebhookHandlerService { private readonly namespace = 'database-webhook-handler'; async handleWebhook(request: Request, webhooksSecret: string) { + const logger = await getLogger(); + const json = await request.clone().json(); const { table, type } = json as RecordChange; - Logger.info( + logger.info( { name: this.namespace, table, @@ -40,7 +42,7 @@ export class DatabaseWebhookHandlerService { // handle the webhook event based on the table await service.handleWebhook(json); - Logger.info( + logger.info( { name: this.namespace, table, @@ -49,7 +51,7 @@ export class DatabaseWebhookHandlerService { 'Webhook processed successfully', ); } catch (error) { - Logger.error( + logger.error( { name: this.namespace, table, diff --git a/packages/database-webhooks/src/server/services/database-webhook-router.service.ts b/packages/database-webhooks/src/server/services/database-webhook-router.service.ts index 47b2885d4..66c8e7be5 100644 --- a/packages/database-webhooks/src/server/services/database-webhook-router.service.ts +++ b/packages/database-webhooks/src/server/services/database-webhook-router.service.ts @@ -1,6 +1,6 @@ import { SupabaseClient } from '@supabase/supabase-js'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { RecordChange, Tables } from '../record-change.type'; @@ -8,7 +8,7 @@ import { RecordChange, Tables } from '../record-change.type'; export class DatabaseWebhookRouterService { constructor(private readonly adminClient: SupabaseClient) {} - handleWebhook(body: RecordChange) { + async handleWebhook(body: RecordChange) { switch (body.table) { case 'invitations': { const payload = body as RecordChange; @@ -23,7 +23,9 @@ export class DatabaseWebhookRouterService { } default: { - Logger.warn( + const logger = await getLogger(); + + logger.warn( { table: body.table, }, diff --git a/packages/features/accounts/src/server/personal-accounts-server-actions.ts b/packages/features/accounts/src/server/personal-accounts-server-actions.ts index f63a62b27..ea4c116ee 100644 --- a/packages/features/accounts/src/server/personal-accounts-server-actions.ts +++ b/packages/features/accounts/src/server/personal-accounts-server-actions.ts @@ -4,7 +4,7 @@ import { RedirectType, redirect } from 'next/navigation'; import { z } from 'zod'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client'; @@ -31,7 +31,8 @@ export async function deletePersonalAccountAction(formData: FormData) { const auth = await requireUser(client); if (auth.error) { - Logger.error(`User is not authenticated. Redirecting to login page`); + const logger = await getLogger(); + logger.error(`User is not authenticated. Redirecting to login page`); redirect(auth.redirectTo); } diff --git a/packages/features/accounts/src/server/services/delete-personal-account.service.ts b/packages/features/accounts/src/server/services/delete-personal-account.service.ts index 7d2baa01b..af0ad02e3 100644 --- a/packages/features/accounts/src/server/services/delete-personal-account.service.ts +++ b/packages/features/accounts/src/server/services/delete-personal-account.service.ts @@ -1,7 +1,6 @@ import { SupabaseClient } from '@supabase/supabase-js'; -import { Mailer } from '@kit/mailers'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; /** @@ -35,8 +34,9 @@ export class DeletePersonalAccountService { }; }) { const userId = params.userId; + const logger = await getLogger(); - Logger.info( + logger.info( { name: this.namespace, userId }, 'User requested deletion. Processing...', ); @@ -45,7 +45,7 @@ export class DeletePersonalAccountService { try { await params.adminClient.auth.admin.deleteUser(userId); } catch (error) { - Logger.error( + logger.error( { name: this.namespace, userId, @@ -60,7 +60,7 @@ export class DeletePersonalAccountService { // Send account deletion email if (params.userEmail) { try { - Logger.info( + logger.info( { name: this.namespace, userId, @@ -74,8 +74,16 @@ export class DeletePersonalAccountService { userDisplayName: params.userEmail, userEmail: params.userEmail, }); + + logger.info( + { + name: this.namespace, + userId, + }, + `Account deletion email sent`, + ); } catch (error) { - Logger.error( + logger.error( { name: this.namespace, userId, @@ -94,13 +102,15 @@ export class DeletePersonalAccountService { productName: string; }) { const { renderAccountDeleteEmail } = await import('@kit/email-templates'); + const { getMailer } = await import('@kit/mailers'); + const mailer = await getMailer(); const html = renderAccountDeleteEmail({ userDisplayName: params.userDisplayName, productName: params.productName, }); - await Mailer.sendEmail({ + return mailer.sendEmail({ to: params.userEmail, from: params.fromEmail, subject: 'Account Deletion Request', diff --git a/packages/features/team-accounts/src/server/actions/create-team-account-server-actions.ts b/packages/features/team-accounts/src/server/actions/create-team-account-server-actions.ts index bd7e5307e..c75f65c8d 100644 --- a/packages/features/team-accounts/src/server/actions/create-team-account-server-actions.ts +++ b/packages/features/team-accounts/src/server/actions/create-team-account-server-actions.ts @@ -4,7 +4,7 @@ import { redirect } from 'next/navigation'; import { z } from 'zod'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client'; @@ -31,6 +31,7 @@ export async function createOrganizationAccountAction( redirect(auth.redirectTo); } + const logger = await getLogger(); const userId = auth.data.id; const createAccountResponse = await service.createNewOrganizationAccount({ @@ -39,7 +40,7 @@ export async function createOrganizationAccountAction( }); if (createAccountResponse.error) { - Logger.error( + logger.error( { userId, error: createAccountResponse.error, @@ -51,6 +52,15 @@ export async function createOrganizationAccountAction( throw new Error('Error creating team account'); } + logger.info( + { + userId, + accountName, + name: 'accounts', + }, + `Team account created successfully`, + ); + const accountHomePath = TEAM_ACCOUNTS_HOME_PATH + '/' + createAccountResponse.data.slug; diff --git a/packages/features/team-accounts/src/server/services/account-invitations-webhook.service.ts b/packages/features/team-accounts/src/server/services/account-invitations-webhook.service.ts index 4b0e14ada..c8e6c9cb9 100644 --- a/packages/features/team-accounts/src/server/services/account-invitations-webhook.service.ts +++ b/packages/features/team-accounts/src/server/services/account-invitations-webhook.service.ts @@ -2,8 +2,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import { z } from 'zod'; -import { Mailer } from '@kit/mailers'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; type Invitation = Database['public']['Tables']['invitations']['Row']; @@ -57,8 +56,12 @@ export class AccountInvitationsWebhookService { throw team.error; } + const logger = await getLogger(); + try { const { renderInviteEmail } = await import('@kit/email-templates'); + const { getMailer } = await import('@kit/mailers'); + const mailer = await getMailer(); const html = renderInviteEmail({ link: this.getInvitationLink(invitation.invite_token), @@ -68,26 +71,34 @@ export class AccountInvitationsWebhookService { teamName: team.data.name, }); - await Mailer.sendEmail({ - from: env.emailSender, - to: invitation.email, - subject: 'You have been invited to join a team', - html, - }); - - Logger.info('Invitation email sent', { - email: invitation.email, - account: invitation.account_id, - name: this.namespace, - }); + await mailer + .sendEmail({ + from: env.emailSender, + to: invitation.email, + subject: 'You have been invited to join a team', + html, + }) + .then(() => { + logger.info('Invitation email sent', { + email: invitation.email, + account: invitation.account_id, + name: this.namespace, + }); + }) + .catch((error) => { + logger.warn( + { error, name: this.namespace }, + 'Failed to send invitation email', + ); + }); return { success: true, }; } catch (error) { - Logger.warn( + logger.warn( { error, name: this.namespace }, - 'Failed to send invitation email', + 'Failed to invite user to team', ); return { diff --git a/packages/features/team-accounts/src/server/services/account-invitations.service.ts b/packages/features/team-accounts/src/server/services/account-invitations.service.ts index 3762aea42..e21bb874e 100644 --- a/packages/features/team-accounts/src/server/services/account-invitations.service.ts +++ b/packages/features/team-accounts/src/server/services/account-invitations.service.ts @@ -4,7 +4,7 @@ import { addDays, formatISO } from 'date-fns'; import 'server-only'; import { z } from 'zod'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { DeleteInvitationSchema } from '../../schema/delete-invitation.schema'; @@ -17,7 +17,9 @@ export class AccountInvitationsService { constructor(private readonly client: SupabaseClient) {} async deleteInvitation(params: z.infer) { - Logger.info('Removing invitation', { + const logger = await getLogger(); + + logger.info('Removing invitation', { name: this.namespace, ...params, }); @@ -33,7 +35,7 @@ export class AccountInvitationsService { throw error; } - Logger.info('Invitation successfully removed', { + logger.info('Invitation successfully removed', { ...params, name: this.namespace, }); @@ -42,7 +44,9 @@ export class AccountInvitationsService { } async updateInvitation(params: z.infer) { - Logger.info('Updating invitation', { + const logger = await getLogger(); + + logger.info('Updating invitation', { ...params, name: this.namespace, }); @@ -60,7 +64,7 @@ export class AccountInvitationsService { throw error; } - Logger.info('Invitation successfully updated', { + logger.info('Invitation successfully updated', { ...params, name: this.namespace, }); @@ -75,7 +79,9 @@ export class AccountInvitationsService { invitations: z.infer['invitations']; accountSlug: string; }) { - Logger.info( + const logger = await getLogger(); + + logger.info( { account: accountSlug, invitations, @@ -91,7 +97,7 @@ export class AccountInvitationsService { .single(); if (!accountResponse.data) { - Logger.error( + logger.error( { accountSlug, name: this.namespace, @@ -108,7 +114,7 @@ export class AccountInvitationsService { }); if (response.error) { - Logger.error( + logger.error( { accountSlug, error: response.error, @@ -124,7 +130,7 @@ export class AccountInvitationsService { ? response.data : [response.data]; - Logger.info( + logger.info( { account: accountSlug, count: responseInvitations.length, @@ -157,7 +163,9 @@ export class AccountInvitationsService { } async renewInvitation(invitationId: number) { - Logger.info('Renewing invitation', { + const logger = await getLogger(); + + logger.info('Renewing invitation', { invitationId, name: this.namespace, }); @@ -177,7 +185,7 @@ export class AccountInvitationsService { throw error; } - Logger.info('Invitation successfully renewed', { + logger.info('Invitation successfully renewed', { invitationId, name: this.namespace, }); diff --git a/packages/features/team-accounts/src/server/services/account-members.service.ts b/packages/features/team-accounts/src/server/services/account-members.service.ts index 1867fcf96..5f7e895eb 100644 --- a/packages/features/team-accounts/src/server/services/account-members.service.ts +++ b/packages/features/team-accounts/src/server/services/account-members.service.ts @@ -3,7 +3,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import 'server-only'; import { z } from 'zod'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; import { RemoveMemberSchema } from '../../schema/remove-member.schema'; @@ -17,12 +17,14 @@ export class AccountMembersService { constructor(private readonly client: SupabaseClient) {} async removeMemberFromAccount(params: z.infer) { + const logger = await getLogger(); + const ctx = { namespace: this.namespace, ...params, }; - Logger.info(ctx, `Removing member from account...`); + logger.info(ctx, `Removing member from account...`); const { data, error } = await this.client .from('accounts_memberships') @@ -33,7 +35,7 @@ export class AccountMembersService { }); if (error) { - Logger.error( + logger.error( { ...ctx, error, @@ -44,7 +46,7 @@ export class AccountMembersService { throw error; } - Logger.info( + logger.info( ctx, `Successfully removed member from account. Verifying seat count...`, ); @@ -57,12 +59,14 @@ export class AccountMembersService { } async updateMemberRole(params: z.infer) { + const logger = await getLogger(); + const ctx = { namespace: this.namespace, ...params, }; - Logger.info(ctx, `Updating member role...`); + logger.info(ctx, `Updating member role...`); const { data, error } = await this.client .from('accounts_memberships') @@ -75,7 +79,7 @@ export class AccountMembersService { }); if (error) { - Logger.error( + logger.error( { ...ctx, error, @@ -86,7 +90,7 @@ export class AccountMembersService { throw error; } - Logger.info(ctx, `Successfully updated member role`); + logger.info(ctx, `Successfully updated member role`); return data; } @@ -94,12 +98,14 @@ export class AccountMembersService { async transferOwnership( params: z.infer, ) { + const logger = await getLogger(); + const ctx = { namespace: this.namespace, ...params, }; - Logger.info(ctx, `Transferring ownership of account...`); + logger.info(ctx, `Transferring ownership of account...`); const { data, error } = await this.client.rpc( 'transfer_team_account_ownership', @@ -110,7 +116,7 @@ export class AccountMembersService { ); if (error) { - Logger.error( + logger.error( { ...ctx, error }, `Failed to transfer ownership of account`, ); @@ -118,7 +124,7 @@ export class AccountMembersService { throw error; } - Logger.info(ctx, `Successfully transferred ownership of account`); + logger.info(ctx, `Successfully transferred ownership of account`); return data; } diff --git a/packages/features/team-accounts/src/server/services/account-per-seat-billing.service.ts b/packages/features/team-accounts/src/server/services/account-per-seat-billing.service.ts index 465dc993c..d1ba73b08 100644 --- a/packages/features/team-accounts/src/server/services/account-per-seat-billing.service.ts +++ b/packages/features/team-accounts/src/server/services/account-per-seat-billing.service.ts @@ -1,7 +1,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import { BillingGatewayService } from '@kit/billing-gateway'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; export class AccountPerSeatBillingService { @@ -10,7 +10,9 @@ export class AccountPerSeatBillingService { constructor(private readonly client: SupabaseClient) {} async getPerSeatSubscriptionItem(accountId: string) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: this.namespace, accountId, @@ -36,7 +38,7 @@ export class AccountPerSeatBillingService { .maybeSingle(); if (error) { - Logger.info( + logger.error( { name: this.namespace, accountId, @@ -49,7 +51,7 @@ export class AccountPerSeatBillingService { } if (!data?.subscription_items) { - Logger.info( + logger.info( { name: this.namespace, accountId }, `No per-seat subscription item found for account ${accountId}. Exiting...`, ); @@ -57,7 +59,7 @@ export class AccountPerSeatBillingService { return; } - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -69,6 +71,7 @@ export class AccountPerSeatBillingService { } async increaseSeats(accountId: string) { + const logger = await getLogger(); const subscription = await this.getPerSeatSubscriptionItem(accountId); if (!subscription) { @@ -85,7 +88,7 @@ export class AccountPerSeatBillingService { const billingGateway = new BillingGatewayService(subscription.provider); - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -96,7 +99,7 @@ export class AccountPerSeatBillingService { const promises = subscriptionItems.map(async (item) => { try { - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -112,7 +115,7 @@ export class AccountPerSeatBillingService { quantity: item.quantity + 1, }); - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -122,7 +125,7 @@ export class AccountPerSeatBillingService { `Subscription item updated successfully`, ); } catch (error) { - Logger.error( + logger.error( { name: this.namespace, accountId, @@ -137,6 +140,7 @@ export class AccountPerSeatBillingService { } async decreaseSeats(accountId: string) { + const logger = await getLogger(); const subscription = await this.getPerSeatSubscriptionItem(accountId); if (!subscription) { @@ -151,7 +155,7 @@ export class AccountPerSeatBillingService { return; } - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -164,7 +168,7 @@ export class AccountPerSeatBillingService { const promises = subscriptionItems.map(async (item) => { try { - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -180,7 +184,7 @@ export class AccountPerSeatBillingService { quantity: item.quantity - 1, }); - Logger.info( + logger.info( { name: this.namespace, accountId, @@ -190,7 +194,7 @@ export class AccountPerSeatBillingService { `Subscription item updated successfully`, ); } catch (error) { - Logger.error( + logger.error( { name: this.namespace, accountId, diff --git a/packages/features/team-accounts/src/server/services/create-team-account.service.ts b/packages/features/team-accounts/src/server/services/create-team-account.service.ts index e69f0d9f2..596364981 100644 --- a/packages/features/team-accounts/src/server/services/create-team-account.service.ts +++ b/packages/features/team-accounts/src/server/services/create-team-account.service.ts @@ -1,6 +1,6 @@ import { SupabaseClient } from '@supabase/supabase-js'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; export class CreateTeamAccountService { @@ -8,13 +8,15 @@ export class CreateTeamAccountService { constructor(private readonly client: SupabaseClient) {} - createNewOrganizationAccount(params: { name: string; userId: string }) { - Logger.info( + async createNewOrganizationAccount(params: { name: string; userId: string }) { + const logger = await getLogger(); + + logger.info( { ...params, namespace: this.namespace }, `Creating new team account...`, ); - return this.client.rpc('create_account', { + return await this.client.rpc('create_account', { account_name: params.name, }); } diff --git a/packages/features/team-accounts/src/server/services/delete-team-account.service.ts b/packages/features/team-accounts/src/server/services/delete-team-account.service.ts index bf527c447..95bd612b8 100644 --- a/packages/features/team-accounts/src/server/services/delete-team-account.service.ts +++ b/packages/features/team-accounts/src/server/services/delete-team-account.service.ts @@ -2,7 +2,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import 'server-only'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; export class DeleteTeamAccountService { @@ -24,7 +24,9 @@ export class DeleteTeamAccountService { userId: string; }, ) { - Logger.info( + const logger = await getLogger(); + + logger.info( { name: this.namespace, accountId: params.accountId, @@ -40,7 +42,7 @@ export class DeleteTeamAccountService { .eq('id', params.accountId); if (error) { - Logger.error( + logger.error( { name: this.namespace, accountId: params.accountId, @@ -53,7 +55,7 @@ export class DeleteTeamAccountService { throw new Error('Failed to delete team account'); } - Logger.info( + logger.info( { name: this.namespace, accountId: params.accountId, diff --git a/packages/features/team-accounts/src/server/services/leave-team-account.service.ts b/packages/features/team-accounts/src/server/services/leave-team-account.service.ts index a889eb68a..dd7ae45af 100644 --- a/packages/features/team-accounts/src/server/services/leave-team-account.service.ts +++ b/packages/features/team-accounts/src/server/services/leave-team-account.service.ts @@ -3,7 +3,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import 'server-only'; import { z } from 'zod'; -import { Logger } from '@kit/shared/logger'; +import { getLogger } from '@kit/shared/logger'; import { Database } from '@kit/supabase/database'; const Schema = z.object({ @@ -17,12 +17,14 @@ export class LeaveTeamAccountService { constructor(private readonly adminClient: SupabaseClient) {} async leaveTeamAccount(params: z.infer) { + const logger = await getLogger(); + const ctx = { ...params, name: this.namespace, }; - Logger.info(ctx, 'Leaving team account'); + logger.info(ctx, 'Leaving team account...'); const { accountId, userId } = Schema.parse(params); @@ -35,11 +37,11 @@ export class LeaveTeamAccountService { }); if (error) { - Logger.error({ ...ctx, error }, 'Failed to leave team account'); + logger.error({ ...ctx, error }, 'Failed to leave team account'); throw new Error('Failed to leave team account'); } - Logger.info(ctx, 'Successfully left team account'); + logger.info(ctx, 'Successfully left team account'); } } diff --git a/packages/mailers/README.md b/packages/mailers/README.md index 8e72fe613..aef5e5fc8 100644 --- a/packages/mailers/README.md +++ b/packages/mailers/README.md @@ -27,13 +27,17 @@ MAILER_PROVIDER=cloudflare ### Send an email -```javascript -import { Mailer } from '@kit/mailers'; +```tsx +import { getMailer } from '@kit/mailers'; -Mailer.sendEmail({ +async function sendEmail() { + const mailer = await getMailer(); + + return mailer.sendEmail({ to: '', from: '', subject: 'Hello', text: 'Hello, World!' -}); + }); +} ``` \ No newline at end of file diff --git a/packages/mailers/src/index.ts b/packages/mailers/src/index.ts index 51f4af572..349cef6a5 100644 --- a/packages/mailers/src/index.ts +++ b/packages/mailers/src/index.ts @@ -5,28 +5,10 @@ const MAILER_PROVIDER = z .default('nodemailer') .parse(process.env.MAILER_PROVIDER); -/** - * @description A mailer interface that can be implemented by any mailer. - * We export a single mailer implementation using Nodemailer. You can add more mailers or replace the existing one. - * @example - * ```ts - * import { Mailer } from '@kit/mailers'; - * - * const mailer = new Mailer(); - * - * mailer.sendEmail({ - * from: '', - * to: '', - * subject: 'Hello', - * text: 'Hello, World!' - * }); - */ -export const Mailer = await getMailer(); - /** * @description Get the mailer based on the environment variable. */ -async function getMailer() { +export async function getMailer() { switch (MAILER_PROVIDER) { case 'nodemailer': { const { Nodemailer } = await import('./impl/nodemailer'); diff --git a/packages/monitoring/src/instrumentation.ts b/packages/monitoring/src/instrumentation.ts index 70e228ac4..8feeb5602 100644 --- a/packages/monitoring/src/instrumentation.ts +++ b/packages/monitoring/src/instrumentation.ts @@ -17,10 +17,9 @@ const DEFAULT_INSTRUMENTATION_PROVIDER = process.env * Please set the MONITORING_INSTRUMENTATION_PROVIDER environment variable to register the monitoring instrumentation provider. */ export async function registerInstrumentation() { - if ( - process.env.NEXT_RUNTIME !== 'nodejs' || - !DEFAULT_INSTRUMENTATION_PROVIDER - ) { + if (!DEFAULT_INSTRUMENTATION_PROVIDER) { + console.info(`No instrumentation provider specified. Skipping...`); + return; } diff --git a/packages/shared/src/logger/index.ts b/packages/shared/src/logger/index.ts index e6610e16b..c21d244dc 100644 --- a/packages/shared/src/logger/index.ts +++ b/packages/shared/src/logger/index.ts @@ -20,6 +20,4 @@ async function getLogger(): Promise { } } -const Logger = await getLogger(); - -export { Logger }; +export { getLogger }; diff --git a/packages/shared/src/utils.ts b/packages/shared/src/utils.ts index f440452f7..a17807e98 100644 --- a/packages/shared/src/utils.ts +++ b/packages/shared/src/utils.ts @@ -1,7 +1,14 @@ +/** + * Check if the code is running in a browser environment. + */ export function isBrowser() { return typeof window !== 'undefined'; } +/** + *@name formatCurrency + * @description Format the currency based on the currency code + */ export function formatCurrency(currencyCode: string, value: string | number) { return new Intl.NumberFormat('en-US', { style: 'currency', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4a3e0619..7c0354780 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,7 +103,7 @@ importers: version: 5.28.6(react@18.2.0) '@tanstack/react-query-next-experimental': specifier: ^5.28.14 - version: 5.28.14(@tanstack/react-query@5.28.6)(next@14.2.0-canary.61)(react@18.2.0) + version: 5.28.14(@tanstack/react-query@5.28.6)(next@14.2.0-canary.62)(react@18.2.0) '@tanstack/react-table': specifier: ^8.15.3 version: 8.15.3(react-dom@18.2.0)(react@18.2.0) @@ -112,7 +112,7 @@ importers: version: 3.6.0 edge-csrf: specifier: ^1.0.9 - version: 1.0.9(next@14.2.0-canary.61) + version: 1.0.9(next@14.2.0-canary.62) i18next: specifier: ^23.10.1 version: 23.10.1 @@ -123,11 +123,11 @@ importers: specifier: ^0.363.0 version: 0.363.0(react@18.2.0) next: - specifier: 14.2.0-canary.61 - version: 14.2.0-canary.61(react-dom@18.2.0)(react@18.2.0) + specifier: 14.2.0-canary.62 + version: 14.2.0-canary.62(react-dom@18.2.0)(react@18.2.0) next-sitemap: specifier: ^4.2.3 - version: 4.2.3(next@14.2.0-canary.61) + version: 4.2.3(next@14.2.0-canary.62) next-themes: specifier: 0.3.0 version: 0.3.0(react-dom@18.2.0)(react@18.2.0) @@ -2302,8 +2302,8 @@ packages: resolution: {integrity: sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw==} dev: false - /@next/env@14.2.0-canary.61: - resolution: {integrity: sha512-Ueqse8kdwaoebGrpSo60M4/cjFaMJEE7BMsKZufYwZDTlE0qXw7N4GsdVpUZzJG00sXf6CoTnCU1lCTPrUMC4g==} + /@next/env@14.2.0-canary.62: + resolution: {integrity: sha512-K5lmKK/TalagQELw3W0hKDXmNGGXY3Zxw3yH27y9DOT7evhiJvK2Ywq5uN4lEjYHkeW+QbyC/OjUIcK3RUSHbQ==} dev: false /@next/eslint-plugin-next@14.1.4: @@ -2330,8 +2330,8 @@ packages: dev: false optional: true - /@next/swc-darwin-arm64@14.2.0-canary.61: - resolution: {integrity: sha512-mMlp2/hvtaBbCY5qYhuvAqX9Z/aFC+Rgme4FjFSxq2C3TC/mL3G4fVG/TVl7bqjikKCxSvJgiWXRwvhIaqGktw==} + /@next/swc-darwin-arm64@14.2.0-canary.62: + resolution: {integrity: sha512-Cm53nqD/u7I1wo4xeULBZ6YjThK7Mk+ThaoYJu69varPPHsahpzbf/rM3ZkW3UB5Cgl5I7N3mNIb+Z9U/JZemw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -2357,8 +2357,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@14.2.0-canary.61: - resolution: {integrity: sha512-4bEjO0WK6keRi972eAY1AfvTXOQRHnM59klNqnUh5zfalbi7VkEdluhYAZOop2NycCHjF+m8p+ytYtrF1uCO1Q==} + /@next/swc-darwin-x64@14.2.0-canary.62: + resolution: {integrity: sha512-2cSC0EOiJHe9kQad5TR/tXJuIc85JLBUeRl4x20jdsa0oIuOdsvksPA9TAROWLebuIkysPAsfmrbCwlKZk5yDw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -2384,8 +2384,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@14.2.0-canary.61: - resolution: {integrity: sha512-wIXc3EdxrETlL2XwlGlLQkMU9godhNSMAXxiJotd/mhN3K4iKajPahAStvFxY2Zwc/on2IBa0NpUGpzDONNt9A==} + /@next/swc-linux-arm64-gnu@14.2.0-canary.62: + resolution: {integrity: sha512-Iow3tpn05nK2hW1nBzk1rCEVgbwakvlPViFZMxYg4FxEEoIcxcsxTMnG7sjJGmgrzCW7vfCVc+AM3Gy6bZXxqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2411,8 +2411,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@14.2.0-canary.61: - resolution: {integrity: sha512-95aMF55sq2N6+5iLEqxCfz7ccYMBURQ8D0KYmcq+rMJTE5z/qvxEToSJWAbV4jGyd2Eq/vXjPdR1rFytv2FnOw==} + /@next/swc-linux-arm64-musl@14.2.0-canary.62: + resolution: {integrity: sha512-dTugxbWEi95dNFn59C7RYuNTJ2jOVbDgD9lJmFtAJO46XPtN8IySJSe/5zB9YECA1apK2xWf5XaSbpuh5vWT8Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2438,8 +2438,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@14.2.0-canary.61: - resolution: {integrity: sha512-LWG5OC9hNSCYtDb+7MQcIjE1PO70Sho+ZJkqJnmLxJ08Atp/nJQBo9nAMjORdcO5Nz+hPNVY5vmrY+5Fl5kadw==} + /@next/swc-linux-x64-gnu@14.2.0-canary.62: + resolution: {integrity: sha512-yGKHq4PfPgQO+IVWVOxbdv5pdIib/jwr62NsPKbY+t16gDB6RNTPhOcuhkQTvDBYlh+VF3vmhenlM5Ci0W5QQQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2465,8 +2465,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@14.2.0-canary.61: - resolution: {integrity: sha512-EjOXbSmDTPVi8xkOix4/WYJM6OUert+lfBtdUJBRba+oGiRw/mheih8FliFZKFOmQbPYj67A9z/QCus2ZDnfSw==} + /@next/swc-linux-x64-musl@14.2.0-canary.62: + resolution: {integrity: sha512-Nw/l0Z4jzAL5VP1Z2mjNAMF7n+9aOTZgFJCtJ6C0aBf5rvZY3BrVDXblK57v6q1bWqU6FRGYmDava3h4B2i0hQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2492,8 +2492,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@14.2.0-canary.61: - resolution: {integrity: sha512-TK8oV4ozzUGWAwvZp/0SBsNgAUhrUFLWCMSXsFHz+YMRjHg7nT0KdK8BYh2Ln4Qt0jjDTUHbI1jaQKxmSMEMmA==} + /@next/swc-win32-arm64-msvc@14.2.0-canary.62: + resolution: {integrity: sha512-FgS+pzblgiGe1iA2zvIxH5FTz/NVkXknhVgE3g0A5pIQeIfHn5hbki501fCBKvYujhsP094pSGePI9Hi35KFYA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -2519,8 +2519,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@14.2.0-canary.61: - resolution: {integrity: sha512-i0iWCehuLKDOfVbQ6MEKG9v0lfcJU0DPWkYINFSi6p3fkFobI/+7DVT3KvYH5VVng/+opx+pA6cesV5eyQnBtw==} + /@next/swc-win32-ia32-msvc@14.2.0-canary.62: + resolution: {integrity: sha512-1cns8tyYICpspnhVC6FoRmd2Nal7uSXLPW4l1jX0+ofpifcmRy6Lra127/kdl8l+00W6ERQ/QAhx8uiYrw3VGQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -2546,8 +2546,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@14.2.0-canary.61: - resolution: {integrity: sha512-WB0UjpWcu+oXQOMFDTHDZWKcL2jiXeQfN+1RRkb0x7ZjVxvA/O66vOJE08fLSu7rdymLiGXxX+AKlGFq1Tpisg==} + /@next/swc-win32-x64-msvc@14.2.0-canary.62: + resolution: {integrity: sha512-67gfnbOVzVrg4lsRhE9qHQegpPl/ljHMNFw4JyIOlLmCG7daHe6wgKmXGAyYBSZ6F6P9HiQWHcqU/qTHtw2lFw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -5038,7 +5038,7 @@ packages: /@tanstack/query-core@5.28.6: resolution: {integrity: sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==} - /@tanstack/react-query-next-experimental@5.28.14(@tanstack/react-query@5.28.6)(next@14.2.0-canary.61)(react@18.2.0): + /@tanstack/react-query-next-experimental@5.28.14(@tanstack/react-query@5.28.6)(next@14.2.0-canary.62)(react@18.2.0): resolution: {integrity: sha512-gGHx3uJkZNYYpFNFk8eEo96ssiFE2OmYA49wszHxHrtO5nL7kzRcnJF8SALGpqSEjo5D3fLMH24MrhbBsO0sig==} peerDependencies: '@tanstack/react-query': ^5.28.14 @@ -5046,7 +5046,7 @@ packages: react: ^18.0.0 dependencies: '@tanstack/react-query': 5.28.6(react@18.2.0) - next: 14.2.0-canary.61(react-dom@18.2.0)(react@18.2.0) + next: 14.2.0-canary.62(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false @@ -6858,12 +6858,12 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - /edge-csrf@1.0.9(next@14.2.0-canary.61): + /edge-csrf@1.0.9(next@14.2.0-canary.62): resolution: {integrity: sha512-3F89YTh42UDdISr3s9AEcgJDLi4ysgjGfnybzF0LuZGaG2W31h1ZwgWwEQBLMj04lAklcP4XHZYi7vk9o8zcbg==} peerDependencies: next: ^13.0.0 || ^14.0.0 dependencies: - next: 14.2.0-canary.61(react-dom@18.2.0)(react@18.2.0) + next: 14.2.0-canary.62(react-dom@18.2.0)(react@18.2.0) dev: false /editorconfig@1.0.4: @@ -9648,7 +9648,7 @@ packages: - supports-color dev: false - /next-sitemap@4.2.3(next@14.2.0-canary.61): + /next-sitemap@4.2.3(next@14.2.0-canary.62): resolution: {integrity: sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==} engines: {node: '>=14.18'} hasBin: true @@ -9659,7 +9659,7 @@ packages: '@next/env': 13.5.6 fast-glob: 3.3.2 minimist: 1.2.8 - next: 14.2.0-canary.61(react-dom@18.2.0)(react@18.2.0) + next: 14.2.0-canary.62(react-dom@18.2.0)(react@18.2.0) dev: false /next-themes@0.3.0(react-dom@18.2.0)(react@18.2.0): @@ -9751,8 +9751,8 @@ packages: - babel-plugin-macros dev: false - /next@14.2.0-canary.61(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-UbdoNkGX04TO0Q0N3k7fmiNCliE1yihVBHd/nwg2zMnpjB6dGU3r1UNgCBpfUUlrs1t19FAWazfVQANOOfBT4w==} + /next@14.2.0-canary.62(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-SsS+fpJ/anrtLgeCC76V9WOlreZanUYsuKsRMx+FDwOJ3ZnbZkohu3+RRLIQM1vtWcp707iV11+OlF/qgOldCA==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -9769,7 +9769,7 @@ packages: sass: optional: true dependencies: - '@next/env': 14.2.0-canary.61 + '@next/env': 14.2.0-canary.62 '@swc/helpers': 0.5.5 busboy: 1.6.0 caniuse-lite: 1.0.30001600 @@ -9779,15 +9779,15 @@ packages: react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(react@18.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.0-canary.61 - '@next/swc-darwin-x64': 14.2.0-canary.61 - '@next/swc-linux-arm64-gnu': 14.2.0-canary.61 - '@next/swc-linux-arm64-musl': 14.2.0-canary.61 - '@next/swc-linux-x64-gnu': 14.2.0-canary.61 - '@next/swc-linux-x64-musl': 14.2.0-canary.61 - '@next/swc-win32-arm64-msvc': 14.2.0-canary.61 - '@next/swc-win32-ia32-msvc': 14.2.0-canary.61 - '@next/swc-win32-x64-msvc': 14.2.0-canary.61 + '@next/swc-darwin-arm64': 14.2.0-canary.62 + '@next/swc-darwin-x64': 14.2.0-canary.62 + '@next/swc-linux-arm64-gnu': 14.2.0-canary.62 + '@next/swc-linux-arm64-musl': 14.2.0-canary.62 + '@next/swc-linux-x64-gnu': 14.2.0-canary.62 + '@next/swc-linux-x64-musl': 14.2.0-canary.62 + '@next/swc-win32-arm64-msvc': 14.2.0-canary.62 + '@next/swc-win32-ia32-msvc': 14.2.0-canary.62 + '@next/swc-win32-x64-msvc': 14.2.0-canary.62 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros