chore: formatting updates and lockfile changes

This commit is contained in:
Tiago Yamamoto 2025-12-15 10:40:55 -03:00
parent 5c45557537
commit 3be9807d88
8 changed files with 4851 additions and 89 deletions

View file

@ -3,8 +3,8 @@ import { AdminService } from './admin.service';
import { AdminController } from './admin.controller'; import { AdminController } from './admin.controller';
@Module({ @Module({
providers: [AdminService], providers: [AdminService],
controllers: [AdminController], controllers: [AdminController],
exports: [AdminService], exports: [AdminService],
}) })
export class AdminModule { } export class AdminModule {}

View file

@ -16,4 +16,4 @@ import { AdminModule } from './admin';
controllers: [AppController], controllers: [AppController],
providers: [AppService], providers: [AppService],
}) })
export class AppModule { } export class AppModule {}

View file

@ -5,11 +5,17 @@ import { PlansService } from './plans.service';
@ApiTags('Plans') @ApiTags('Plans')
@Controller('plans') @Controller('plans')
export class PlansController { export class PlansController {
constructor(private readonly plansService: PlansService) { } constructor(private readonly plansService: PlansService) {}
@Get() @ApiOperation({ summary: 'Get all plans' }) @Get()
getAllPlans() { return this.plansService.getAllPlans(); } @ApiOperation({ summary: 'Get all plans' })
getAllPlans() {
return this.plansService.getAllPlans();
}
@Get(':id') @ApiOperation({ summary: 'Get plan by ID' }) @Get(':id')
getPlanById(@Param('id') id: string) { return this.plansService.getPlanById(id); } @ApiOperation({ summary: 'Get plan by ID' })
getPlanById(@Param('id') id: string) {
return this.plansService.getPlanById(id);
}
} }

View file

@ -3,8 +3,8 @@ import { PlansService } from './plans.service';
import { PlansController } from './plans.controller'; import { PlansController } from './plans.controller';
@Module({ @Module({
providers: [PlansService], providers: [PlansService],
controllers: [PlansController], controllers: [PlansController],
exports: [PlansService], exports: [PlansService],
}) })
export class PlansModule { } export class PlansModule {}

View file

@ -1,35 +1,59 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
export interface Plan { export interface Plan {
id: string; id: string;
name: string; name: string;
description: string; description: string;
monthlyPrice: number; monthlyPrice: number;
yearlyPrice: number; yearlyPrice: number;
features: string[]; features: string[];
popular?: boolean; popular?: boolean;
} }
@Injectable() @Injectable()
export class PlansService { export class PlansService {
private readonly plans: Plan[] = [ private readonly plans: Plan[] = [
{ {
id: 'starter', name: 'Starter', description: 'For small companies', id: 'starter',
monthlyPrice: 99, yearlyPrice: 990, name: 'Starter',
features: ['5 job postings', 'Basic analytics', 'Email support'], description: 'For small companies',
}, monthlyPrice: 99,
{ yearlyPrice: 990,
id: 'professional', name: 'Professional', description: 'For growing companies', features: ['5 job postings', 'Basic analytics', 'Email support'],
monthlyPrice: 299, yearlyPrice: 2990, popular: true, },
features: ['25 job postings', 'Advanced analytics', 'Priority support', 'Featured listings'], {
}, id: 'professional',
{ name: 'Professional',
id: 'enterprise', name: 'Enterprise', description: 'For large organizations', description: 'For growing companies',
monthlyPrice: 799, yearlyPrice: 7990, monthlyPrice: 299,
features: ['Unlimited postings', 'Custom analytics', 'Dedicated support', 'API access'], yearlyPrice: 2990,
}, popular: true,
]; features: [
'25 job postings',
'Advanced analytics',
'Priority support',
'Featured listings',
],
},
{
id: 'enterprise',
name: 'Enterprise',
description: 'For large organizations',
monthlyPrice: 799,
yearlyPrice: 7990,
features: [
'Unlimited postings',
'Custom analytics',
'Dedicated support',
'API access',
],
},
];
getAllPlans(): Plan[] { return this.plans; } getAllPlans(): Plan[] {
getPlanById(id: string): Plan | undefined { return this.plans.find(p => p.id === id); } return this.plans;
}
getPlanById(id: string): Plan | undefined {
return this.plans.find((p) => p.id === id);
}
} }

View file

@ -4,8 +4,8 @@ import { StripeService } from './stripe.service';
@Global() @Global()
@Module({ @Module({
imports: [ConfigModule], imports: [ConfigModule],
providers: [StripeService], providers: [StripeService],
exports: [StripeService], exports: [StripeService],
}) })
export class StripeModule { } export class StripeModule {}

View file

@ -4,59 +4,74 @@ import Stripe from 'stripe';
@Injectable() @Injectable()
export class StripeService implements OnModuleInit { export class StripeService implements OnModuleInit {
private stripe: Stripe; private stripe: Stripe;
constructor(private configService: ConfigService) { } constructor(private configService: ConfigService) {}
onModuleInit() { onModuleInit() {
const secretKey = this.configService.get<string>('STRIPE_SECRET_KEY'); const secretKey = this.configService.get<string>('STRIPE_SECRET_KEY');
if (!secretKey) { if (!secretKey) {
console.warn('STRIPE_SECRET_KEY not configured'); console.warn('STRIPE_SECRET_KEY not configured');
return; return;
}
this.stripe = new Stripe(secretKey, { apiVersion: '2025-11-17.clover' as const });
} }
this.stripe = new Stripe(secretKey, {
apiVersion: '2025-11-17.clover' as const,
});
}
getClient(): Stripe { return this.stripe; } getClient(): Stripe {
return this.stripe;
}
async createCustomer(email: string, name: string) { async createCustomer(email: string, name: string) {
return this.stripe.customers.create({ email, name }); return this.stripe.customers.create({ email, name });
} }
async createSubscription(customerId: string, priceId: string) { async createSubscription(customerId: string, priceId: string) {
return this.stripe.subscriptions.create({ return this.stripe.subscriptions.create({
customer: customerId, customer: customerId,
items: [{ price: priceId }], items: [{ price: priceId }],
payment_behavior: 'default_incomplete', payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'], expand: ['latest_invoice.payment_intent'],
}); });
} }
async cancelSubscription(subscriptionId: string) { async cancelSubscription(subscriptionId: string) {
return this.stripe.subscriptions.cancel(subscriptionId); return this.stripe.subscriptions.cancel(subscriptionId);
} }
async listSubscriptions(customerId: string) { async listSubscriptions(customerId: string) {
return this.stripe.subscriptions.list({ customer: customerId, status: 'all' }); return this.stripe.subscriptions.list({
} customer: customerId,
status: 'all',
});
}
async createCheckoutSession(customerId: string, priceId: string, successUrl: string, cancelUrl: string) { async createCheckoutSession(
return this.stripe.checkout.sessions.create({ customerId: string,
customer: customerId, priceId: string,
payment_method_types: ['card'], successUrl: string,
line_items: [{ price: priceId, quantity: 1 }], cancelUrl: string,
mode: 'subscription', ) {
success_url: successUrl, return this.stripe.checkout.sessions.create({
cancel_url: cancelUrl, customer: customerId,
}); payment_method_types: ['card'],
} line_items: [{ price: priceId, quantity: 1 }],
mode: 'subscription',
success_url: successUrl,
cancel_url: cancelUrl,
});
}
async createBillingPortalSession(customerId: string, returnUrl: string) { async createBillingPortalSession(customerId: string, returnUrl: string) {
return this.stripe.billingPortal.sessions.create({ customer: customerId, return_url: returnUrl }); return this.stripe.billingPortal.sessions.create({
} customer: customerId,
return_url: returnUrl,
});
}
constructWebhookEvent(body: Buffer, signature: string): Stripe.Event { constructWebhookEvent(body: Buffer, signature: string): Stripe.Event {
const secret = this.configService.get<string>('STRIPE_WEBHOOK_SECRET')!; const secret = this.configService.get<string>('STRIPE_WEBHOOK_SECRET')!;
return this.stripe.webhooks.constructEvent(body, signature, secret); return this.stripe.webhooks.constructEvent(body, signature, secret);
} }
} }

File diff suppressed because it is too large Load diff