kybernus 2.1.0 → 2.2.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/node_modules/{@isaacs/balanced-match → balanced-match}/README.md +7 -10
- package/node_modules/{@isaacs/balanced-match → balanced-match}/package.json +5 -16
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/README.md +2 -5
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.js +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.js.map +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.js +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.js.map +1 -1
- package/node_modules/{@isaacs/brace-expansion → brace-expansion}/package.json +9 -5
- package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/glob.js +2 -1
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
- package/node_modules/glob/dist/commonjs/index.min.js +4 -0
- package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/commonjs/pattern.js +4 -0
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
- package/node_modules/glob/dist/esm/glob.d.ts +8 -0
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/glob.js +2 -1
- package/node_modules/glob/dist/esm/glob.js.map +1 -1
- package/node_modules/glob/dist/esm/index.min.js +4 -0
- package/node_modules/glob/dist/esm/index.min.js.map +7 -0
- package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
- package/node_modules/glob/dist/esm/pattern.js +4 -0
- package/node_modules/glob/dist/esm/pattern.js.map +1 -1
- package/node_modules/glob/package.json +30 -10
- package/node_modules/lru-cache/package.json +7 -7
- package/node_modules/minimatch/README.md +3 -1
- package/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/ast.js +37 -27
- package/node_modules/minimatch/dist/commonjs/ast.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js +2 -4
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/escape.js +4 -4
- package/node_modules/minimatch/dist/commonjs/escape.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/index.d.ts +50 -0
- package/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/commonjs/index.js +37 -31
- package/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
- package/node_modules/minimatch/dist/commonjs/unescape.js +4 -4
- package/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -1
- package/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/ast.js +37 -27
- package/node_modules/minimatch/dist/esm/ast.js.map +1 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/brace-expressions.js +2 -4
- package/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
- package/node_modules/minimatch/dist/esm/escape.js +4 -4
- package/node_modules/minimatch/dist/esm/escape.js.map +1 -1
- package/node_modules/minimatch/dist/esm/index.d.ts +50 -0
- package/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minimatch/dist/esm/index.js +37 -31
- package/node_modules/minimatch/dist/esm/index.js.map +1 -1
- package/node_modules/minimatch/dist/esm/unescape.js +4 -4
- package/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
- package/node_modules/minimatch/package.json +3 -3
- package/node_modules/minipass/LICENSE.md +55 -0
- package/node_modules/minipass/dist/commonjs/index.d.ts +12 -16
- package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/commonjs/index.js +13 -3
- package/node_modules/minipass/dist/commonjs/index.js.map +1 -1
- package/node_modules/minipass/dist/esm/index.d.ts +12 -16
- package/node_modules/minipass/dist/esm/index.d.ts.map +1 -1
- package/node_modules/minipass/dist/esm/index.js +3 -1
- package/node_modules/minipass/dist/esm/index.js.map +1 -1
- package/node_modules/minipass/package.json +9 -14
- package/node_modules/rimraf/README.md +29 -0
- package/node_modules/rimraf/dist/commonjs/fs.d.ts +9 -8
- package/node_modules/rimraf/dist/commonjs/fs.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/index.js +9 -3
- package/node_modules/rimraf/dist/commonjs/index.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.js +2 -1
- package/node_modules/rimraf/dist/commonjs/opt-arg.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.js +2 -1
- package/node_modules/rimraf/dist/commonjs/path-arg.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts +2 -2
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js +1 -2
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts.map +1 -1
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.js.map +1 -1
- package/node_modules/rimraf/dist/esm/bin.mjs.map +1 -1
- package/node_modules/rimraf/dist/esm/fs.d.ts +9 -8
- package/node_modules/rimraf/dist/esm/fs.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/index.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/index.js +10 -4
- package/node_modules/rimraf/dist/esm/index.js.map +1 -1
- package/node_modules/rimraf/dist/esm/opt-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/opt-arg.js +2 -1
- package/node_modules/rimraf/dist/esm/opt-arg.js.map +1 -1
- package/node_modules/rimraf/dist/esm/path-arg.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/path-arg.js +2 -1
- package/node_modules/rimraf/dist/esm/path-arg.js.map +1 -1
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts +2 -2
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-posix.js +1 -2
- package/node_modules/rimraf/dist/esm/rimraf-posix.js.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts.map +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.js +1 -1
- package/node_modules/rimraf/dist/esm/rimraf-windows.js.map +1 -1
- package/node_modules/rimraf/package.json +4 -19
- package/package.json +2 -2
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/AuthController.java.hbs +38 -42
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/ItemController.java.hbs +42 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/PaymentsController.java.hbs +65 -22
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/model/Item.java.hbs +38 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/model/User.java.hbs +41 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/repository/ItemRepository.java.hbs +9 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/repository/UserRepository.java.hbs +13 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/service/AuthService.java.hbs +62 -0
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/service/StripeService.java.hbs +18 -18
- package/templates/java-spring/mvc/src/main/java/{{packagePath}}/{{projectNamePascalCase}}Application.java.hbs +2 -0
- package/templates/nestjs/mvc/package.json.hbs +6 -2
- package/templates/nestjs/mvc/prisma/schema.prisma.hbs +31 -0
- package/templates/nestjs/mvc/src/app.module.ts.hbs +3 -1
- package/templates/nestjs/mvc/src/auth/auth.service.ts.hbs +34 -31
- package/templates/nestjs/mvc/src/payments/payments.service.ts.hbs +26 -6
- package/templates/nestjs/mvc/src/prisma/prisma.module.ts.hbs +9 -0
- package/templates/nestjs/mvc/src/prisma/prisma.service.ts.hbs +15 -0
- package/templates/nestjs/mvc/src/services/items.service.ts.hbs +33 -20
- package/templates/nextjs/mvc/package.json.hbs +1 -0
- package/templates/nextjs/mvc/prisma/schema.prisma.hbs +60 -6
- package/templates/nextjs/mvc/src/app/api/webhook/route.ts.hbs +23 -18
- package/templates/nodejs-express/mvc/package.json.hbs +8 -4
- package/templates/nodejs-express/mvc/prisma/schema.prisma.hbs +31 -0
- package/templates/nodejs-express/mvc/src/config/database.ts.hbs +2 -9
- package/templates/nodejs-express/mvc/src/controllers/auth.controller.ts.hbs +40 -58
- package/templates/nodejs-express/mvc/src/controllers/items.controller.ts.hbs +29 -0
- package/templates/nodejs-express/mvc/src/models/README.md.hbs +10 -0
- package/templates/nodejs-express/mvc/src/prisma/client.ts.hbs +3 -0
- package/templates/nodejs-express/mvc/src/services/auth.service.ts.hbs +71 -0
- package/templates/nodejs-express/mvc/src/services/stripe.service.ts.hbs +35 -25
- package/templates/python-fastapi/mvc/app/controllers/auth.py.hbs +25 -16
- package/templates/python-fastapi/mvc/app/controllers/items.py.hbs +9 -7
- package/templates/python-fastapi/mvc/app/controllers/payments.py.hbs +42 -15
- package/templates/python-fastapi/mvc/app/database.py.hbs +17 -0
- package/templates/python-fastapi/mvc/app/main.py.hbs +4 -0
- package/templates/python-fastapi/mvc/app/models/item.py.hbs +11 -8
- package/templates/python-fastapi/mvc/app/models/user.py.hbs +15 -0
- package/templates/python-fastapi/mvc/app/repositories/item_repository.py.hbs +15 -0
- package/templates/python-fastapi/mvc/app/repositories/user_repository.py.hbs +15 -0
- package/templates/python-fastapi/mvc/app/services/item_service.py.hbs +17 -19
- package/node_modules/minipass/LICENSE +0 -15
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/LICENSE.md +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.js +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/index.js.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.js +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/index.js.map +0 -0
- /package/node_modules/{@isaacs/balanced-match → balanced-match}/dist/esm/package.json +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/LICENSE +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.d.ts +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/commonjs/package.json +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.d.ts +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/index.d.ts.map +0 -0
- /package/node_modules/{@isaacs/brace-expansion → brace-expansion}/dist/esm/package.json +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package {{packageName}}.model;
|
|
2
|
+
|
|
3
|
+
import jakarta.persistence.*;
|
|
4
|
+
import lombok.*;
|
|
5
|
+
import org.springframework.data.annotation.CreatedDate;
|
|
6
|
+
import org.springframework.data.annotation.LastModifiedDate;
|
|
7
|
+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|
8
|
+
|
|
9
|
+
import java.time.LocalDateTime;
|
|
10
|
+
|
|
11
|
+
@Entity
|
|
12
|
+
@Table(name = "items")
|
|
13
|
+
@Data
|
|
14
|
+
@NoArgsConstructor
|
|
15
|
+
@AllArgsConstructor
|
|
16
|
+
@Builder
|
|
17
|
+
@EntityListeners(AuditingEntityListener.class)
|
|
18
|
+
public class Item {
|
|
19
|
+
|
|
20
|
+
@Id
|
|
21
|
+
@GeneratedValue(strategy = GenerationType.UUID)
|
|
22
|
+
private String id;
|
|
23
|
+
|
|
24
|
+
@Column(nullable = false)
|
|
25
|
+
private String name;
|
|
26
|
+
|
|
27
|
+
private String description;
|
|
28
|
+
|
|
29
|
+
private Double price;
|
|
30
|
+
|
|
31
|
+
@CreatedDate
|
|
32
|
+
@Column(name = "created_at", nullable = false, updatable = false)
|
|
33
|
+
private LocalDateTime createdAt;
|
|
34
|
+
|
|
35
|
+
@LastModifiedDate
|
|
36
|
+
@Column(name = "updated_at", nullable = false)
|
|
37
|
+
private LocalDateTime updatedAt;
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package {{packageName}}.model;
|
|
2
|
+
|
|
3
|
+
import jakarta.persistence.*;
|
|
4
|
+
import lombok.*;
|
|
5
|
+
import org.springframework.data.annotation.CreatedDate;
|
|
6
|
+
import org.springframework.data.annotation.LastModifiedDate;
|
|
7
|
+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|
8
|
+
|
|
9
|
+
import java.time.LocalDateTime;
|
|
10
|
+
|
|
11
|
+
@Entity
|
|
12
|
+
@Table(name = "users")
|
|
13
|
+
@Data
|
|
14
|
+
@NoArgsConstructor
|
|
15
|
+
@AllArgsConstructor
|
|
16
|
+
@Builder
|
|
17
|
+
@EntityListeners(AuditingEntityListener.class)
|
|
18
|
+
public class User {
|
|
19
|
+
|
|
20
|
+
@Id
|
|
21
|
+
@GeneratedValue(strategy = GenerationType.UUID)
|
|
22
|
+
private String id;
|
|
23
|
+
|
|
24
|
+
@Column(unique = true, nullable = false)
|
|
25
|
+
private String email;
|
|
26
|
+
|
|
27
|
+
private String name;
|
|
28
|
+
|
|
29
|
+
private String password;
|
|
30
|
+
|
|
31
|
+
@Column(name = "stripe_customer_id")
|
|
32
|
+
private String stripeCustomerId;
|
|
33
|
+
|
|
34
|
+
@CreatedDate
|
|
35
|
+
@Column(name = "created_at", nullable = false, updatable = false)
|
|
36
|
+
private LocalDateTime createdAt;
|
|
37
|
+
|
|
38
|
+
@LastModifiedDate
|
|
39
|
+
@Column(name = "updated_at", nullable = false)
|
|
40
|
+
private LocalDateTime updatedAt;
|
|
41
|
+
}
|
package/templates/java-spring/mvc/src/main/java/{{packagePath}}/repository/ItemRepository.java.hbs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package {{packageName}}.repository;
|
|
2
|
+
|
|
3
|
+
import {{packageName}}.model.Item;
|
|
4
|
+
import org.springframework.data.jpa.repository.JpaRepository;
|
|
5
|
+
import org.springframework.stereotype.Repository;
|
|
6
|
+
|
|
7
|
+
@Repository
|
|
8
|
+
public interface ItemRepository extends JpaRepository<Item, String> {
|
|
9
|
+
}
|
package/templates/java-spring/mvc/src/main/java/{{packagePath}}/repository/UserRepository.java.hbs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package {{packageName}}.repository;
|
|
2
|
+
|
|
3
|
+
import {{packageName}}.model.User;
|
|
4
|
+
import org.springframework.data.jpa.repository.JpaRepository;
|
|
5
|
+
import org.springframework.stereotype.Repository;
|
|
6
|
+
|
|
7
|
+
import java.util.Optional;
|
|
8
|
+
|
|
9
|
+
@Repository
|
|
10
|
+
public interface UserRepository extends JpaRepository<User, String> {
|
|
11
|
+
Optional<User> findByEmail(String email);
|
|
12
|
+
Optional<User> findByStripeCustomerId(String stripeCustomerId);
|
|
13
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
package {{packageName}}.service;
|
|
2
|
+
|
|
3
|
+
import {{packageName}}.dto.AuthRequest;
|
|
4
|
+
import {{packageName}}.dto.AuthResponse;
|
|
5
|
+
import {{packageName}}.model.User;
|
|
6
|
+
import {{packageName}}.repository.UserRepository;
|
|
7
|
+
import {{packageName}}.security.JwtTokenProvider;
|
|
8
|
+
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
9
|
+
import org.springframework.stereotype.Service;
|
|
10
|
+
|
|
11
|
+
import java.util.Optional;
|
|
12
|
+
|
|
13
|
+
@Service
|
|
14
|
+
public class AuthService {
|
|
15
|
+
|
|
16
|
+
private final UserRepository userRepository;
|
|
17
|
+
private final PasswordEncoder passwordEncoder;
|
|
18
|
+
private final JwtTokenProvider tokenProvider;
|
|
19
|
+
|
|
20
|
+
public AuthService(UserRepository userRepository, PasswordEncoder passwordEncoder, JwtTokenProvider tokenProvider) {
|
|
21
|
+
this.userRepository = userRepository;
|
|
22
|
+
this.passwordEncoder = passwordEncoder;
|
|
23
|
+
this.tokenProvider = tokenProvider;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public AuthResponse register(AuthRequest request) {
|
|
27
|
+
if (userRepository.findByEmail(request.email()).isPresent()) {
|
|
28
|
+
throw new IllegalArgumentException("User already exists");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
String hashedPassword = passwordEncoder.encode(request.password());
|
|
32
|
+
|
|
33
|
+
User user = User.builder()
|
|
34
|
+
.email(request.email())
|
|
35
|
+
.password(hashedPassword)
|
|
36
|
+
.build();
|
|
37
|
+
|
|
38
|
+
user = userRepository.save(user);
|
|
39
|
+
|
|
40
|
+
String token = tokenProvider.generateToken(user.getId(), user.getEmail());
|
|
41
|
+
|
|
42
|
+
return new AuthResponse(token, user.getId(), user.getEmail());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public AuthResponse login(AuthRequest request) {
|
|
46
|
+
Optional<User> userOptional = userRepository.findByEmail(request.email());
|
|
47
|
+
|
|
48
|
+
if (userOptional.isEmpty() || !passwordEncoder.matches(request.password(), userOptional.get().getPassword())) {
|
|
49
|
+
throw new IllegalArgumentException("Invalid credentials");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
User user = userOptional.get();
|
|
53
|
+
String token = tokenProvider.generateToken(user.getId(), user.getEmail());
|
|
54
|
+
|
|
55
|
+
return new AuthResponse(token, user.getId(), user.getEmail());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public User getMe(String userId) {
|
|
59
|
+
return userRepository.findById(userId)
|
|
60
|
+
.orElseThrow(() -> new IllegalArgumentException("User not found"));
|
|
61
|
+
}
|
|
62
|
+
}
|
package/templates/java-spring/mvc/src/main/java/{{packagePath}}/service/StripeService.java.hbs
CHANGED
|
@@ -29,18 +29,18 @@ public class StripeService {
|
|
|
29
29
|
|
|
30
30
|
public Session createCheckoutSession(String customerId) throws StripeException {
|
|
31
31
|
SessionCreateParams.Builder paramsBuilder = SessionCreateParams.builder()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
.setMode(SessionCreateParams.Mode.SUBSCRIPTION)
|
|
33
|
+
.setSuccessUrl(frontendUrl + "/success?session_id={CHECKOUT_SESSION_ID}")
|
|
34
|
+
.setCancelUrl(frontendUrl + "/cancel")
|
|
35
|
+
.addLineItem(
|
|
36
|
+
SessionCreateParams.LineItem.builder()
|
|
37
|
+
.setPrice(priceId)
|
|
38
|
+
.setQuantity(1L)
|
|
39
|
+
.build()
|
|
40
|
+
);
|
|
41
41
|
|
|
42
42
|
if (customerId != null && !customerId.isEmpty()) {
|
|
43
|
-
|
|
43
|
+
paramsBuilder.setCustomer(customerId);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return Session.create(paramsBuilder.build());
|
|
@@ -48,20 +48,20 @@ public class StripeService {
|
|
|
48
48
|
|
|
49
49
|
public com.stripe.model.billingportal.Session createPortalSession(String customerId) throws StripeException {
|
|
50
50
|
com.stripe.param.billingportal.SessionCreateParams params =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
com.stripe.param.billingportal.SessionCreateParams.builder()
|
|
52
|
+
.setCustomer(customerId)
|
|
53
|
+
.setReturnUrl(frontendUrl + "/dashboard")
|
|
54
|
+
.build();
|
|
55
55
|
|
|
56
56
|
return com.stripe.model.billingportal.Session.create(params);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
public Customer createCustomer(String email, String name) throws StripeException {
|
|
60
60
|
CustomerCreateParams params = CustomerCreateParams.builder()
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
.setEmail(email)
|
|
62
|
+
.setName(name)
|
|
63
|
+
.build();
|
|
64
64
|
|
|
65
65
|
return Customer.create(params);
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
|
@@ -2,8 +2,10 @@ package {{packageName}};
|
|
|
2
2
|
|
|
3
3
|
import org.springframework.boot.SpringApplication;
|
|
4
4
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
5
|
+
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
|
5
6
|
|
|
6
7
|
@SpringBootApplication
|
|
8
|
+
@EnableJpaAuditing
|
|
7
9
|
public class {{projectNamePascalCase}}Application {
|
|
8
10
|
|
|
9
11
|
public static void main(String[] args) {
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
"build": "nest build",
|
|
8
8
|
"start": "node dist/main.js",
|
|
9
9
|
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
10
|
-
"test": "jest"
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"db:generate": "prisma generate",
|
|
12
|
+
"db:push": "prisma db push"
|
|
11
13
|
},
|
|
12
14
|
"dependencies": {
|
|
13
15
|
"@nestjs/common": "^10.3.0",
|
|
@@ -16,6 +18,7 @@
|
|
|
16
18
|
"@nestjs/jwt": "^10.2.0",
|
|
17
19
|
"@nestjs/passport": "^10.0.3",
|
|
18
20
|
"@nestjs/platform-express": "^10.3.0",
|
|
21
|
+
"@prisma/client": "^5.10.2",
|
|
19
22
|
"bcryptjs": "^2.4.3",
|
|
20
23
|
"class-transformer": "^0.5.1",
|
|
21
24
|
"class-validator": "^0.14.1",
|
|
@@ -32,6 +35,7 @@
|
|
|
32
35
|
"@types/node": "^20.11.0",
|
|
33
36
|
"@types/passport-jwt": "^4.0.0",
|
|
34
37
|
"@types/uuid": "^9.0.7",
|
|
38
|
+
"prisma": "^5.10.2",
|
|
35
39
|
"typescript": "^5.3.3"
|
|
36
40
|
}
|
|
37
|
-
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
datasource db {
|
|
6
|
+
provider = "postgresql"
|
|
7
|
+
url = env("DATABASE_URL")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
model User {
|
|
11
|
+
id String @id @default(uuid())
|
|
12
|
+
email String @unique
|
|
13
|
+
name String?
|
|
14
|
+
password String
|
|
15
|
+
stripeCustomerId String? @map("stripe_customer_id")
|
|
16
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
17
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
18
|
+
|
|
19
|
+
@@map("users")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
model Item {
|
|
23
|
+
id String @id @default(uuid())
|
|
24
|
+
name String
|
|
25
|
+
description String?
|
|
26
|
+
price Float?
|
|
27
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
28
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
29
|
+
|
|
30
|
+
@@map("items")
|
|
31
|
+
}
|
|
@@ -4,14 +4,16 @@ import { ItemsModule } from './modules/items.module';
|
|
|
4
4
|
import { AuthModule } from './auth/auth.module';
|
|
5
5
|
import { PaymentsModule } from './payments/payments.module';
|
|
6
6
|
import { HealthController } from './controllers/health.controller';
|
|
7
|
+
import { PrismaModule } from './prisma/prisma.module';
|
|
7
8
|
|
|
8
9
|
@Module({
|
|
9
10
|
imports: [
|
|
10
11
|
ConfigModule.forRoot({ isGlobal: true }),
|
|
12
|
+
PrismaModule,
|
|
11
13
|
AuthModule,
|
|
12
14
|
PaymentsModule,
|
|
13
15
|
ItemsModule,
|
|
14
16
|
],
|
|
15
17
|
controllers: [HealthController],
|
|
16
18
|
})
|
|
17
|
-
export class AppModule {}
|
|
19
|
+
export class AppModule {}
|
|
@@ -1,43 +1,46 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
1
|
+
import { Injectable, UnauthorizedException, BadRequestException } from '@nestjs/common';
|
|
2
2
|
import { JwtService } from '@nestjs/jwt';
|
|
3
3
|
import * as bcrypt from 'bcryptjs';
|
|
4
|
-
|
|
5
|
-
interface User {
|
|
6
|
-
id: string;
|
|
7
|
-
email: string;
|
|
8
|
-
name: string;
|
|
9
|
-
password: string;
|
|
10
|
-
}
|
|
4
|
+
import { PrismaService } from '../prisma/prisma.service';
|
|
11
5
|
|
|
12
6
|
@Injectable()
|
|
13
7
|
export class AuthService {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
constructor(
|
|
9
|
+
private jwtService: JwtService,
|
|
10
|
+
private prisma: PrismaService,
|
|
11
|
+
) {}
|
|
17
12
|
|
|
18
13
|
async register(email: string, name: string, password: string) {
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
const existingUser = await this.prisma.user.findUnique({
|
|
15
|
+
where: { email },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
if (existingUser) {
|
|
19
|
+
throw new BadRequestException('User already exists');
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
|
|
24
|
+
const user = await this.prisma.user.create({
|
|
25
|
+
data: {
|
|
26
|
+
email,
|
|
27
|
+
name,
|
|
28
|
+
password: hashedPassword,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
32
|
const token = this.jwtService.sign({ sub: user.id, email: user.email });
|
|
33
33
|
|
|
34
34
|
return { token, user: { id: user.id, email: user.email, name: user.name } };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
async login(email: string, password: string) {
|
|
38
|
-
const user = this.
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const user = await this.prisma.user.findUnique({
|
|
39
|
+
where: { email },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (users || !(await bcrypt.compare(password, user.password))) {
|
|
43
|
+
throw new UnauthorizedException('Invalid credentials');
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
const token = this.jwtService.sign({ sub: user.id, email: user.email });
|
|
@@ -45,11 +48,11 @@ export class AuthService {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
async validateUser(userId: string) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
51
|
+
const user = await this.prisma.user.findUnique({
|
|
52
|
+
where: { id: userId },
|
|
53
|
+
select: { id: true, email: true, name: true }
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return user;
|
|
54
57
|
}
|
|
55
|
-
}
|
|
58
|
+
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Injectable } from '@nestjs/common';
|
|
2
2
|
import { ConfigService } from '@nestjs/config';
|
|
3
3
|
import Stripe from 'stripe';
|
|
4
|
+
import { PrismaService } from '../prisma/prisma.service';
|
|
4
5
|
|
|
5
6
|
@Injectable()
|
|
6
7
|
export class PaymentsService {
|
|
7
8
|
private stripe: Stripe;
|
|
8
9
|
|
|
9
|
-
constructor(
|
|
10
|
+
constructor(
|
|
11
|
+
private configService: ConfigService,
|
|
12
|
+
private prisma: PrismaService,
|
|
13
|
+
) {
|
|
10
14
|
this.stripe = new Stripe(configService.get('STRIPE_SECRET_KEY', ''), {
|
|
11
15
|
apiVersion: '2024-12-18.acacia',
|
|
12
16
|
});
|
|
@@ -31,13 +35,29 @@ export class PaymentsService {
|
|
|
31
35
|
|
|
32
36
|
switch (event.type) {
|
|
33
37
|
case 'checkout.session.completed':
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
{
|
|
39
|
+
const session = event.data.object as Stripe.Checkout.Session;
|
|
40
|
+
console.log('Checkout completed:', session.id);
|
|
41
|
+
// Match the session back to the user via client_reference_id or customer email
|
|
42
|
+
// await this.prisma.user.update({...});
|
|
43
|
+
}
|
|
44
|
+
break;
|
|
36
45
|
case 'customer.subscription.updated':
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
{
|
|
47
|
+
const subscription = event.data.object as Stripe.Subscription;
|
|
48
|
+
console.log('Subscription updated:', subscription.id);
|
|
49
|
+
// Update user's subscription status in DB
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
case 'customer.subscription.deleted':
|
|
53
|
+
{
|
|
54
|
+
const subscription = event.data.object as Stripe.Subscription;
|
|
55
|
+
console.log('Subscription deleted:', subscription.id);
|
|
56
|
+
// Cancel user's subscription in DB
|
|
57
|
+
}
|
|
58
|
+
break;
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
return { received: true };
|
|
42
62
|
}
|
|
43
|
-
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Injectable, OnModuleInit, INestApplication } from '@nestjs/common';
|
|
2
|
+
import { PrismaClient } from '@prisma/client';
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class PrismaService extends PrismaClient implements OnModuleInit {
|
|
6
|
+
async onModuleInit() {
|
|
7
|
+
await this.$connect();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async enableShutdownHooks(app: INestApplication) {
|
|
11
|
+
this.$on('beforeExit', async () => {
|
|
12
|
+
await app.close();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,32 +1,45 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
1
|
+
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
2
|
+
import { PrismaService } from '../prisma/prisma.service';
|
|
2
3
|
import { CreateItemDto } from '../models/create-item.dto';
|
|
3
|
-
import { Item } from '../models/item.model';
|
|
4
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
5
4
|
|
|
6
5
|
@Injectable()
|
|
7
6
|
export class ItemsService {
|
|
8
|
-
private
|
|
7
|
+
constructor(private prisma: PrismaService) {}
|
|
9
8
|
|
|
10
|
-
findAll()
|
|
11
|
-
return
|
|
9
|
+
async findAll() {
|
|
10
|
+
return this.prisma.item.findMany();
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
findOne(id: string)
|
|
15
|
-
|
|
13
|
+
async findOne(id: string) {
|
|
14
|
+
const item = await this.prisma.item.findUnique({
|
|
15
|
+
where: { id },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
if (!item) {
|
|
19
|
+
throw new NotFoundException('Item not found');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return item;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
|
-
create(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return item;
|
|
25
|
+
async create(createItemDto: CreateItemDto) {
|
|
26
|
+
return this.prisma.item.create({
|
|
27
|
+
data: {
|
|
28
|
+
name: createItemDto.name,
|
|
29
|
+
description: createItemDto.description,
|
|
30
|
+
price: createItemDto.price,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
remove(id: string)
|
|
30
|
-
|
|
35
|
+
async remove(id: string) {
|
|
36
|
+
try {
|
|
37
|
+
await this.prisma.item.delete({
|
|
38
|
+
where: { id },
|
|
39
|
+
});
|
|
40
|
+
return true;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
31
44
|
}
|
|
32
|
-
}
|
|
45
|
+
}
|
|
@@ -8,14 +8,68 @@ datasource db {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
model User {
|
|
11
|
-
id String
|
|
12
|
-
email String
|
|
11
|
+
id String @id @default(uuid())
|
|
12
|
+
email String @unique
|
|
13
13
|
name String?
|
|
14
|
-
password String?
|
|
15
|
-
stripeCustomerId String?
|
|
14
|
+
password String? // Optional for OAuth, required for credentials
|
|
15
|
+
stripeCustomerId String? @map("stripe_customer_id")
|
|
16
16
|
image String?
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
emailVerified DateTime? @map("email_verified")
|
|
18
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
19
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
20
|
+
|
|
21
|
+
accounts Account[]
|
|
22
|
+
sessions Session[]
|
|
19
23
|
|
|
20
24
|
@@map("users")
|
|
21
25
|
}
|
|
26
|
+
|
|
27
|
+
model Account {
|
|
28
|
+
id String @id @default(uuid())
|
|
29
|
+
userId String @map("user_id")
|
|
30
|
+
type String
|
|
31
|
+
provider String
|
|
32
|
+
providerAccountId String @map("provider_account_id")
|
|
33
|
+
refresh_token String? @db.Text
|
|
34
|
+
access_token String? @db.Text
|
|
35
|
+
expires_at Int?
|
|
36
|
+
token_type String?
|
|
37
|
+
scope String?
|
|
38
|
+
id_token String? @db.Text
|
|
39
|
+
session_state String?
|
|
40
|
+
|
|
41
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
42
|
+
|
|
43
|
+
@@unique([provider, providerAccountId])
|
|
44
|
+
@@map("accounts")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
model Session {
|
|
48
|
+
id String @id @default(uuid())
|
|
49
|
+
sessionToken String @unique @map("session_token")
|
|
50
|
+
userId String @map("user_id")
|
|
51
|
+
expires DateTime
|
|
52
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
53
|
+
|
|
54
|
+
@@map("sessions")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
model VerificationToken {
|
|
58
|
+
identifier String
|
|
59
|
+
token String @unique
|
|
60
|
+
expires DateTime
|
|
61
|
+
|
|
62
|
+
@@unique([identifier, token])
|
|
63
|
+
@@map("verification_tokens")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
model Item {
|
|
67
|
+
id String @id @default(uuid())
|
|
68
|
+
name String
|
|
69
|
+
description String?
|
|
70
|
+
price Float?
|
|
71
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
72
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
73
|
+
|
|
74
|
+
@@map("items")
|
|
75
|
+
}
|