archforge-x 1.0.2 → 1.0.3
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/dist/cli/commands/sync.js +22 -0
- package/dist/cli/interactive.js +41 -3
- package/dist/core/architecture/schema.js +23 -2
- package/dist/core/architecture/validator.js +112 -0
- package/dist/generators/base.js +166 -0
- package/dist/generators/generator.js +35 -332
- package/dist/generators/go/gin.js +327 -0
- package/dist/generators/node/express.js +920 -0
- package/dist/generators/node/nestjs.js +770 -0
- package/dist/generators/node/nextjs.js +252 -0
- package/dist/generators/python/django.js +327 -0
- package/dist/generators/python/fastapi.js +309 -0
- package/dist/generators/registry.js +25 -0
- package/dist/index.js +10 -1
- package/package.json +3 -1
|
@@ -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;
|