archforge-x 1.0.2 → 1.0.4

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.
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoGinGenerator = void 0;
4
+ const base_1 = require("../base");
5
+ class GoGinGenerator extends base_1.BaseGenerator {
6
+ getGeneratorName() {
7
+ return "Go (Gin)";
8
+ }
9
+ async generateProjectStructure(root, arch, options) {
10
+ const projectName = options.projectName || "go-gin-app";
11
+ this.generateCommonFiles(root, projectName, options);
12
+ this.generateAppStructure(root, options);
13
+ }
14
+ generateCommonFiles(root, projectName, options) {
15
+ this.writeFile(root, "go.mod", `
16
+ module ${projectName}
17
+
18
+ go 1.21
19
+
20
+ require (
21
+ github.com/gin-gonic/gin v1.9.1
22
+ github.com/joho/godotenv v1.5.1
23
+ ${options.orm === 'gorm' ? 'gorm.io/gorm v1.25.5' : ''}
24
+ ${options.orm === 'gorm' && options.database === 'postgresql' ? 'gorm.io/driver/postgres v1.5.4' : ''}
25
+ ${options.orm === 'gorm' && options.database === 'mysql' ? 'gorm.io/driver/mysql v1.5.2' : ''}
26
+ ${options.orm === 'gorm' && options.database === 'sqlite' ? 'gorm.io/driver/sqlite v1.5.4' : ''}
27
+ )
28
+ `.trim());
29
+ if (options.orm === 'gorm') {
30
+ this.generateGORMSetup(root, options);
31
+ }
32
+ this.writeFile(root, ".env", "PORT=8080\nENV=development");
33
+ this.writeFile(root, ".gitignore", "bin/\n.env\nvendor/\n");
34
+ this.writeFile(root, "README.md", `# ${projectName}\n\nGenerated by ArchForge X`);
35
+ // .golangci.yml (Architecture Guardrails)
36
+ this.writeFile(root, ".golangci.yml", `
37
+ linters:
38
+ enable:
39
+ - depguard
40
+
41
+ linters-settings:
42
+ depguard:
43
+ rules:
44
+ main:
45
+ files:
46
+ - "$all"
47
+ - "!$test"
48
+ allow:
49
+ - $gostd
50
+ - github.com/gin-gonic/gin
51
+ - github.com/joho/godotenv
52
+ - ${projectName}/internal/api
53
+ - ${projectName}/internal/handlers
54
+ - ${projectName}/internal/models
55
+ deny:
56
+ - pkg: ${projectName}/internal/handlers
57
+ desc: "Models cannot import handlers"
58
+ files:
59
+ - "**/internal/models/**/*.go"
60
+ - pkg: ${projectName}/internal/api
61
+ desc: "Models cannot import api"
62
+ files:
63
+ - "**/internal/models/**/*.go"
64
+ `.trim());
65
+ }
66
+ generateAppStructure(root, options) {
67
+ // Standard Go Layout: cmd, internal, pkg
68
+ // cmd/server/main.go
69
+ this.writeFile(root, "cmd/server/main.go", `
70
+ package main
71
+
72
+ import (
73
+ "log"
74
+ "os"
75
+
76
+ "github.com/gin-gonic/gin"
77
+ "github.com/joho/godotenv"
78
+ "${options.projectName || "go-gin-app"}/internal/api"
79
+ ${options.orm === 'gorm' ? `"${options.projectName || "go-gin-app"}/internal/infrastructure/database"` : ''}
80
+ )
81
+
82
+ func main() {
83
+ if err := godotenv.Load(); err != nil {
84
+ log.Println("No .env file found")
85
+ }
86
+
87
+ ${options.orm === 'gorm' ? 'database.InitDB()' : ''}
88
+
89
+ r := gin.Default()
90
+
91
+ api.SetupRoutes(r)
92
+
93
+ port := os.Getenv("PORT")
94
+ if port == "" {
95
+ port = "8080"
96
+ }
97
+
98
+ r.Run(":" + port)
99
+ }
100
+ `);
101
+ // internal/api/routes.go
102
+ this.writeFile(root, "internal/api/routes.go", `
103
+ package api
104
+
105
+ import (
106
+ "github.com/gin-gonic/gin"
107
+ "${options.projectName || "go-gin-app"}/internal/handlers"
108
+ )
109
+
110
+ func SetupRoutes(r *gin.Engine) {
111
+ v1 := r.Group("/api/v1")
112
+ {
113
+ v1.GET("/health", handlers.HealthCheck)
114
+ v1.POST("/users", handlers.CreateUser)
115
+ }
116
+ }
117
+ `);
118
+ // internal/handlers/user.go
119
+ if (options.orm === 'gorm') {
120
+ this.writeFile(root, "internal/handlers/user.go", `
121
+ package handlers
122
+
123
+ import (
124
+ "net/http"
125
+ "github.com/gin-gonic/gin"
126
+ "${options.projectName || "go-gin-app"}/internal/models"
127
+ "${options.projectName || "go-gin-app"}/internal/infrastructure/database"
128
+ )
129
+
130
+ func HealthCheck(c *gin.Context) {
131
+ c.JSON(http.StatusOK, gin.H{"status": "ok"})
132
+ }
133
+
134
+ func CreateUser(c *gin.Context) {
135
+ var user models.User
136
+ if err := c.ShouldBindJSON(&user); err != nil {
137
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
138
+ return
139
+ }
140
+
141
+ if err := database.DB.Create(&user).Error; err != nil {
142
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
143
+ return
144
+ }
145
+
146
+ c.JSON(http.StatusCreated, user)
147
+ }
148
+ `);
149
+ }
150
+ else {
151
+ this.writeFile(root, "internal/handlers/user.go", `
152
+ package handlers
153
+
154
+ import (
155
+ "net/http"
156
+ "github.com/gin-gonic/gin"
157
+ "${options.projectName || "go-gin-app"}/internal/models"
158
+ )
159
+
160
+ func HealthCheck(c *gin.Context) {
161
+ c.JSON(http.StatusOK, gin.H{"status": "ok"})
162
+ }
163
+
164
+ func CreateUser(c *gin.Context) {
165
+ var user models.User
166
+ if err := c.ShouldBindJSON(&user); err != nil {
167
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
168
+ return
169
+ }
170
+
171
+ user.ID = "123"
172
+ c.JSON(http.StatusCreated, user)
173
+ }
174
+ `);
175
+ }
176
+ // internal/models/user.go
177
+ if (options.orm === 'gorm') {
178
+ this.writeFile(root, "internal/models/user.go", `
179
+ package models
180
+
181
+ import "gorm.io/gorm"
182
+
183
+ type User struct {
184
+ gorm.Model
185
+ Name string \`json:"name" binding:"required"\`
186
+ Email string \`json:"email" binding:"required,email" gorm:"uniqueIndex"\`
187
+ }
188
+ `);
189
+ }
190
+ else {
191
+ this.writeFile(root, "internal/models/user.go", `
192
+ package models
193
+
194
+ type User struct {
195
+ ID string \`json:"id"\`
196
+ Name string \`json:"name" binding:"required"\`
197
+ Email string \`json:"email" binding:"required,email"\`
198
+ }
199
+ `);
200
+ }
201
+ }
202
+ generateDocker(root, options) {
203
+ const dbService = options.database === "postgresql" ? `
204
+ db:
205
+ image: postgres:15-alpine
206
+ environment:
207
+ - POSTGRES_USER=user
208
+ - POSTGRES_PASSWORD=password
209
+ - POSTGRES_DB=appdb
210
+ ports:
211
+ - "5432:5432"
212
+ ` : options.database === "mysql" ? `
213
+ db:
214
+ image: mysql:8
215
+ environment:
216
+ - MYSQL_ROOT_PASSWORD=password
217
+ - MYSQL_DATABASE=appdb
218
+ ports:
219
+ - "3306:3306"
220
+ ` : "";
221
+ const dbUrl = options.database === "postgresql" ? "host=db user=user password=password dbname=appdb port=5432 sslmode=disable" :
222
+ options.database === "mysql" ? "root:password@tcp(db:3306)/appdb?charset=utf8mb4&parseTime=True&loc=Local" :
223
+ "app.db";
224
+ this.writeFile(root, "Dockerfile", `
225
+ FROM golang:1.21-alpine AS builder
226
+ WORKDIR /app
227
+ COPY go.mod go.sum ./
228
+ RUN go mod download
229
+ COPY . .
230
+ RUN go build -o main cmd/server/main.go
231
+
232
+ FROM alpine:latest
233
+ WORKDIR /app
234
+ COPY --from=builder /app/main .
235
+ COPY --from=builder /app/.env .
236
+ EXPOSE 8080
237
+ CMD ["./main"]
238
+ `);
239
+ this.writeFile(root, "docker-compose.yml", `
240
+ version: '3.8'
241
+ services:
242
+ app:
243
+ build: .
244
+ ports:
245
+ - "8080:8080"
246
+ environment:
247
+ - PORT=8080
248
+ - ENV=production
249
+ - DATABASE_URL=${dbUrl}
250
+ depends_on:
251
+ ${dbService ? "- db" : ""}
252
+ restart: always
253
+ ${dbService}
254
+ `);
255
+ }
256
+ generateCI(root, options) {
257
+ this.writeFile(root, ".github/workflows/ci.yml", `
258
+ name: CI
259
+
260
+ on:
261
+ push:
262
+ branches: [ main ]
263
+ pull_request:
264
+ branches: [ main ]
265
+
266
+ jobs:
267
+ build:
268
+ runs-on: ubuntu-latest
269
+
270
+ steps:
271
+ - uses: actions/checkout@v3
272
+ - name: Set up Go
273
+ uses: actions/setup-go@v4
274
+ with:
275
+ go-version: '1.21'
276
+ - name: Check Architecture Boundaries
277
+ uses: golangci/golangci-lint-action@v3
278
+ with:
279
+ version: latest
280
+ - name: Architecture Sync & Validation
281
+ run: |
282
+ # In a real scenario, archforge would be installed
283
+ echo "Running archforge sync..."
284
+ - name: Build
285
+ run: go build -v ./...
286
+ - name: Test
287
+ run: go test -v ./...
288
+ `);
289
+ }
290
+ generateGORMSetup(root, options) {
291
+ const driver = options.database === "postgresql" ? "postgres" :
292
+ options.database === "mysql" ? "mysql" : "sqlite";
293
+ const importPath = options.database === "postgresql" ? "gorm.io/driver/postgres" :
294
+ options.database === "mysql" ? "gorm.io/driver/mysql" : "gorm.io/driver/sqlite";
295
+ this.writeFile(root, "internal/infrastructure/database/db.go", `
296
+ package database
297
+
298
+ import (
299
+ "log"
300
+ "os"
301
+
302
+ "${importPath}"
303
+ "gorm.io/gorm"
304
+ "${options.projectName || "go-gin-app"}/internal/models"
305
+ )
306
+
307
+ var DB *gorm.DB
308
+
309
+ func InitDB() {
310
+ dsn := os.Getenv("DATABASE_URL")
311
+ if dsn == "" {
312
+ ${options.database === 'sqlite' ? 'dsn = "app.db"' : 'log.Fatal("DATABASE_URL is not set")'}
313
+ }
314
+
315
+ var err error
316
+ DB, err = gorm.Open(${driver}.Open(dsn), &gorm.Config{})
317
+ if err != nil {
318
+ log.Fatal("Failed to connect to database:", err)
319
+ }
320
+
321
+ // Auto Migrate
322
+ DB.AutoMigrate(&models.User{})
323
+ }
324
+ `);
325
+ }
326
+ }
327
+ exports.GoGinGenerator = GoGinGenerator;