openwork-agent 1.0.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/LICENSE +21 -0
- package/README.md +436 -0
- package/package.json +78 -0
- package/src/core/TechDetector.js +351 -0
- package/src/generators/ProjectGenerator.js +1241 -0
- package/src/generators/ProjectGeneratorExtensions.js +14 -0
- package/src/generators/TemplateMethods.js +402 -0
- package/src/generators/index.js +5 -0
- package/src/index.js +152 -0
- package/src/main.js +8 -0
- package/src/templates/common/README.md.hbs +358 -0
- package/src/templates/docker/index.js +518 -0
- package/src/templates/docker.js +58 -0
- package/src/templates/go/basic/api/routes/user.go.hbs +138 -0
- package/src/templates/go/basic/config/config.go.hbs +54 -0
- package/src/templates/go/basic/go.mod.hbs +8 -0
- package/src/templates/go/basic/main.go.hbs +70 -0
- package/src/templates/go/basic/models/user.go.hbs +69 -0
- package/src/templates/go/basic/services/user_service.go.hbs +173 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/controller/UserController.java.hbs +91 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/dto/ApiResponse.java.hbs +40 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/model/User.java.hbs +102 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/repository/UserRepository.java.hbs +20 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/service/UserService.java.hbs +65 -0
- package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/{{pascalCase projectName}}Application.java.hbs +16 -0
- package/src/templates/node/basic/src/config/database.ts.hbs +18 -0
- package/src/templates/node/basic/src/controllers/UserController.ts.hbs +98 -0
- package/src/templates/node/basic/src/index.ts.hbs +45 -0
- package/src/templates/node/basic/src/middleware/errorHandler.ts.hbs +33 -0
- package/src/templates/node/basic/src/routes/index.ts.hbs +42 -0
- package/src/templates/node/basic/src/types/index.ts.hbs +18 -0
- package/src/templates/python/basic/config/database.py.hbs +36 -0
- package/src/templates/python/basic/main.py.hbs +58 -0
- package/src/templates/python/basic/middleware/error_handler.py.hbs +41 -0
- package/src/templates/python/basic/models/user.py.hbs +40 -0
- package/src/templates/python/basic/routes/__init__.py.hbs +12 -0
- package/src/templates/python/basic/routes/users.py.hbs +64 -0
- package/src/templates/rust/basic/Cargo.toml.hbs +39 -0
- package/src/templates/rust/basic/src/config/database.rs.hbs +27 -0
- package/src/templates/rust/basic/src/handlers/user.rs.hbs +130 -0
- package/src/templates/rust/basic/src/handlers/user_routes.rs.hbs +15 -0
- package/src/templates/rust/basic/src/main.rs.hbs +53 -0
- package/src/templates/rust/basic/src/models/mod.rs.hbs +79 -0
- package/src/templates/rust/basic/src/schema.rs.hbs +10 -0
- package/src/utils/FileManager.js +186 -0
- package/src/utils/Templates.js +231 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package config
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"log"
|
|
5
|
+
"os"
|
|
6
|
+
"strconv"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
type Config struct {
|
|
10
|
+
ServerPort string
|
|
11
|
+
DatabaseURL string
|
|
12
|
+
DatabaseName string
|
|
13
|
+
JWTSecret string
|
|
14
|
+
Environment string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
var AppConfig *Config
|
|
18
|
+
|
|
19
|
+
func LoadConfig() {
|
|
20
|
+
AppConfig = &Config{
|
|
21
|
+
ServerPort: getEnv("PORT", "8080"),
|
|
22
|
+
DatabaseURL: getEnv("DATABASE_URL", "mongodb://localhost:27017"),
|
|
23
|
+
DatabaseName: getEnv("DB_NAME", "{{projectName}}"),
|
|
24
|
+
JWTSecret: getEnv("JWT_SECRET", "your-secret-key"),
|
|
25
|
+
Environment: getEnv("ENVIRONMENT", "development"),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
log.Printf("Configuration loaded for environment: %s", AppConfig.Environment)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func getEnv(key, defaultValue string) string {
|
|
32
|
+
if value := os.Getenv(key); value != "" {
|
|
33
|
+
return value
|
|
34
|
+
}
|
|
35
|
+
return defaultValue
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
func getEnvAsInt(key string, defaultValue int) int {
|
|
39
|
+
if valueStr := os.Getenv(key); valueStr != "" {
|
|
40
|
+
if value, err := strconv.Atoi(valueStr); err == nil {
|
|
41
|
+
return value
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return defaultValue
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func getEnvAsBool(key string, defaultValue bool) bool {
|
|
48
|
+
if valueStr := os.Getenv(key); valueStr != "" {
|
|
49
|
+
if value, err := strconv.ParseBool(valueStr); err == nil {
|
|
50
|
+
return value
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return defaultValue
|
|
54
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"log"
|
|
5
|
+
"os"
|
|
6
|
+
|
|
7
|
+
"{{projectName}}/api/routes"
|
|
8
|
+
"{{projectName}}/config"
|
|
9
|
+
"{{projectName}}/models"
|
|
10
|
+
|
|
11
|
+
"github.com/gin-gonic/gin"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
func main() {
|
|
15
|
+
// Load configuration
|
|
16
|
+
config.LoadConfig()
|
|
17
|
+
|
|
18
|
+
// Initialize database
|
|
19
|
+
if err := models.ConnectDatabase(); err != nil {
|
|
20
|
+
log.Fatal("Failed to connect to database:", err)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Set Gin mode
|
|
24
|
+
if os.Getenv("GIN_MODE") == "release" {
|
|
25
|
+
gin.SetMode(gin.ReleaseMode)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Create Gin router
|
|
29
|
+
r := gin.Default()
|
|
30
|
+
|
|
31
|
+
// Add middleware
|
|
32
|
+
r.Use(gin.Logger())
|
|
33
|
+
r.Use(gin.Recovery())
|
|
34
|
+
|
|
35
|
+
// CORS middleware
|
|
36
|
+
r.Use(func(c *gin.Context) {
|
|
37
|
+
c.Header("Access-Control-Allow-Origin", "*")
|
|
38
|
+
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
|
39
|
+
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
|
40
|
+
|
|
41
|
+
if c.Request.Method == "OPTIONS" {
|
|
42
|
+
c.AbortWithStatus(204)
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
c.Next()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Health check endpoint
|
|
50
|
+
r.GET("/health", func(c *gin.Context) {
|
|
51
|
+
c.JSON(200, gin.H{
|
|
52
|
+
"status": "OK",
|
|
53
|
+
"timestamp": "2024-01-01T00:00:00Z",
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// Setup routes
|
|
58
|
+
api := r.Group("/api")
|
|
59
|
+
routes.SetupRoutes(api)
|
|
60
|
+
|
|
61
|
+
port := os.Getenv("PORT")
|
|
62
|
+
if port == "" {
|
|
63
|
+
port = "8080"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
log.Printf("🚀 Server starting on port %s", port)
|
|
67
|
+
if err := r.Run(":" + port); err != nil {
|
|
68
|
+
log.Fatal("Failed to start server:", err)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package models
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"log"
|
|
6
|
+
"time"
|
|
7
|
+
|
|
8
|
+
"{{projectName}}/config"
|
|
9
|
+
|
|
10
|
+
"go.mongodb.org/mongo-driver/mongo"
|
|
11
|
+
"go.mongodb.org/mongo-driver/mongo/options"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
var DB *mongo.Database
|
|
15
|
+
|
|
16
|
+
type User struct {
|
|
17
|
+
ID string `json:"id" bson:"_id,omitempty"`
|
|
18
|
+
Name string `json:"name" bson:"name"`
|
|
19
|
+
Email string `json:"email" bson:"email"`
|
|
20
|
+
Age *int `json:"age" bson:"age,omitempty"`
|
|
21
|
+
CreatedAt time.Time `json:"created_at" bson:"created_at"`
|
|
22
|
+
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func ConnectDatabase() error {
|
|
26
|
+
clientOptions := options.Client().ApplyURI(config.AppConfig.DatabaseURL)
|
|
27
|
+
client, err := mongo.Connect(context.Background(), clientOptions)
|
|
28
|
+
|
|
29
|
+
if err != nil {
|
|
30
|
+
return err
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check the connection
|
|
34
|
+
err = client.Ping(context.Background(), nil)
|
|
35
|
+
if err != nil {
|
|
36
|
+
return err
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
DB = client.Database(config.AppConfig.DatabaseName)
|
|
40
|
+
log.Println("✅ Connected to MongoDB")
|
|
41
|
+
|
|
42
|
+
// Create indexes
|
|
43
|
+
if err := createIndexes(); err != nil {
|
|
44
|
+
log.Printf("Warning: Failed to create indexes: %v", err)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return nil
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func createIndexes() error {
|
|
51
|
+
userCollection := DB.Collection("users")
|
|
52
|
+
|
|
53
|
+
// Create unique index on email
|
|
54
|
+
indexModel := mongo.IndexModel{
|
|
55
|
+
Keys: map[string]int{"email": 1},
|
|
56
|
+
Options: options.Index().SetUnique(true),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_, err := userCollection.Indexes().CreateOne(context.Background(), indexModel)
|
|
60
|
+
return err
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func (u *User) PreSave() {
|
|
64
|
+
now := time.Now()
|
|
65
|
+
if u.CreatedAt.IsZero() {
|
|
66
|
+
u.CreatedAt = now
|
|
67
|
+
}
|
|
68
|
+
u.UpdatedAt = now
|
|
69
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
package services
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"errors"
|
|
6
|
+
"fmt"
|
|
7
|
+
"time"
|
|
8
|
+
|
|
9
|
+
"{{projectName}}/models"
|
|
10
|
+
|
|
11
|
+
"go.mongodb.org/mongo-driver/bson"
|
|
12
|
+
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
13
|
+
"go.mongodb.org/mongo-driver/mongo"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
type UserService struct {
|
|
17
|
+
collection *mongo.Collection
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func NewUserService() *UserService {
|
|
21
|
+
return &UserService{
|
|
22
|
+
collection: models.DB.Collection("users"),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func (s *UserService) GetAllUsers() ([]models.User, error) {
|
|
27
|
+
var users []models.User
|
|
28
|
+
|
|
29
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
30
|
+
defer cancel()
|
|
31
|
+
|
|
32
|
+
cursor, err := s.collection.Find(ctx, bson.M{})
|
|
33
|
+
if err != nil {
|
|
34
|
+
return nil, err
|
|
35
|
+
}
|
|
36
|
+
defer cursor.Close(ctx)
|
|
37
|
+
|
|
38
|
+
for cursor.Next(ctx) {
|
|
39
|
+
var user models.User
|
|
40
|
+
if err := cursor.Decode(&user); err != nil {
|
|
41
|
+
return nil, err
|
|
42
|
+
}
|
|
43
|
+
users = append(users, user)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if err := cursor.Err(); err != nil {
|
|
47
|
+
return nil, err
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return users, nil
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func (s *UserService) GetUserByID(id string) (*models.User, error) {
|
|
54
|
+
objectID, err := primitive.ObjectIDFromHex(id)
|
|
55
|
+
if err != nil {
|
|
56
|
+
return nil, fmt.Errorf("invalid user ID")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var user models.User
|
|
60
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
61
|
+
defer cancel()
|
|
62
|
+
|
|
63
|
+
err = s.collection.FindOne(ctx, bson.M{"_id": objectID}).Decode(&user)
|
|
64
|
+
if err != nil {
|
|
65
|
+
if err == mongo.ErrNoDocuments {
|
|
66
|
+
return nil, fmt.Errorf("user not found")
|
|
67
|
+
}
|
|
68
|
+
return nil, err
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return &user, nil
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func (s *UserService) CreateUser(user *models.User) (*models.User, error) {
|
|
75
|
+
user.PreSave()
|
|
76
|
+
|
|
77
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
78
|
+
defer cancel()
|
|
79
|
+
|
|
80
|
+
result, err := s.collection.InsertOne(ctx, user)
|
|
81
|
+
if err != nil {
|
|
82
|
+
return nil, err
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
user.ID = result.InsertedID.(primitive.ObjectID).Hex()
|
|
86
|
+
return user, nil
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
func (s *UserService) UpdateUser(id string, user *models.User) (*models.User, error) {
|
|
90
|
+
objectID, err := primitive.ObjectIDFromHex(id)
|
|
91
|
+
if err != nil {
|
|
92
|
+
return nil, fmt.Errorf("invalid user ID")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
user.PreSave()
|
|
96
|
+
|
|
97
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
98
|
+
defer cancel()
|
|
99
|
+
|
|
100
|
+
update := bson.M{
|
|
101
|
+
"$set": bson.M{
|
|
102
|
+
"name": user.Name,
|
|
103
|
+
"email": user.Email,
|
|
104
|
+
"age": user.Age,
|
|
105
|
+
"updated_at": user.UpdatedAt,
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
var updatedUser models.User
|
|
110
|
+
err = s.collection.FindOneAndUpdate(
|
|
111
|
+
ctx,
|
|
112
|
+
bson.M{"_id": objectID},
|
|
113
|
+
update,
|
|
114
|
+
).Decode(&updatedUser)
|
|
115
|
+
|
|
116
|
+
if err != nil {
|
|
117
|
+
if err == mongo.ErrNoDocuments {
|
|
118
|
+
return nil, fmt.Errorf("user not found")
|
|
119
|
+
}
|
|
120
|
+
return nil, err
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return &updatedUser, nil
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
func (s *UserService) DeleteUser(id string) error {
|
|
127
|
+
objectID, err := primitive.ObjectIDFromHex(id)
|
|
128
|
+
if err != nil {
|
|
129
|
+
return fmt.Errorf("invalid user ID")
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
133
|
+
defer cancel()
|
|
134
|
+
|
|
135
|
+
result, err := s.collection.DeleteOne(ctx, bson.M{"_id": objectID})
|
|
136
|
+
if err != nil {
|
|
137
|
+
return err
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if result.DeletedCount == 0 {
|
|
141
|
+
return fmt.Errorf("user not found")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return nil
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
func (s *UserService) GetUserByEmail(email string) (*models.User, error) {
|
|
148
|
+
var user models.User
|
|
149
|
+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
150
|
+
defer cancel()
|
|
151
|
+
|
|
152
|
+
err := s.collection.FindOne(ctx, bson.M{"email": email}).Decode(&user)
|
|
153
|
+
if err != nil {
|
|
154
|
+
if err == mongo.ErrNoDocuments {
|
|
155
|
+
return nil, fmt.Errorf("user not found")
|
|
156
|
+
}
|
|
157
|
+
return nil, err
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return &user, nil
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
func (s *UserService) UserExists(email string) (bool, error) {
|
|
164
|
+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
165
|
+
defer cancel()
|
|
166
|
+
|
|
167
|
+
count, err := s.collection.CountDocuments(ctx, bson.M{"email": email})
|
|
168
|
+
if err != nil {
|
|
169
|
+
return false, err
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return count > 0, nil
|
|
173
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package com.{{snakeCase projectName}}.{{projectName}}.controller;
|
|
2
|
+
|
|
3
|
+
import com.{{snakeCase projectName}}.{{projectName}}.model.User;
|
|
4
|
+
import com.{{snakeCase projectName}}.{{projectName}}.service.UserService;
|
|
5
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
|
6
|
+
import org.springframework.http.HttpStatus;
|
|
7
|
+
import org.springframework.http.ResponseEntity;
|
|
8
|
+
import org.springframework.web.bind.annotation.*;
|
|
9
|
+
|
|
10
|
+
import java.util.List;
|
|
11
|
+
import java.util.Optional;
|
|
12
|
+
|
|
13
|
+
@RestController
|
|
14
|
+
@RequestMapping("/api/users")
|
|
15
|
+
@CrossOrigin(origins = "*")
|
|
16
|
+
public class UserController {
|
|
17
|
+
|
|
18
|
+
@Autowired
|
|
19
|
+
private UserService userService;
|
|
20
|
+
|
|
21
|
+
@GetMapping
|
|
22
|
+
public ResponseEntity<ApiResponse<List<User>>> getAllUsers() {
|
|
23
|
+
try {
|
|
24
|
+
List<User> users = userService.getAllUsers();
|
|
25
|
+
return ResponseEntity.ok(new ApiResponse<>(true, users, "Users retrieved successfully"));
|
|
26
|
+
} catch (Exception e) {
|
|
27
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
28
|
+
.body(new ApiResponse<>(false, null, "Failed to retrieve users: " + e.getMessage()));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@GetMapping("/{id}")
|
|
33
|
+
public ResponseEntity<ApiResponse<User>> getUserById(@PathVariable String id) {
|
|
34
|
+
try {
|
|
35
|
+
Optional<User> user = userService.getUserById(id);
|
|
36
|
+
if (user.isPresent()) {
|
|
37
|
+
return ResponseEntity.ok(new ApiResponse<>(true, user.get(), "User retrieved successfully"));
|
|
38
|
+
} else {
|
|
39
|
+
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
|
40
|
+
.body(new ApiResponse<>(false, null, "User not found"));
|
|
41
|
+
}
|
|
42
|
+
} catch (Exception e) {
|
|
43
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
44
|
+
.body(new ApiResponse<>(false, null, "Failed to retrieve user: " + e.getMessage()));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@PostMapping
|
|
49
|
+
public ResponseEntity<ApiResponse<User>> createUser(@RequestBody User user) {
|
|
50
|
+
try {
|
|
51
|
+
User createdUser = userService.createUser(user);
|
|
52
|
+
return ResponseEntity.status(HttpStatus.CREATED)
|
|
53
|
+
.body(new ApiResponse<>(true, createdUser, "User created successfully"));
|
|
54
|
+
} catch (Exception e) {
|
|
55
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
56
|
+
.body(new ApiResponse<>(false, null, "Failed to create user: " + e.getMessage()));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@PutMapping("/{id}")
|
|
61
|
+
public ResponseEntity<ApiResponse<User>> updateUser(@PathVariable String id, @RequestBody User user) {
|
|
62
|
+
try {
|
|
63
|
+
User updatedUser = userService.updateUser(id, user);
|
|
64
|
+
if (updatedUser != null) {
|
|
65
|
+
return ResponseEntity.ok(new ApiResponse<>(true, updatedUser, "User updated successfully"));
|
|
66
|
+
} else {
|
|
67
|
+
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
|
68
|
+
.body(new ApiResponse<>(false, null, "User not found"));
|
|
69
|
+
}
|
|
70
|
+
} catch (Exception e) {
|
|
71
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
72
|
+
.body(new ApiResponse<>(false, null, "Failed to update user: " + e.getMessage()));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@DeleteMapping("/{id}")
|
|
77
|
+
public ResponseEntity<ApiResponse<Void>> deleteUser(@PathVariable String id) {
|
|
78
|
+
try {
|
|
79
|
+
boolean deleted = userService.deleteUser(id);
|
|
80
|
+
if (deleted) {
|
|
81
|
+
return ResponseEntity.ok(new ApiResponse<>(true, null, "User deleted successfully"));
|
|
82
|
+
} else {
|
|
83
|
+
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
|
84
|
+
.body(new ApiResponse<>(false, null, "User not found"));
|
|
85
|
+
}
|
|
86
|
+
} catch (Exception e) {
|
|
87
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
88
|
+
.body(new ApiResponse<>(false, null, "Failed to delete user: " + e.getMessage()));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
package com.{{snakeCase projectName}}.{{projectName}}.dto;
|
|
2
|
+
|
|
3
|
+
public class ApiResponse<T> {
|
|
4
|
+
private boolean success;
|
|
5
|
+
private T data;
|
|
6
|
+
private String message;
|
|
7
|
+
|
|
8
|
+
public ApiResponse() {}
|
|
9
|
+
|
|
10
|
+
public ApiResponse(boolean success, T data, String message) {
|
|
11
|
+
this.success = success;
|
|
12
|
+
this.data = data;
|
|
13
|
+
this.message = message;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Getters and Setters
|
|
17
|
+
public boolean isSuccess() {
|
|
18
|
+
return success;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public void setSuccess(boolean success) {
|
|
22
|
+
this.success = success;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public T getData() {
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public void setData(T data) {
|
|
30
|
+
this.data = data;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public String getMessage() {
|
|
34
|
+
return message;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public void setMessage(String message) {
|
|
38
|
+
this.message = message;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
package com.{{snakeCase projectName}}.{{projectName}}.model;
|
|
2
|
+
|
|
3
|
+
import org.springframework.data.annotation.Id;
|
|
4
|
+
import org.springframework.data.mongodb.core.mapping.Document;
|
|
5
|
+
import org.springframework.data.mongodb.core.mapping.Field;
|
|
6
|
+
import java.time.LocalDateTime;
|
|
7
|
+
|
|
8
|
+
@Document(collection = "users")
|
|
9
|
+
public class User {
|
|
10
|
+
|
|
11
|
+
@Id
|
|
12
|
+
private String id;
|
|
13
|
+
|
|
14
|
+
private String name;
|
|
15
|
+
|
|
16
|
+
private String email;
|
|
17
|
+
|
|
18
|
+
private Integer age;
|
|
19
|
+
|
|
20
|
+
@Field("created_at")
|
|
21
|
+
private LocalDateTime createdAt;
|
|
22
|
+
|
|
23
|
+
@Field("updated_at")
|
|
24
|
+
private LocalDateTime updatedAt;
|
|
25
|
+
|
|
26
|
+
// Constructors
|
|
27
|
+
public User() {
|
|
28
|
+
this.createdAt = LocalDateTime.now();
|
|
29
|
+
this.updatedAt = LocalDateTime.now();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public User(String name, String email, Integer age) {
|
|
33
|
+
this();
|
|
34
|
+
this.name = name;
|
|
35
|
+
this.email = email;
|
|
36
|
+
this.age = age;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Getters and Setters
|
|
40
|
+
public String getId() {
|
|
41
|
+
return id;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public void setId(String id) {
|
|
45
|
+
this.id = id;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public String getName() {
|
|
49
|
+
return name;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public void setName(String name) {
|
|
53
|
+
this.name = name;
|
|
54
|
+
this.updatedAt = LocalDateTime.now();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public String getEmail() {
|
|
58
|
+
return email;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public void setEmail(String email) {
|
|
62
|
+
this.email = email;
|
|
63
|
+
this.updatedAt = LocalDateTime.now();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public Integer getAge() {
|
|
67
|
+
return age;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public void setAge(Integer age) {
|
|
71
|
+
this.age = age;
|
|
72
|
+
this.updatedAt = LocalDateTime.now();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public LocalDateTime getCreatedAt() {
|
|
76
|
+
return createdAt;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public void setCreatedAt(LocalDateTime createdAt) {
|
|
80
|
+
this.createdAt = createdAt;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public LocalDateTime getUpdatedAt() {
|
|
84
|
+
return updatedAt;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public void setUpdatedAt(LocalDateTime updatedAt) {
|
|
88
|
+
this.updatedAt = updatedAt;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Override
|
|
92
|
+
public String toString() {
|
|
93
|
+
return "User{" +
|
|
94
|
+
"id='" + id + '\'' +
|
|
95
|
+
", name='" + name + '\'' +
|
|
96
|
+
", email='" + email + '\'' +
|
|
97
|
+
", age=" + age +
|
|
98
|
+
", createdAt=" + createdAt +
|
|
99
|
+
", updatedAt=" + updatedAt +
|
|
100
|
+
'}';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.{{snakeCase projectName}}.{{projectName}}.repository;
|
|
2
|
+
|
|
3
|
+
import com.{{snakeCase projectName}}.{{projectName}}.model.User;
|
|
4
|
+
import org.springframework.data.mongodb.repository.MongoRepository;
|
|
5
|
+
import org.springframework.stereotype.Repository;
|
|
6
|
+
|
|
7
|
+
import java.util.List;
|
|
8
|
+
import java.util.Optional;
|
|
9
|
+
|
|
10
|
+
@Repository
|
|
11
|
+
public interface UserRepository extends MongoRepository<User, String> {
|
|
12
|
+
|
|
13
|
+
Optional<User> findByEmail(String email);
|
|
14
|
+
|
|
15
|
+
List<User> findByNameContainingIgnoreCase(String name);
|
|
16
|
+
|
|
17
|
+
boolean existsByEmail(String email);
|
|
18
|
+
|
|
19
|
+
void deleteByEmail(String email);
|
|
20
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
package com.{{snakeCase projectName}}.{{projectName}}.service;
|
|
2
|
+
|
|
3
|
+
import com.{{snakeCase projectName}}.{{projectName}}.model.User;
|
|
4
|
+
import com.{{snakeCase projectName}}.{{projectName}}.repository.UserRepository;
|
|
5
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
|
6
|
+
import org.springframework.stereotype.Service;
|
|
7
|
+
|
|
8
|
+
import java.time.LocalDateTime;
|
|
9
|
+
import java.util.List;
|
|
10
|
+
import java.util.Optional;
|
|
11
|
+
|
|
12
|
+
@Service
|
|
13
|
+
public class UserService {
|
|
14
|
+
|
|
15
|
+
@Autowired
|
|
16
|
+
private UserRepository userRepository;
|
|
17
|
+
|
|
18
|
+
public List<User> getAllUsers() {
|
|
19
|
+
return userRepository.findAll();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public Optional<User> getUserById(String id) {
|
|
23
|
+
return userRepository.findById(id);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public User createUser(User user) {
|
|
27
|
+
user.setCreatedAt(LocalDateTime.now());
|
|
28
|
+
user.setUpdatedAt(LocalDateTime.now());
|
|
29
|
+
return userRepository.save(user);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public User updateUser(String id, User userDetails) {
|
|
33
|
+
Optional<User> optionalUser = userRepository.findById(id);
|
|
34
|
+
|
|
35
|
+
if (optionalUser.isPresent()) {
|
|
36
|
+
User user = optionalUser.get();
|
|
37
|
+
user.setName(userDetails.getName() != null ? userDetails.getName() : user.getName());
|
|
38
|
+
user.setEmail(userDetails.getEmail() != null ? userDetails.getEmail() : user.getEmail());
|
|
39
|
+
user.setAge(userDetails.getAge() != null ? userDetails.getAge() : user.getAge());
|
|
40
|
+
user.setUpdatedAt(LocalDateTime.now());
|
|
41
|
+
return userRepository.save(user);
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public boolean deleteUser(String id) {
|
|
47
|
+
if (userRepository.existsById(id)) {
|
|
48
|
+
userRepository.deleteById(id);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public Optional<User> getUserByEmail(String email) {
|
|
55
|
+
return userRepository.findByEmail(email);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public List<User> getUsersByName(String name) {
|
|
59
|
+
return userRepository.findByNameContainingIgnoreCase(name);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public boolean userExists(String email) {
|
|
63
|
+
return userRepository.existsByEmail(email);
|
|
64
|
+
}
|
|
65
|
+
}
|