archforge-x 1.0.0 ā 1.0.2
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/package.json +4 -4
- package/dist/generators/professional.js +0 -509
- package/dist/generators/templates/base.js +0 -10
- package/dist/sample-app/application/application.js +0 -8
- package/dist/sample-app/domain/domain.js +0 -2
- package/dist/sample-app/domain/domain.spec.js +0 -2
- package/dist/sample-app/infrastructure/infrastructure.js +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archforge-x",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Enterprise Architecture Engine for scaffolding, analyzing, and visualizing software architecture.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
"@types/node": "^25.0.3",
|
|
43
43
|
"@types/prompts": "^2.4.9",
|
|
44
44
|
"@types/viz.js": "^2.1.5",
|
|
45
|
-
"ts-node": "^10.9.2"
|
|
46
|
-
"typescript": "^5.9.3"
|
|
45
|
+
"ts-node": "^10.9.2"
|
|
47
46
|
},
|
|
48
47
|
"dependencies": {
|
|
49
48
|
"chalk": "^5.6.2",
|
|
50
49
|
"commander": "^14.0.2",
|
|
51
50
|
"fs-extra": "^11.3.3",
|
|
52
51
|
"prompts": "^2.4.2",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
53
|
"viz.js": "^2.1.2",
|
|
54
54
|
"yaml": "^2.8.2",
|
|
55
55
|
"zod": "^4.2.1"
|
|
56
56
|
}
|
|
57
|
-
}
|
|
57
|
+
}
|
|
@@ -1,509 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.professionalGenerator = professionalGenerator;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
-
// --- HELPER FUNCTIONS ---
|
|
11
|
-
const writeFile = (root, filePath, content) => {
|
|
12
|
-
const fullPath = path_1.default.join(root, filePath);
|
|
13
|
-
fs_1.default.mkdirSync(path_1.default.dirname(fullPath), { recursive: true });
|
|
14
|
-
fs_1.default.writeFileSync(fullPath, content.trim());
|
|
15
|
-
};
|
|
16
|
-
const getPackageJson = (name, fw, arch, modules) => {
|
|
17
|
-
const deps = {
|
|
18
|
-
"dotenv": "^16.0.3",
|
|
19
|
-
};
|
|
20
|
-
const devDeps = {
|
|
21
|
-
"typescript": "^5.0.0",
|
|
22
|
-
"@types/node": "^20.0.0",
|
|
23
|
-
"jest": "^29.5.0",
|
|
24
|
-
"ts-jest": "^29.1.0",
|
|
25
|
-
"@types/jest": "^29.5.0",
|
|
26
|
-
"eslint": "^8.0.0",
|
|
27
|
-
"prettier": "^3.0.0"
|
|
28
|
-
};
|
|
29
|
-
if (fw === "nestjs") {
|
|
30
|
-
Object.assign(deps, {
|
|
31
|
-
"@nestjs/common": "^10.0.0",
|
|
32
|
-
"@nestjs/core": "^10.0.0",
|
|
33
|
-
"@nestjs/platform-express": "^10.0.0",
|
|
34
|
-
"reflect-metadata": "^0.1.13",
|
|
35
|
-
"rxjs": "^7.8.0"
|
|
36
|
-
});
|
|
37
|
-
Object.assign(devDeps, {
|
|
38
|
-
"@nestjs/cli": "^10.0.0",
|
|
39
|
-
"@nestjs/schematics": "^10.0.0",
|
|
40
|
-
"@nestjs/testing": "^10.0.0"
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
else if (fw === "express") {
|
|
44
|
-
Object.assign(deps, { "express": "^4.18.2", "cors": "^2.8.5" });
|
|
45
|
-
Object.assign(devDeps, { "@types/express": "^4.17.17", "ts-node-dev": "^2.0.0" });
|
|
46
|
-
}
|
|
47
|
-
if (modules.includes("auth"))
|
|
48
|
-
deps["jsonwebtoken"] = "^9.0.0";
|
|
49
|
-
if (modules.includes("auth") && fw === "nestjs")
|
|
50
|
-
deps["@nestjs/jwt"] = "^10.0.0";
|
|
51
|
-
if (modules.includes("db"))
|
|
52
|
-
deps["typeorm"] = "^0.3.17"; // Defaulting to TypeORM for boilerplate
|
|
53
|
-
if (modules.includes("cache"))
|
|
54
|
-
deps["ioredis"] = "^5.3.0";
|
|
55
|
-
return JSON.stringify({
|
|
56
|
-
name,
|
|
57
|
-
version: "0.0.1",
|
|
58
|
-
scripts: {
|
|
59
|
-
"start:dev": fw === "nestjs" ? "nest start --watch" : "ts-node-dev src/main.ts",
|
|
60
|
-
"build": "tsc",
|
|
61
|
-
"test": "jest"
|
|
62
|
-
},
|
|
63
|
-
dependencies: deps,
|
|
64
|
-
devDependencies: devDeps
|
|
65
|
-
}, null, 2);
|
|
66
|
-
};
|
|
67
|
-
const getGoMod = (name, fw) => {
|
|
68
|
-
return `module ${name}
|
|
69
|
-
|
|
70
|
-
go 1.21
|
|
71
|
-
|
|
72
|
-
require (
|
|
73
|
-
${fw === "gin" ? 'github.com/gin-gonic/gin v1.9.1' : ''}
|
|
74
|
-
github.com/joho/godotenv v1.5.1
|
|
75
|
-
)`;
|
|
76
|
-
};
|
|
77
|
-
const getRequirementsTxt = (fw, modules) => {
|
|
78
|
-
const reqs = ["python-dotenv"];
|
|
79
|
-
if (fw === "django")
|
|
80
|
-
reqs.push("Django>=4.2");
|
|
81
|
-
if (fw === "flask")
|
|
82
|
-
reqs.push("Flask>=2.3");
|
|
83
|
-
if (modules.includes("db"))
|
|
84
|
-
reqs.push("psycopg2-binary", "sqlalchemy");
|
|
85
|
-
if (modules.includes("auth"))
|
|
86
|
-
reqs.push("PyJWT");
|
|
87
|
-
return reqs.join("\n");
|
|
88
|
-
};
|
|
89
|
-
// --- CONTENT GENERATORS (Architecture Specific) ---
|
|
90
|
-
const generateTsCleanArch = (root, options) => {
|
|
91
|
-
// 1. Core / Domain (Enterprise Business Rules)
|
|
92
|
-
writeFile(root, "src/domain/entities/user.entity.ts", `
|
|
93
|
-
export class User {
|
|
94
|
-
constructor(
|
|
95
|
-
public readonly id: string,
|
|
96
|
-
public readonly name: string,
|
|
97
|
-
public readonly email: string,
|
|
98
|
-
public readonly passwordHash: string
|
|
99
|
-
) {}
|
|
100
|
-
}
|
|
101
|
-
`);
|
|
102
|
-
writeFile(root, "src/domain/repositories/user.repository.interface.ts", `
|
|
103
|
-
import { User } from "../entities/user.entity";
|
|
104
|
-
|
|
105
|
-
export interface IUserRepository {
|
|
106
|
-
save(user: User): Promise<User>;
|
|
107
|
-
findByEmail(email: string): Promise<User | null>;
|
|
108
|
-
findById(id: string): Promise<User | null>;
|
|
109
|
-
}
|
|
110
|
-
`);
|
|
111
|
-
// 2. Application (Application Business Rules / Use Cases)
|
|
112
|
-
writeFile(root, "src/application/use-cases/create-user.use-case.ts", `
|
|
113
|
-
import { User } from "../../domain/entities/user.entity";
|
|
114
|
-
import { IUserRepository } from "../../domain/repositories/user.repository.interface";
|
|
115
|
-
|
|
116
|
-
export class CreateUserUseCase {
|
|
117
|
-
constructor(private userRepository: IUserRepository) {}
|
|
118
|
-
|
|
119
|
-
async execute(name: string, email: string, passwordHash: string): Promise<User> {
|
|
120
|
-
const existing = await this.userRepository.findByEmail(email);
|
|
121
|
-
if (existing) throw new Error("User already exists");
|
|
122
|
-
|
|
123
|
-
const user = new User(Date.now().toString(), name, email, passwordHash);
|
|
124
|
-
return await this.userRepository.save(user);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
`);
|
|
128
|
-
// 3. Interface Adapters (Controllers, Presenters)
|
|
129
|
-
if (options.framework === "express") {
|
|
130
|
-
writeFile(root, "src/interface-adapters/controllers/user.controller.ts", `
|
|
131
|
-
import { Request, Response } from "express";
|
|
132
|
-
import { CreateUserUseCase } from "../../application/use-cases/create-user.use-case";
|
|
133
|
-
|
|
134
|
-
export class UserController {
|
|
135
|
-
constructor(private createUserUseCase: CreateUserUseCase) {}
|
|
136
|
-
|
|
137
|
-
async create(req: Request, res: Response) {
|
|
138
|
-
try {
|
|
139
|
-
const { name, email, password } = req.body;
|
|
140
|
-
const user = await this.createUserUseCase.execute(name, email, password);
|
|
141
|
-
res.status(201).json(user);
|
|
142
|
-
} catch (e: any) {
|
|
143
|
-
res.status(400).json({ error: e.message });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
`);
|
|
148
|
-
}
|
|
149
|
-
// 4. Infrastructure (Frameworks, Drivers)
|
|
150
|
-
writeFile(root, "src/infrastructure/repositories/in-memory-user.repository.ts", `
|
|
151
|
-
import { User } from "../../domain/entities/user.entity";
|
|
152
|
-
import { IUserRepository } from "../../domain/repositories/user.repository.interface";
|
|
153
|
-
|
|
154
|
-
export class InMemoryUserRepository implements IUserRepository {
|
|
155
|
-
private users: User[] = [];
|
|
156
|
-
async save(user: User): Promise<User> {
|
|
157
|
-
this.users.push(user);
|
|
158
|
-
return user;
|
|
159
|
-
}
|
|
160
|
-
async findByEmail(email: string): Promise<User | null> {
|
|
161
|
-
return this.users.find(u => u.email === email) || null;
|
|
162
|
-
}
|
|
163
|
-
async findById(id: string): Promise<User | null> {
|
|
164
|
-
return this.users.find(u => u.id === id) || null;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
`);
|
|
168
|
-
// Main Entry
|
|
169
|
-
if (options.framework === "express") {
|
|
170
|
-
writeFile(root, "src/main.ts", `
|
|
171
|
-
import express from "express";
|
|
172
|
-
import { UserController } from "./interface-adapters/controllers/user.controller";
|
|
173
|
-
import { CreateUserUseCase } from "./application/use-cases/create-user.use-case";
|
|
174
|
-
import { InMemoryUserRepository } from "./infrastructure/repositories/in-memory-user.repository";
|
|
175
|
-
|
|
176
|
-
const app = express();
|
|
177
|
-
app.use(express.json());
|
|
178
|
-
|
|
179
|
-
// Dependency Injection Composition Root
|
|
180
|
-
const userRepo = new InMemoryUserRepository();
|
|
181
|
-
const createUserUseCase = new CreateUserUseCase(userRepo);
|
|
182
|
-
const userController = new UserController(createUserUseCase);
|
|
183
|
-
|
|
184
|
-
app.post("/users", (req, res) => userController.create(req, res));
|
|
185
|
-
|
|
186
|
-
app.listen(3000, () => console.log("š Server running on PORT 3000 (Clean Architecture)"));
|
|
187
|
-
`);
|
|
188
|
-
}
|
|
189
|
-
else if (options.framework === "nestjs") {
|
|
190
|
-
// NestJS needs modules
|
|
191
|
-
writeFile(root, "src/app.module.ts", `
|
|
192
|
-
import { Module } from '@nestjs/common';
|
|
193
|
-
import { UserController } from './interface-adapters/controllers/user.controller';
|
|
194
|
-
import { UserService } from './application/services/user.service'; // NestJS prefers Services over generic UseCases usually, but we stick to clean
|
|
195
|
-
import { InMemoryUserRepository } from './infrastructure/repositories/in-memory-user.repository';
|
|
196
|
-
|
|
197
|
-
@Module({
|
|
198
|
-
controllers: [UserController],
|
|
199
|
-
providers: [
|
|
200
|
-
{ provide: 'IUserRepository', useClass: InMemoryUserRepository },
|
|
201
|
-
UserService
|
|
202
|
-
],
|
|
203
|
-
})
|
|
204
|
-
export class AppModule {}
|
|
205
|
-
`);
|
|
206
|
-
writeFile(root, "src/main.ts", `
|
|
207
|
-
import { NestFactory } from '@nestjs/core';
|
|
208
|
-
import { AppModule } from './app.module';
|
|
209
|
-
|
|
210
|
-
async function bootstrap() {
|
|
211
|
-
const app = await NestFactory.create(AppModule);
|
|
212
|
-
await app.listen(3000);
|
|
213
|
-
console.log("š NestJS Server with Clean Architecture running on 3000");
|
|
214
|
-
}
|
|
215
|
-
bootstrap();
|
|
216
|
-
`);
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
const generateGoStandard = (root, options) => {
|
|
220
|
-
// Standard Go Layout (Internal/Pkg)
|
|
221
|
-
// Domain
|
|
222
|
-
writeFile(root, "internal/core/domain/user.go", `
|
|
223
|
-
package domain
|
|
224
|
-
|
|
225
|
-
type User struct {
|
|
226
|
-
ID string \`json:"id"\`
|
|
227
|
-
Name string \`json:"name"\`
|
|
228
|
-
Email string \`json:"email"\`
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
type UserRepository interface {
|
|
232
|
-
Save(user *User) error
|
|
233
|
-
GetByEmail(email string) (*User, error)
|
|
234
|
-
}
|
|
235
|
-
`);
|
|
236
|
-
// Port/Service
|
|
237
|
-
writeFile(root, "internal/core/services/user_service.go", `
|
|
238
|
-
package services
|
|
239
|
-
import (
|
|
240
|
-
"errors"
|
|
241
|
-
"${options.projectName}/internal/core/domain"
|
|
242
|
-
"time"
|
|
243
|
-
"fmt"
|
|
244
|
-
)
|
|
245
|
-
|
|
246
|
-
type UserService struct {
|
|
247
|
-
repo domain.UserRepository
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
func NewUserService(repo domain.UserRepository) *UserService {
|
|
251
|
-
return &UserService{repo: repo}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
func (s *UserService) Create(name, email string) (*domain.User, error) {
|
|
255
|
-
existing, _ := s.repo.GetByEmail(email)
|
|
256
|
-
if existing != nil {
|
|
257
|
-
return nil, errors.New("user already exists")
|
|
258
|
-
}
|
|
259
|
-
user := &domain.User{
|
|
260
|
-
ID: fmt.Sprintf("%d", time.Now().Unix()),
|
|
261
|
-
Name: name,
|
|
262
|
-
Email: email,
|
|
263
|
-
}
|
|
264
|
-
return user, s.repo.Save(user)
|
|
265
|
-
}
|
|
266
|
-
`);
|
|
267
|
-
// Adapter
|
|
268
|
-
writeFile(root, "internal/adapters/repository/memory_repo.go", `
|
|
269
|
-
package repository
|
|
270
|
-
import "${options.projectName}/internal/core/domain"
|
|
271
|
-
|
|
272
|
-
type MemoryRepo struct {
|
|
273
|
-
users []*domain.User
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
func NewMemoryRepo() *MemoryRepo {
|
|
277
|
-
return &MemoryRepo{users: []*domain.User{}}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
func (m *MemoryRepo) Save(user *domain.User) error {
|
|
281
|
-
m.users = append(m.users, user)
|
|
282
|
-
return nil
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
func (m *MemoryRepo) GetByEmail(email string) (*domain.User, error) {
|
|
286
|
-
for _, u := range m.users {
|
|
287
|
-
if u.Email == email { return u, nil }
|
|
288
|
-
}
|
|
289
|
-
return nil, nil
|
|
290
|
-
}
|
|
291
|
-
`);
|
|
292
|
-
// Main
|
|
293
|
-
if (options.framework === "gin") {
|
|
294
|
-
writeFile(root, "cmd/server/main.go", `
|
|
295
|
-
package main
|
|
296
|
-
import (
|
|
297
|
-
"github.com/gin-gonic/gin"
|
|
298
|
-
"${options.projectName}/internal/adapters/repository"
|
|
299
|
-
"${options.projectName}/internal/core/services"
|
|
300
|
-
"${options.projectName}/internal/core/domain"
|
|
301
|
-
"net/http"
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
func main() {
|
|
305
|
-
repo := repository.NewMemoryRepo()
|
|
306
|
-
svc := services.NewUserService(repo)
|
|
307
|
-
|
|
308
|
-
r := gin.Default()
|
|
309
|
-
r.POST("/users", func(c *gin.Context) {
|
|
310
|
-
var req domain.User
|
|
311
|
-
if err := c.ShouldBindJSON(&req); err != nil {
|
|
312
|
-
c.JSON(400, gin.H{"error": err.Error()})
|
|
313
|
-
return
|
|
314
|
-
}
|
|
315
|
-
user, err := svc.Create(req.Name, req.Email)
|
|
316
|
-
if err != nil {
|
|
317
|
-
c.JSON(400, gin.H{"error": err.Error()})
|
|
318
|
-
return
|
|
319
|
-
}
|
|
320
|
-
c.JSON(201, user)
|
|
321
|
-
})
|
|
322
|
-
r.Run(":8080")
|
|
323
|
-
}
|
|
324
|
-
`);
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
const generatePythonStructure = (root, options) => {
|
|
328
|
-
// Python tends to be slightly flatter, but we can do Clean
|
|
329
|
-
const init = "";
|
|
330
|
-
if (options.framework === "django") {
|
|
331
|
-
writeFile(root, "manage.py", "# Django boilerplate management script");
|
|
332
|
-
writeFile(root, `${options.projectName}/settings.py`, "# Django Settings");
|
|
333
|
-
writeFile(root, `${options.projectName}/urls.py`, "# Main URLs");
|
|
334
|
-
// Use DDD-like apps
|
|
335
|
-
const appPath = "apps/users";
|
|
336
|
-
writeFile(root, `${appPath}/__init__.py`, init);
|
|
337
|
-
writeFile(root, `${appPath}/models.py`, `
|
|
338
|
-
from django.db import models
|
|
339
|
-
|
|
340
|
-
class User(models.Model):
|
|
341
|
-
name = models.CharField(max_length=255)
|
|
342
|
-
email = models.EmailField(unique=True)
|
|
343
|
-
`);
|
|
344
|
-
writeFile(root, `${appPath}/services.py`, `
|
|
345
|
-
from .models import User
|
|
346
|
-
|
|
347
|
-
class UserService:
|
|
348
|
-
@staticmethod
|
|
349
|
-
def create_user(name: str, email: str) -> User:
|
|
350
|
-
if User.objects.filter(email=email).exists():
|
|
351
|
-
raise ValueError("User exists")
|
|
352
|
-
return User.objects.create(name=name, email=email)
|
|
353
|
-
`);
|
|
354
|
-
writeFile(root, `${appPath}/views.py`, `
|
|
355
|
-
from rest_framework.views import APIView
|
|
356
|
-
from rest_framework.response import Response
|
|
357
|
-
from .services import UserService
|
|
358
|
-
|
|
359
|
-
class UserView(APIView):
|
|
360
|
-
def post(self, request):
|
|
361
|
-
try:
|
|
362
|
-
user = UserService.create_user(request.data['name'], request.data['email'])
|
|
363
|
-
return Response({"id": user.id, "email": user.email})
|
|
364
|
-
except Exception as e:
|
|
365
|
-
return Response({"error": str(e)}, status=400)
|
|
366
|
-
`);
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
// Flask Hexagonal
|
|
370
|
-
writeFile(root, "app/__init__.py", init);
|
|
371
|
-
// Domain
|
|
372
|
-
writeFile(root, "app/core/domain/user.py", `
|
|
373
|
-
from dataclasses import dataclass
|
|
374
|
-
@dataclass
|
|
375
|
-
class User:
|
|
376
|
-
id: str
|
|
377
|
-
name: str
|
|
378
|
-
email: str
|
|
379
|
-
`);
|
|
380
|
-
// Ports
|
|
381
|
-
writeFile(root, "app/core/ports/user_repository.py", `
|
|
382
|
-
from abc import ABC, abstractmethod
|
|
383
|
-
from ..domain.user import User
|
|
384
|
-
|
|
385
|
-
class UserRepository(ABC):
|
|
386
|
-
@abstractmethod
|
|
387
|
-
def save(self, user: User): pass
|
|
388
|
-
`);
|
|
389
|
-
// Adapter
|
|
390
|
-
writeFile(root, "app/adapters/db/in_memory_repo.py", `
|
|
391
|
-
from app.core.ports.user_repository import UserRepository
|
|
392
|
-
class InMemoryUserRepo(UserRepository):
|
|
393
|
-
def __init__(self): self.users = []
|
|
394
|
-
def save(self, user): self.users.append(user)
|
|
395
|
-
`);
|
|
396
|
-
// Entry
|
|
397
|
-
writeFile(root, "run.py", `
|
|
398
|
-
from flask import Flask, request, jsonify
|
|
399
|
-
from app.adapters.db.in_memory_repo import InMemoryUserRepo
|
|
400
|
-
from app.core.domain.user import User
|
|
401
|
-
import uuid
|
|
402
|
-
|
|
403
|
-
app = Flask(__name__)
|
|
404
|
-
repo = InMemoryUserRepo()
|
|
405
|
-
|
|
406
|
-
@app.route('/users', methods=['POST'])
|
|
407
|
-
def create_user():
|
|
408
|
-
data = request.json
|
|
409
|
-
user = User(id=str(uuid.uuid4()), name=data['name'], email=data['email'])
|
|
410
|
-
repo.save(user)
|
|
411
|
-
return jsonify(user.__dict__), 201
|
|
412
|
-
|
|
413
|
-
if __name__ == "__main__":
|
|
414
|
-
app.run(debug=True, port=5000)
|
|
415
|
-
`);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
// --- MAIN GENERATOR FUNCTION ---
|
|
419
|
-
async function professionalGenerator(_arch, options) {
|
|
420
|
-
const root = path_1.default.resolve(options.projectName);
|
|
421
|
-
// 1. Scaffold Directories
|
|
422
|
-
if (!fs_1.default.existsSync(root))
|
|
423
|
-
fs_1.default.mkdirSync(root);
|
|
424
|
-
console.log(chalk_1.default.green(`\nš Creating project infrastructure at ${root}...`));
|
|
425
|
-
// 2. Generate Configuration Files (The Backbone)
|
|
426
|
-
if (options.language === "ts" || options.language === "js") {
|
|
427
|
-
writeFile(root, "package.json", getPackageJson(options.projectName, options.framework, options.architecture, options.modules));
|
|
428
|
-
writeFile(root, "tsconfig.json", JSON.stringify({
|
|
429
|
-
compilerOptions: { target: "ES2020", module: "commonjs", outDir: "./dist", rootDir: "./src", strict: true, experimentalDecorators: true, emitDecoratorMetadata: true },
|
|
430
|
-
exclude: ["node_modules", "dist"]
|
|
431
|
-
}, null, 2));
|
|
432
|
-
}
|
|
433
|
-
else if (options.language === "go") {
|
|
434
|
-
writeFile(root, "go.mod", getGoMod(options.projectName, options.framework));
|
|
435
|
-
}
|
|
436
|
-
else if (options.language === "py") {
|
|
437
|
-
writeFile(root, "requirements.txt", getRequirementsTxt(options.framework, options.modules));
|
|
438
|
-
}
|
|
439
|
-
writeFile(root, ".env.example", "PORT=3000\nDB_HOST=localhost\nJWT_SECRET=supersecret");
|
|
440
|
-
writeFile(root, ".gitignore", "node_modules/\ndist/\n.env\n__pycache__/\n*.exe\nvendor/");
|
|
441
|
-
writeFile(root, "README.md", `# ${options.projectName}\nGenerated by ArchForge X\nArchitecture: ${options.architecture}`);
|
|
442
|
-
// 3. Generate Architecture Logic
|
|
443
|
-
console.log(chalk_1.default.blue("šļø Constructing Architecture layers..."));
|
|
444
|
-
if (options.language === "ts" || options.language === "js") {
|
|
445
|
-
generateTsCleanArch(root, options);
|
|
446
|
-
}
|
|
447
|
-
else if (options.language === "go") {
|
|
448
|
-
generateGoStandard(root, options);
|
|
449
|
-
}
|
|
450
|
-
else if (options.language === "py") {
|
|
451
|
-
generatePythonStructure(root, options);
|
|
452
|
-
}
|
|
453
|
-
// 4. Inject Optional Modules (Advanced Integration)
|
|
454
|
-
if (options.modules.includes("docker")) {
|
|
455
|
-
console.log(chalk_1.default.cyan("š³ Containerizing application..."));
|
|
456
|
-
const dockerfileContent = options.language === "go"
|
|
457
|
-
? `FROM golang:1.21-alpine\nWORKDIR /app\nCOPY . .\nRUN go build -o main cmd/server/main.go\nCMD ["./main"]`
|
|
458
|
-
: options.language === "py"
|
|
459
|
-
? `FROM python:3.9-slim\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install -r requirements.txt\nCOPY . .\nCMD ["python", "run.py"]`
|
|
460
|
-
: `FROM node:18-alpine\nWORKDIR /app\nCOPY package*.json .\nRUN npm install\nCOPY . .\nRUN npm run build\nCMD ["npm", "start"]`;
|
|
461
|
-
writeFile(root, "Dockerfile", dockerfileContent);
|
|
462
|
-
writeFile(root, "docker-compose.yml", `
|
|
463
|
-
version: '3.8'
|
|
464
|
-
services:
|
|
465
|
-
app:
|
|
466
|
-
build: .
|
|
467
|
-
ports:
|
|
468
|
-
- "${options.language === 'py' ? '5000:5000' : '3000:3000'}"
|
|
469
|
-
env_file: .env
|
|
470
|
-
${options.modules.includes("db") ? ` db:
|
|
471
|
-
image: postgres:15
|
|
472
|
-
environment:
|
|
473
|
-
POSTGRES_PASSWORD: root
|
|
474
|
-
ports:
|
|
475
|
-
- "5432:5432"` : ''}
|
|
476
|
-
`);
|
|
477
|
-
}
|
|
478
|
-
if (options.modules.includes("ci")) {
|
|
479
|
-
writeFile(root, ".github/workflows/ci.yml", `
|
|
480
|
-
name: CI
|
|
481
|
-
on: [push]
|
|
482
|
-
jobs:
|
|
483
|
-
build:
|
|
484
|
-
runs-on: ubuntu-latest
|
|
485
|
-
steps:
|
|
486
|
-
- uses: actions/checkout@v3
|
|
487
|
-
- name: Test
|
|
488
|
-
run: echo "Running tests..."
|
|
489
|
-
`);
|
|
490
|
-
}
|
|
491
|
-
if (options.modules.includes("auth")) {
|
|
492
|
-
// Add a specialized Auth service file depending on lang
|
|
493
|
-
const authPath = options.language === "go" ? "internal/core/services/auth_service.go"
|
|
494
|
-
: options.language === "py" ? "app/core/services/auth.py"
|
|
495
|
-
: "src/application/services/auth.service.ts";
|
|
496
|
-
writeFile(root, authPath, `
|
|
497
|
-
// JWT Authentication Service Boilerplate
|
|
498
|
-
// TODO: Implement actual signing and validation logic here
|
|
499
|
-
export class AuthService {
|
|
500
|
-
login(u: any) { return "jwt_token_example"; }
|
|
501
|
-
}
|
|
502
|
-
`.replace("export class", options.language === "go" ? "package services\ntype AuthService struct{}" : "class"));
|
|
503
|
-
}
|
|
504
|
-
console.log(chalk_1.default.green.bold(`\nā
Project ${options.projectName} successfully generated!`));
|
|
505
|
-
console.log(chalk_1.default.gray(` Architecture: ${options.architecture.toUpperCase()}`));
|
|
506
|
-
console.log(chalk_1.default.gray(` Language: ${options.language.toUpperCase()}`));
|
|
507
|
-
if (options.modules.length > 0)
|
|
508
|
-
console.log(chalk_1.default.gray(` Modules: ${options.modules.join(", ")}`));
|
|
509
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateBaseFile = generateBaseFile;
|
|
4
|
-
function generateBaseFile(layerName) {
|
|
5
|
-
return `/**
|
|
6
|
-
* Base file for ${layerName} layer
|
|
7
|
-
* Generated by ArchForge X
|
|
8
|
-
*/
|
|
9
|
-
`;
|
|
10
|
-
}
|