kybernus 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +2 -2
- package/templates/java-spring/clean/.gitignore.hbs +72 -0
- package/templates/java-spring/clean/docker-compose.yml.hbs +6 -3
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/application/usecase/PaymentUseCase.java.hbs +21 -17
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/persistence/entity/UserEntity.java.hbs +52 -0
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/persistence/repository/JpaUserRepository.java.hbs +12 -0
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/security/JwtAuthenticationFilter.java.hbs +64 -0
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/security/SecurityConfig.java.hbs +36 -0
- package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/stripe/StripeGateway.java.hbs +63 -0
- package/templates/java-spring/clean/src/main/resources/application.properties.hbs +6 -7
- package/templates/java-spring/hexagonal/.gitignore.hbs +72 -0
- package/templates/java-spring/hexagonal/docker-compose.yml.hbs +6 -3
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/security/JwtFilter.java.hbs +71 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/security/SecurityConfig.java.hbs +35 -0
- package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/core/service/PaymentService.java.hbs +3 -3
- package/templates/java-spring/hexagonal/src/main/resources/application.properties.hbs +4 -4
- package/templates/java-spring/mvc/.gitignore.hbs +72 -0
- package/templates/java-spring/mvc/docker-compose.yml.hbs +6 -3
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/config/SecurityConfig.java.hbs +13 -12
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/AuthController.java.hbs +9 -8
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/PaymentsController.java.hbs +5 -6
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/service/StripeService.java.hbs +3 -3
- package/templates/java-spring/mvc/src/main/resources/application.yml.hbs +29 -26
- package/templates/nestjs/clean/.gitignore.hbs +42 -0
- package/templates/nestjs/clean/Dockerfile.hbs +6 -3
- package/templates/nestjs/clean/docker-compose.yml.hbs +1 -11
- package/templates/nestjs/clean/package.json.hbs +51 -41
- package/templates/nestjs/clean/src/app.module.ts.hbs +2 -1
- package/templates/nestjs/clean/src/application/payment.service.ts.hbs +72 -72
- package/templates/nestjs/clean/src/domain/entities/user.entity.ts.hbs +2 -2
- package/templates/nestjs/clean/src/domain/repositories/user.repository.ts.hbs +2 -2
- package/templates/nestjs/clean/src/infrastructure/database/repositories/prisma.user.repository.ts.hbs +18 -18
- package/templates/nestjs/clean/src/infrastructure/http/health.controller.ts.hbs +9 -0
- package/templates/nestjs/clean/src/main.ts.hbs +1 -4
- package/templates/nestjs/clean/src/payment.module.ts.hbs +12 -12
- package/templates/nestjs/hexagonal/.gitignore.hbs +42 -0
- package/templates/nestjs/hexagonal/Dockerfile.hbs +6 -3
- package/templates/nestjs/hexagonal/docker-compose.yml.hbs +1 -11
- package/templates/nestjs/hexagonal/package.json.hbs +51 -41
- package/templates/nestjs/hexagonal/src/adapters/inbound/health.controller.ts.hbs +9 -0
- package/templates/nestjs/hexagonal/src/app.module.ts.hbs +2 -1
- package/templates/nestjs/hexagonal/src/core/domain/user.entity.ts.hbs +6 -6
- package/templates/nestjs/hexagonal/src/core/ports/ports.ts.hbs +4 -4
- package/templates/nestjs/hexagonal/src/main.ts.hbs +1 -4
- package/templates/nestjs/mvc/.gitignore.hbs +42 -0
- package/templates/nestjs/mvc/Dockerfile.hbs +6 -3
- package/templates/nestjs/mvc/docker-compose.yml.hbs +1 -11
- package/templates/nestjs/mvc/package.json.hbs +49 -39
- package/templates/nestjs/mvc/src/auth/auth.controller.ts.hbs +11 -1
- package/templates/nestjs/mvc/src/auth/auth.service.ts.hbs +3 -1
- package/templates/nestjs/mvc/src/controllers/health.controller.ts.hbs +6 -6
- package/templates/nestjs/mvc/src/main.ts.hbs +1 -4
- package/templates/nestjs/mvc/src/models/create-item.dto.ts.hbs +5 -2
- package/templates/nestjs/mvc/src/prisma/prisma.service.ts.hbs +1 -0
- package/templates/nextjs/mvc/.gitignore.hbs +42 -0
- package/templates/nextjs/mvc/Dockerfile.hbs +23 -8
- package/templates/nextjs/mvc/docker-compose.yml.hbs +1 -1
- package/templates/nextjs/mvc/package.json.hbs +46 -36
- package/templates/nodejs-express/clean/.gitignore.hbs +42 -0
- package/templates/nodejs-express/clean/Dockerfile.hbs +6 -1
- package/templates/nodejs-express/clean/docker-compose.yml.hbs +2 -2
- package/templates/nodejs-express/clean/package.json.hbs +12 -2
- package/templates/nodejs-express/clean/src/config.ts.hbs +11 -0
- package/templates/nodejs-express/clean/src/domain/entities/User.ts.hbs +46 -8
- package/templates/nodejs-express/hexagonal/.gitignore.hbs +42 -0
- package/templates/nodejs-express/hexagonal/Dockerfile.hbs +1 -1
- package/templates/nodejs-express/hexagonal/docker-compose.yml.hbs +2 -2
- package/templates/nodejs-express/hexagonal/package.json.hbs +12 -2
- package/templates/nodejs-express/hexagonal/src/adapters/inbound/http/PaymentController.ts.hbs +21 -38
- package/templates/nodejs-express/hexagonal/src/adapters/outbound/persistence/prisma.ts.hbs +2 -0
- package/templates/nodejs-express/hexagonal/src/config.ts.hbs +9 -0
- package/templates/nodejs-express/hexagonal/src/core/AuthService.ts.hbs +5 -5
- package/templates/nodejs-express/hexagonal/src/core/PaymentService.ts.hbs +7 -22
- package/templates/nodejs-express/hexagonal/src/core/domain/entities/User.ts.hbs +24 -4
- package/templates/nodejs-express/mvc/.gitignore.hbs +42 -0
- package/templates/nodejs-express/mvc/package.json.hbs +12 -2
- package/templates/python-fastapi/clean/.gitignore.hbs +76 -0
- package/templates/python-fastapi/clean/app/application/services/payment_service.py.hbs +3 -3
- package/templates/python-fastapi/clean/app/config.py.hbs +6 -7
- package/templates/python-fastapi/clean/app/domain/usecases/login_user.py.hbs +15 -0
- package/templates/python-fastapi/clean/app/infrastructure/http/auth_controller.py.hbs +40 -6
- package/templates/python-fastapi/clean/app/infrastructure/http/payment_controller.py.hbs +5 -4
- package/templates/python-fastapi/clean/app/infrastructure/security/jwt.py.hbs +23 -0
- package/templates/python-fastapi/clean/app/main.py.hbs +3 -0
- package/templates/python-fastapi/clean/docker-compose.yml.hbs +5 -12
- package/templates/python-fastapi/clean/requirements.txt.hbs +3 -0
- package/templates/python-fastapi/hexagonal/.gitignore.hbs +76 -0
- package/templates/python-fastapi/hexagonal/app/adapters/inbound/http_adapter.py.hbs +6 -9
- package/templates/python-fastapi/hexagonal/app/adapters/inbound/payment_http_adapter.py.hbs +4 -3
- package/templates/python-fastapi/hexagonal/app/adapters/outbound/stripe_adapter.py.hbs +30 -19
- package/templates/python-fastapi/hexagonal/app/config.py.hbs +14 -4
- package/templates/python-fastapi/hexagonal/app/core/domain/user.py.hbs +3 -1
- package/templates/python-fastapi/hexagonal/app/core/payment_service.py.hbs +28 -18
- package/templates/python-fastapi/hexagonal/app/core/ports/__init__.py.hbs +3 -0
- package/templates/python-fastapi/hexagonal/app/core/ports/user_repository.py.hbs +15 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/database/session.py.hbs +7 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/database/user_repository.py.hbs +53 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/security/__init__.py.hbs +0 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/security/adapters.py.hbs +23 -0
- package/templates/python-fastapi/hexagonal/app/infrastructure/security/jwt.py.hbs +23 -0
- package/templates/python-fastapi/hexagonal/docker-compose.yml.hbs +5 -12
- package/templates/python-fastapi/hexagonal/requirements.txt.hbs +4 -0
- package/templates/python-fastapi/mvc/.gitignore.hbs +76 -0
- package/templates/python-fastapi/mvc/app/controllers/payments.py.hbs +3 -17
- package/templates/python-fastapi/mvc/app/middleware/security.py.hbs +24 -3
- package/templates/python-fastapi/mvc/app/schemas/item.py.hbs +3 -1
- package/templates/python-fastapi/mvc/docker-compose.yml.hbs +5 -12
- package/templates/python-fastapi/mvc/requirements.txt.hbs +3 -1
- package/templates/nodejs-express/hexagonal/src/adapters/outbound/persistence/prisma.ts +0 -5
|
@@ -6,85 +6,85 @@ import { StripeProvider } from '../infrastructure/stripe.provider';
|
|
|
6
6
|
|
|
7
7
|
@Injectable()
|
|
8
8
|
export class PaymentService {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly userRepository: UserRepository,
|
|
11
|
+
private readonly stripeProvider: StripeProvider,
|
|
12
|
+
private readonly configService: ConfigService,
|
|
13
|
+
) {}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
async createCheckoutSession(userId: string, priceId: string) {
|
|
16
|
+
const user = await this.userRepository.findById(userId);
|
|
17
|
+
if (!user) throw new NotFoundException('User not found');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
let customerId = user.stripeCustomerId;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
if (!customerId) {
|
|
22
|
+
const customer = await this.stripeProvider.createCustomer(user.email, userId);
|
|
23
|
+
customerId = customer.id;
|
|
24
|
+
user.stripeCustomerId = customerId;
|
|
25
|
+
await this.userRepository.save(user);
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
return this.stripeProvider.createCheckoutSession(
|
|
29
|
+
customerId,
|
|
30
|
+
priceId,
|
|
31
|
+
userId,
|
|
32
|
+
`${this.configService.get('FRONTEND_URL')}/success?session_id={CHECKOUT_SESSION_ID}`,
|
|
33
|
+
`${this.configService.get('FRONTEND_URL')}/cancel`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
async createPortalSession(userId: string) {
|
|
38
|
+
const user = await this.userRepository.findById(userId);
|
|
39
|
+
if (!user?.stripeCustomerId) throw new NotFoundException('No Stripe customer found for this user');
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
return this.stripeProvider.createPortalSession(
|
|
42
|
+
user.stripeCustomerId,
|
|
43
|
+
`${this.configService.get('FRONTEND_URL')}/dashboard`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
async handleWebhook(payload: Buffer, signature: string) {
|
|
48
|
+
let event: Stripe.Event;
|
|
49
|
+
try {
|
|
50
|
+
event = this.stripeProvider.constructEvent(payload, signature);
|
|
51
|
+
} catch (err: any) {
|
|
52
|
+
throw new Error(`Webhook signature verification failed: ${err.message}`);
|
|
53
|
+
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
55
|
+
switch (event.type) {
|
|
56
|
+
case 'checkout.session.completed': {
|
|
57
|
+
const session = event.data.object as Stripe.Checkout.Session;
|
|
58
|
+
const userId = session.client_reference_id;
|
|
59
|
+
if (userId && session.customer) {
|
|
60
|
+
const user = await this.userRepository.findById(userId);
|
|
61
|
+
if (user) {
|
|
62
|
+
user.stripeCustomerId = session.customer as string;
|
|
63
|
+
await this.userRepository.save(user);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
console.log('Checkout completed for user:', userId);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'customer.subscription.updated': {
|
|
70
|
+
const sub = event.data.object as Stripe.Subscription;
|
|
71
|
+
console.log('Subscription updated:', sub.id, '| Status:', sub.status);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case 'customer.subscription.deleted': {
|
|
75
|
+
const sub = event.data.object as Stripe.Subscription;
|
|
76
|
+
console.log('Subscription deleted:', sub.id);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'invoice.payment_failed': {
|
|
80
|
+
const invoice = event.data.object as Stripe.Invoice;
|
|
81
|
+
console.log('Payment failed for invoice:', invoice.id);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
default:
|
|
85
|
+
console.log('Unhandled Stripe event:', event.type);
|
|
86
|
+
}
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
}
|
|
88
|
+
return { received: true };
|
|
90
89
|
}
|
|
90
|
+
}
|
|
@@ -4,9 +4,9 @@ export class User {
|
|
|
4
4
|
public readonly email: string,
|
|
5
5
|
public readonly name: string,
|
|
6
6
|
public readonly password: string,
|
|
7
|
-
public
|
|
7
|
+
public stripeCustomerId?: string,
|
|
8
8
|
public readonly createdAt: Date = new Date(),
|
|
9
9
|
) {
|
|
10
10
|
if (!email.includes('@')) throw new Error('Invalid email');
|
|
11
11
|
}
|
|
12
|
-
}
|
|
12
|
+
}
|
|
@@ -5,28 +5,28 @@ import { PrismaService } from '../prisma.service';
|
|
|
5
5
|
|
|
6
6
|
@Injectable()
|
|
7
7
|
export class PrismaUserRepository implements IUserRepository {
|
|
8
|
-
|
|
8
|
+
constructor(private prisma: PrismaService) {}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
async findByEmail(email: string): Promise<User | null> {
|
|
11
|
+
const user = await this.prisma.user.findUnique({ where: { email } });
|
|
12
|
+
if (!user) return null;
|
|
13
|
+
return new User(user.id, user.name, user.email, user.password);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
async save(user: User): Promise<User> {
|
|
17
17
|
const savedUser = await this.prisma.user.upsert({
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
where: { email: user.email },
|
|
19
|
+
update: {
|
|
20
|
+
name: user.name,
|
|
21
|
+
password: user.password,
|
|
22
|
+
},
|
|
23
|
+
create: {
|
|
24
|
+
id: user.id,
|
|
25
|
+
name: user.name,
|
|
26
|
+
email: user.email,
|
|
27
|
+
password: user.password,
|
|
28
|
+
},
|
|
29
29
|
});
|
|
30
30
|
return new User(savedUser.id, savedUser.name, savedUser.email, savedUser.password);
|
|
31
|
-
|
|
32
|
-
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -3,10 +3,7 @@ import { AppModule } from './app.module';
|
|
|
3
3
|
import { ValidationPipe } from '@nestjs/common';
|
|
4
4
|
|
|
5
5
|
async function bootstrap() {
|
|
6
|
-
const app = await NestFactory.create(AppModule
|
|
7
|
-
// rawBody is required so the Stripe webhook can verify the signature
|
|
8
|
-
rawBody: true,
|
|
9
|
-
});
|
|
6
|
+
const app = await NestFactory.create(AppModule);
|
|
10
7
|
|
|
11
8
|
app.enableCors();
|
|
12
9
|
app.setGlobalPrefix('api');
|
|
@@ -8,16 +8,16 @@ import { PrismaUserRepository } from './infrastructure/database/prisma.user.repo
|
|
|
8
8
|
import { PrismaService } from './infrastructure/database/prisma.service';
|
|
9
9
|
|
|
10
10
|
@Module({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
imports: [ConfigModule],
|
|
12
|
+
controllers: [PaymentController],
|
|
13
|
+
providers: [
|
|
14
|
+
PaymentService,
|
|
15
|
+
StripeProvider,
|
|
16
|
+
PrismaService,
|
|
17
|
+
{
|
|
18
|
+
provide: UserRepository,
|
|
19
|
+
useClass: PrismaUserRepository,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
22
|
})
|
|
23
|
-
export class PaymentModule {}
|
|
23
|
+
export class PaymentModule {}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Build outputs
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
|
|
10
|
+
# Environment variables
|
|
11
|
+
.env
|
|
12
|
+
.env.local
|
|
13
|
+
.env.development.local
|
|
14
|
+
.env.test.local
|
|
15
|
+
.env.production.local
|
|
16
|
+
!.env.example
|
|
17
|
+
|
|
18
|
+
# Logs
|
|
19
|
+
logs/
|
|
20
|
+
*.log
|
|
21
|
+
npm-debug.log*
|
|
22
|
+
yarn-debug.log*
|
|
23
|
+
yarn-error.log*
|
|
24
|
+
pnpm-debug.log*
|
|
25
|
+
lerna-debug.log*
|
|
26
|
+
|
|
27
|
+
# Coverage
|
|
28
|
+
coverage/
|
|
29
|
+
.nyc_output
|
|
30
|
+
|
|
31
|
+
# TypeScript
|
|
32
|
+
*.tsbuildinfo
|
|
33
|
+
|
|
34
|
+
# OS
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
|
37
|
+
|
|
38
|
+
# Editor
|
|
39
|
+
.vscode/
|
|
40
|
+
.idea/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
@@ -9,7 +9,7 @@ WORKDIR /app
|
|
|
9
9
|
COPY package*.json ./
|
|
10
10
|
|
|
11
11
|
# Install dependencies
|
|
12
|
-
RUN npm ci
|
|
12
|
+
RUN npm ci
|
|
13
13
|
|
|
14
14
|
# Copy source code
|
|
15
15
|
COPY . .
|
|
@@ -26,6 +26,9 @@ WORKDIR /app
|
|
|
26
26
|
RUN addgroup -g 1001 -S nodejs && \
|
|
27
27
|
adduser -S nodejs -u 1001
|
|
28
28
|
|
|
29
|
+
# Add openssl
|
|
30
|
+
RUN apk add --no-cache openssl
|
|
31
|
+
|
|
29
32
|
# Copy built application
|
|
30
33
|
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
|
31
34
|
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
@@ -39,7 +42,7 @@ EXPOSE 3000
|
|
|
39
42
|
|
|
40
43
|
# Health check
|
|
41
44
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
42
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
|
|
45
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
|
|
43
46
|
|
|
44
47
|
# Start application
|
|
45
|
-
CMD
|
|
48
|
+
CMD node dist/main.js
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
version: '3.8'
|
|
2
2
|
|
|
3
3
|
services:
|
|
4
|
-
app:
|
|
5
|
-
build: .
|
|
6
|
-
container_name: {{kebabCase projectName}}-app
|
|
7
|
-
ports:
|
|
8
|
-
- "3000:3000"
|
|
9
|
-
environment:
|
|
10
|
-
- DATABASE_URL=postgresql://postgres:postgres@db:5432/{{snakeCase projectName}}
|
|
11
|
-
depends_on:
|
|
12
|
-
- db
|
|
13
|
-
|
|
14
4
|
db:
|
|
15
5
|
image: postgres:15-alpine
|
|
16
6
|
container_name: {{kebabCase projectName}}-db
|
|
@@ -19,7 +9,7 @@ services:
|
|
|
19
9
|
POSTGRES_PASSWORD: postgres
|
|
20
10
|
POSTGRES_DB: {{snakeCase projectName}}
|
|
21
11
|
ports:
|
|
22
|
-
- "
|
|
12
|
+
- "5434:5432"
|
|
23
13
|
volumes:
|
|
24
14
|
- postgres_data:/var/lib/postgresql/data
|
|
25
15
|
restart: unless-stopped
|
|
@@ -1,43 +1,53 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
2
|
+
"name": "{{kebabCase projectName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Generated by Kybernus CLI (Pro)",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "nest start --watch",
|
|
7
|
+
"build": "nest build",
|
|
8
|
+
"start": "node dist/main.js",
|
|
9
|
+
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"migrate:dev": "prisma migrate dev",
|
|
12
|
+
"migrate:deploy": "prisma migrate deploy",
|
|
13
|
+
"generate": "prisma generate"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@nestjs/common": "^10.3.0",
|
|
17
|
+
"@nestjs/core": "^10.3.0",
|
|
18
|
+
"@nestjs/config": "^3.1.1",
|
|
19
|
+
"@nestjs/jwt": "^10.2.0",
|
|
20
|
+
"@nestjs/passport": "^10.0.3",
|
|
21
|
+
"@nestjs/platform-express": "^10.3.0",
|
|
22
|
+
"@prisma/client": "^5.10.2",
|
|
23
|
+
"bcryptjs": "^2.4.3",
|
|
24
|
+
"class-transformer": "^0.5.1",
|
|
25
|
+
"class-validator": "^0.14.1",
|
|
26
|
+
"passport": "^0.7.0",
|
|
27
|
+
"passport-jwt": "^4.0.1",
|
|
28
|
+
"reflect-metadata": "^0.2.1",
|
|
29
|
+
"rxjs": "^7.8.1",
|
|
30
|
+
"stripe": "^14.14.0",
|
|
31
|
+
"uuid": "^9.0.1"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@nestjs/cli": "^10.3.0",
|
|
35
|
+
"@types/bcryptjs": "^2.4.6",
|
|
36
|
+
"@types/node": "^20.11.0",
|
|
37
|
+
"@types/passport-jwt": "^4.0.0",
|
|
38
|
+
"@types/uuid": "^9.0.7",
|
|
39
|
+
"prisma": "^5.10.2",
|
|
40
|
+
"typescript": "^5.3.3",
|
|
41
|
+
"eslint": "^9.16.0"
|
|
42
|
+
},
|
|
43
|
+
"overrides": {
|
|
44
|
+
"rimraf": "^6.1.2",
|
|
45
|
+
"glob": "^11.0.0",
|
|
46
|
+
"inflight": "^1.0.6",
|
|
47
|
+
"@humanwhocodes/config-array": "^0.13.0",
|
|
48
|
+
"@humanwhocodes/object-schema": "^2.0.3",
|
|
49
|
+
"eslint": "^9.16.0",
|
|
50
|
+
"cookie": "^0.7.2",
|
|
51
|
+
"minimatch": "^9.0.8"
|
|
43
52
|
}
|
|
53
|
+
}
|
|
@@ -3,6 +3,7 @@ import { ConfigModule } from '@nestjs/config';
|
|
|
3
3
|
import { AuthModule } from './auth.module';
|
|
4
4
|
import { PaymentModule } from './payment.module';
|
|
5
5
|
import { PrismaService } from './adapters/outbound/persistence/prisma.service';
|
|
6
|
+
import { HealthController } from './adapters/inbound/health.controller';
|
|
6
7
|
|
|
7
8
|
@Module({
|
|
8
9
|
imports: [
|
|
@@ -12,7 +13,7 @@ import { PrismaService } from './adapters/outbound/persistence/prisma.service';
|
|
|
12
13
|
AuthModule,
|
|
13
14
|
PaymentModule,
|
|
14
15
|
],
|
|
15
|
-
controllers: [],
|
|
16
|
+
controllers: [HealthController],
|
|
16
17
|
providers: [PrismaService],
|
|
17
18
|
exports: [PrismaService],
|
|
18
19
|
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export class User {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
constructor(
|
|
3
|
+
public readonly id: string,
|
|
4
|
+
public readonly email: string,
|
|
5
|
+
public readonly name: string,
|
|
6
|
+
public readonly password: string,
|
|
7
|
+
) {}
|
|
8
8
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { User } from '../domain/user.entity';
|
|
2
2
|
|
|
3
3
|
export interface IUserRepositoryPort {
|
|
4
|
-
|
|
5
|
-
}
|
|
4
|
+
save(user: User): Promise<User>;
|
|
5
|
+
}
|
|
6
6
|
|
|
7
|
-
export interface IAuthPort {
|
|
7
|
+
export interface IAuthPort {
|
|
8
8
|
register(email: string, name: string, password: string): Promise<User>;
|
|
9
|
-
}
|
|
9
|
+
}
|
|
@@ -3,10 +3,7 @@ import { AppModule } from './app.module';
|
|
|
3
3
|
import { ValidationPipe } from '@nestjs/common';
|
|
4
4
|
|
|
5
5
|
async function bootstrap() {
|
|
6
|
-
const app = await NestFactory.create(AppModule
|
|
7
|
-
// rawBody is required so the Stripe webhook can verify the signature
|
|
8
|
-
rawBody: true,
|
|
9
|
-
});
|
|
6
|
+
const app = await NestFactory.create(AppModule);
|
|
10
7
|
|
|
11
8
|
app.enableCors();
|
|
12
9
|
app.setGlobalPrefix('api');
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Build outputs
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
|
|
10
|
+
# Environment variables
|
|
11
|
+
.env
|
|
12
|
+
.env.local
|
|
13
|
+
.env.development.local
|
|
14
|
+
.env.test.local
|
|
15
|
+
.env.production.local
|
|
16
|
+
!.env.example
|
|
17
|
+
|
|
18
|
+
# Logs
|
|
19
|
+
logs/
|
|
20
|
+
*.log
|
|
21
|
+
npm-debug.log*
|
|
22
|
+
yarn-debug.log*
|
|
23
|
+
yarn-error.log*
|
|
24
|
+
pnpm-debug.log*
|
|
25
|
+
lerna-debug.log*
|
|
26
|
+
|
|
27
|
+
# Coverage
|
|
28
|
+
coverage/
|
|
29
|
+
.nyc_output
|
|
30
|
+
|
|
31
|
+
# TypeScript
|
|
32
|
+
*.tsbuildinfo
|
|
33
|
+
|
|
34
|
+
# OS
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
|
37
|
+
|
|
38
|
+
# Editor
|
|
39
|
+
.vscode/
|
|
40
|
+
.idea/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
@@ -9,7 +9,7 @@ WORKDIR /app
|
|
|
9
9
|
COPY package*.json ./
|
|
10
10
|
|
|
11
11
|
# Install dependencies
|
|
12
|
-
RUN npm ci
|
|
12
|
+
RUN npm ci
|
|
13
13
|
|
|
14
14
|
# Copy source code
|
|
15
15
|
COPY . .
|
|
@@ -26,6 +26,9 @@ WORKDIR /app
|
|
|
26
26
|
RUN addgroup -g 1001 -S nodejs && \
|
|
27
27
|
adduser -S nodejs -u 1001
|
|
28
28
|
|
|
29
|
+
# Add openssl
|
|
30
|
+
RUN apk add --no-cache openssl
|
|
31
|
+
|
|
29
32
|
# Copy built application
|
|
30
33
|
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
|
31
34
|
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
@@ -39,7 +42,7 @@ EXPOSE 3000
|
|
|
39
42
|
|
|
40
43
|
# Health check
|
|
41
44
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
42
|
-
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
|
|
45
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
|
|
43
46
|
|
|
44
47
|
# Start application
|
|
45
|
-
CMD
|
|
48
|
+
CMD node dist/main.js
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
version: '3.8'
|
|
2
2
|
|
|
3
3
|
services:
|
|
4
|
-
app:
|
|
5
|
-
build: .
|
|
6
|
-
container_name: {{kebabCase projectName}}-app
|
|
7
|
-
ports:
|
|
8
|
-
- "3000:3000"
|
|
9
|
-
environment:
|
|
10
|
-
- DATABASE_URL=postgresql://postgres:postgres@db:5432/{{snakeCase projectName}}
|
|
11
|
-
depends_on:
|
|
12
|
-
- db
|
|
13
|
-
|
|
14
4
|
db:
|
|
15
5
|
image: postgres:15-alpine
|
|
16
6
|
container_name: {{kebabCase projectName}}-db
|
|
@@ -19,7 +9,7 @@ services:
|
|
|
19
9
|
POSTGRES_PASSWORD: postgres
|
|
20
10
|
POSTGRES_DB: {{snakeCase projectName}}
|
|
21
11
|
ports:
|
|
22
|
-
- "
|
|
12
|
+
- "5434:5432"
|
|
23
13
|
volumes:
|
|
24
14
|
- postgres_data:/var/lib/postgresql/data
|
|
25
15
|
restart: unless-stopped
|