archforge-x 1.0.4 ā 1.0.7
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/README.md +51 -155
- package/dist/analyzers/dependency.js +5 -48
- package/dist/api/routes/user.routes.js +18 -0
- package/dist/cli/commands/init-template.js +105 -0
- package/dist/cli/commands/sync.js +11 -3
- package/dist/cli/commands/template-create.js +377 -0
- package/dist/cli/commands/templates.js +152 -0
- package/dist/cli/commands/validate-template.js +179 -0
- package/dist/cli/init.js +74 -0
- package/dist/cli/interactive-init.js +257 -0
- package/dist/cli/interactive.js +53 -82
- package/dist/config/env.schema.js +11 -0
- package/dist/config/index.js +27 -0
- package/dist/core/VersionManifest.js +80 -0
- package/dist/core/architecture/defaults.js +148 -0
- package/dist/core/architecture/parser.js +12 -4
- package/dist/core/architecture/schema.js +2 -2
- package/dist/core/architecture/validator.js +96 -37
- package/dist/core/templates/model.js +3 -0
- package/dist/core/templates/validator.js +163 -0
- package/dist/core/types/user.js +2 -0
- package/dist/discovery/local-registry.js +137 -0
- package/dist/discovery/registry.js +170 -0
- package/dist/discovery/resolver.js +212 -0
- package/dist/generators/base.js +195 -68
- package/dist/generators/generator.js +17 -15
- package/dist/generators/go/gin.js +15 -94
- package/dist/generators/node/express.js +238 -706
- package/dist/generators/node/nestjs.js +76 -677
- package/dist/generators/node/nextjs.js +15 -78
- package/dist/generators/python/django.js +15 -103
- package/dist/generators/python/fastapi.js +17 -98
- package/dist/generators/templates/ci.js +129 -0
- package/dist/generators/templates/docker.js +184 -0
- package/dist/generators/templates/index.js +13 -0
- package/dist/generators/templates/package-versions.js +132 -0
- package/dist/generators/templates/version-validator.js +103 -0
- package/dist/generators/verification/index.js +11 -0
- package/dist/generators/verification/verifier.js +281 -0
- package/dist/index.js +43 -13
- package/dist/infrastructure/cache/cache.interface.js +2 -0
- package/dist/infrastructure/cache/memory.cache.js +26 -0
- package/dist/infrastructure/cache/redis.cache.js +32 -0
- package/dist/infrastructure/database/prisma.js +5 -0
- package/dist/infrastructure/errors/app.error.js +26 -0
- package/dist/infrastructure/logger.js +16 -0
- package/dist/infrastructure/middleware/error.middleware.js +23 -0
- package/dist/interface-adapters/controllers/health.controller.js +29 -0
- package/dist/main.js +27 -0
- package/dist/orchestration/configurator.js +282 -0
- package/dist/orchestration/fetcher.js +90 -0
- package/dist/orchestration/installer.js +155 -0
- package/dist/services/user.service.js +27 -0
- package/dist/utils/git.js +204 -0
- package/dist/utils/package-manager.js +236 -0
- package/dist/validation/compatibility.js +233 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,190 +1,86 @@
|
|
|
1
|
-
# ArchForge X
|
|
1
|
+
# ArchForge X - Enterprise Architecture Engine
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Why This Exists
|
|
6
|
-
|
|
7
|
-
Modern software development often suffers from two primary issues: **setup fatigue** and **architecture drift**. Developers spend hours configuring boilerplate for logging, caching, and database layers, only for the project's architectural boundaries to erode over time as the team grows.
|
|
8
|
-
|
|
9
|
-
ArchForge X solves this by moving architecture from "documentation" to "executable configuration." By defining your project's structure and rules in a central `archforge.yaml`, you ensure that every project starts with production-ready defaults and stays compliant throughout its lifecycle.
|
|
3
|
+
ArchForge X is a CLI tool designed to turn software architecture into executable code. It enables teams to scaffold, validate, audit, and visualize project architecture using a configuration-driven approach.
|
|
10
4
|
|
|
11
5
|
## Key Features
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
## Supported Capabilities
|
|
20
|
-
|
|
21
|
-
- **Architectures**: Clean Architecture (DDD), Layered Architecture, MVC.
|
|
22
|
-
- **Frameworks**: NestJS, Express, FastAPI, Django, Go Gin, Next.js.
|
|
23
|
-
- **ORMs & Databases**: Prisma, SQLAlchemy, GORM, PostgreSQL, MySQL, SQLite, MongoDB.
|
|
24
|
-
- **DevOps**: Automated Dockerfile and Docker Compose generation, GitHub Actions CI/CD workflows.
|
|
7
|
+
* **Policy-Driven Scaffolding**: Generate production-ready projects (Clean Architecture, DDD, Hexagonal) for Node.js (Express, NestJS).
|
|
8
|
+
* **Strict Validation**: Enforce dependency rules between layers (e.g., Domain cannot import Infrastructure).
|
|
9
|
+
* **Automated Audits**: Scan codebase for architectural violations and receive fix suggestions.
|
|
10
|
+
* **Visualization**: Generate SVG dependency graphs to visualize project structure.
|
|
11
|
+
* **Configuration as Code**: Define architecture in `archforge.yaml` or `archforge.json`.
|
|
25
12
|
|
|
26
13
|
## Installation
|
|
27
14
|
|
|
28
|
-
Install ArchForge X globally via npm:
|
|
29
|
-
|
|
30
15
|
```bash
|
|
31
|
-
npm install -g archforge
|
|
16
|
+
npm install -g archforge-x
|
|
32
17
|
```
|
|
33
18
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
### init
|
|
19
|
+
## Quick Start
|
|
37
20
|
|
|
38
|
-
|
|
21
|
+
### 1. Initialize a Project
|
|
22
|
+
Start the interactive wizard to create a new project or generate a config for an existing one.
|
|
39
23
|
|
|
40
24
|
```bash
|
|
41
25
|
archforge init
|
|
42
26
|
```
|
|
43
27
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **Framework**: Select your preferred backend or frontend framework.
|
|
47
|
-
- **ORM & Database**: Configure your data persistence layer.
|
|
48
|
-
- **Optional Modules**: Add Docker support, CI/CD workflows, Caching (Redis), and more.
|
|
49
|
-
|
|
50
|
-
### sync
|
|
51
|
-
|
|
52
|
-
The `sync` command re-applies the architectural rules defined in `archforge.yaml` to your project.
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
archforge sync
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
- **What it changes**: Updates configuration files, architecture guardrails (e.g., ESLint rules), and missing infrastructure layers.
|
|
59
|
-
- **What it never changes**: Your business logic, use cases, or custom implementation files.
|
|
60
|
-
|
|
61
|
-
### validate
|
|
62
|
-
|
|
63
|
-
The `validate` command checks your project against the rules defined in `archforge.yaml`.
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
archforge validate
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
- **Validation**: Checks naming conventions, directory structure, and restricted import paths.
|
|
70
|
-
- **Usage**: Used locally during development or in CI pipelines to prevent architectural violations.
|
|
71
|
-
- **Behavior**: Returns a non-zero exit code on failure, making it ideal for blocking invalid PRs.
|
|
72
|
-
|
|
73
|
-
### upgrade
|
|
74
|
-
|
|
75
|
-
The `upgrade` command adds new production-grade features to an existing ArchForge project.
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
archforge upgrade
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
- **Purpose**: Safely introduces enhancements like new logging providers or health check endpoints without breaking existing code.
|
|
82
|
-
|
|
83
|
-
### generate
|
|
84
|
-
|
|
85
|
-
The `generate` command creates specific architectural components within an existing project.
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
archforge generate module user
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
- **Usage**: Use this to quickly add new features, layers, or modules that follow the project's established patterns.
|
|
92
|
-
- **Alias**: `create`
|
|
93
|
-
|
|
94
|
-
### graph
|
|
95
|
-
|
|
96
|
-
The `graph` command generates a visual representation of your project's architecture.
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
archforge graph
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
- **Output**: Generates an `architecture-graph.svg` file showing the relationships and dependencies between your project's layers.
|
|
103
|
-
- **Alias**: `visualize`
|
|
104
|
-
|
|
105
|
-
## Configuration (archforge.yaml)
|
|
106
|
-
|
|
107
|
-
The `archforge.yaml` file is the single source of truth for your project's architecture. It defines the structure, naming conventions, and enforcement policies.
|
|
28
|
+
### 2. Define Your Architecture
|
|
29
|
+
Create an `archforge.yaml` file to define your layers and rules.
|
|
108
30
|
|
|
109
31
|
```yaml
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
path: src/infrastructure
|
|
126
|
-
canImport: [domain, application]
|
|
127
|
-
- name: presentation
|
|
128
|
-
path: src/presentation
|
|
129
|
-
canImport: [domain, application]
|
|
130
|
-
|
|
131
|
-
naming:
|
|
132
|
-
controllers: "{name}.controller.ts"
|
|
133
|
-
useCases: "{name}.use-case.ts"
|
|
134
|
-
repositories: "{name}.repository.ts"
|
|
135
|
-
|
|
136
|
-
enforcement:
|
|
137
|
-
strictImports: true
|
|
138
|
-
namingConvention: pascalCase
|
|
32
|
+
version: "1.0"
|
|
33
|
+
project:
|
|
34
|
+
name: "my-service"
|
|
35
|
+
layers:
|
|
36
|
+
- name: "domain"
|
|
37
|
+
path: "src/domain"
|
|
38
|
+
canImport: []
|
|
39
|
+
- name: "application"
|
|
40
|
+
path: "src/application"
|
|
41
|
+
canImport: ["domain"]
|
|
42
|
+
- name: "infrastructure"
|
|
43
|
+
path: "src/infrastructure"
|
|
44
|
+
canImport: ["domain", "application"]
|
|
45
|
+
rules:
|
|
46
|
+
enforceLayerBoundaries: true
|
|
139
47
|
```
|
|
140
48
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
ArchForge X enforces rules through a combination of static analysis and framework-specific configurations:
|
|
144
|
-
|
|
145
|
-
1. **Local Enforcement**: During `sync`, ArchForge configures tools like ESLint with `import/no-restricted-paths` to provide real-time feedback in your IDE.
|
|
146
|
-
2. **CI Verification**: Running `archforge validate` in your CI pipeline ensures that no code violating the architecture is merged.
|
|
147
|
-
3. **Fixing Violations**: If a violation is detected (e.g., a Domain entity importing from Infrastructure), the CLI will provide a detailed report pointing to the offending file and rule.
|
|
148
|
-
|
|
149
|
-
## Running the Project
|
|
150
|
-
|
|
151
|
-
### Local Development
|
|
49
|
+
### 3. Validate Your Code
|
|
50
|
+
Check if your code adheres to the defined architecture.
|
|
152
51
|
|
|
153
52
|
```bash
|
|
154
|
-
|
|
155
|
-
npm install
|
|
156
|
-
|
|
157
|
-
# Start in development mode with hot-reload
|
|
158
|
-
npm run start:dev
|
|
53
|
+
archforge validate
|
|
159
54
|
```
|
|
160
55
|
|
|
161
|
-
###
|
|
56
|
+
### 4. Visualize Dependencies
|
|
57
|
+
Generate a graph of your project's architecture.
|
|
162
58
|
|
|
163
59
|
```bash
|
|
164
|
-
|
|
165
|
-
docker-compose up --build
|
|
60
|
+
archforge graph --output architecture.svg
|
|
166
61
|
```
|
|
167
62
|
|
|
168
|
-
|
|
63
|
+
## Documentation
|
|
169
64
|
|
|
170
|
-
|
|
171
|
-
- `PORT`: Server port (default: 3000)
|
|
172
|
-
- `DATABASE_URL`: Connection string for your database.
|
|
173
|
-
- `REDIS_URL`: Connection string for Redis caching.
|
|
65
|
+
For a deep dive into defining rules and best practices, check out the [Rules & Validation Guide](docs/RULES_GUIDE.md).
|
|
174
66
|
|
|
175
|
-
##
|
|
67
|
+
## CLI Commands
|
|
176
68
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
69
|
+
| Command | Description |
|
|
70
|
+
| :--- | :--- |
|
|
71
|
+
| `archforge init` | Interactive wizard to setup a project. |
|
|
72
|
+
| `archforge generate` | Scaffold a new project based on the config. |
|
|
73
|
+
| `archforge validate` | Check for architectural violations. |
|
|
74
|
+
| `archforge audit` | Deep scan with auto-fix suggestions. |
|
|
75
|
+
| `archforge graph` | Generate a visual dependency graph (SVG). |
|
|
76
|
+
| `archforge sync` | Sync project structure with the config. |
|
|
181
77
|
|
|
182
|
-
##
|
|
78
|
+
## Supported Frameworks
|
|
183
79
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
80
|
+
Currently, ArchForge X specializes in TypeScript backends:
|
|
81
|
+
* Express.js (Clean Architecture / DDD)
|
|
82
|
+
* NestJS (Modular / Hexagonal)
|
|
187
83
|
|
|
188
|
-
##
|
|
84
|
+
## License
|
|
189
85
|
|
|
190
|
-
|
|
86
|
+
MIT
|
|
@@ -27,36 +27,6 @@ const parseImportsTS = (content, filePath) => {
|
|
|
27
27
|
});
|
|
28
28
|
return imports;
|
|
29
29
|
};
|
|
30
|
-
const parseImportsPython = (content) => {
|
|
31
|
-
const imports = [];
|
|
32
|
-
const lines = content.split("\n");
|
|
33
|
-
for (const line of lines) {
|
|
34
|
-
const trimmed = line.trim();
|
|
35
|
-
const fromMatch = trimmed.match(/^from\s+([\w\.]+)\s+import/);
|
|
36
|
-
if (fromMatch)
|
|
37
|
-
imports.push(fromMatch[1].replace(/\./g, "/"));
|
|
38
|
-
const importMatch = trimmed.match(/^import\s+([\w\.]+)/);
|
|
39
|
-
if (importMatch)
|
|
40
|
-
imports.push(importMatch[1].replace(/\./g, "/"));
|
|
41
|
-
}
|
|
42
|
-
return imports;
|
|
43
|
-
};
|
|
44
|
-
const parseImportsGo = (content) => {
|
|
45
|
-
const imports = [];
|
|
46
|
-
const singleMatch = content.matchAll(/import\s+"(.+)"/g);
|
|
47
|
-
for (const m of singleMatch)
|
|
48
|
-
imports.push(m[1]);
|
|
49
|
-
const multiBlock = content.match(/import\s+\(([\s\S]*?)\)/);
|
|
50
|
-
if (multiBlock) {
|
|
51
|
-
const lines = multiBlock[1].split("\n");
|
|
52
|
-
for (const line of lines) {
|
|
53
|
-
const clean = line.trim().replace(/"/g, "");
|
|
54
|
-
if (clean)
|
|
55
|
-
imports.push(clean);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return imports;
|
|
59
|
-
};
|
|
60
30
|
// --- CORE ANALYZER ---
|
|
61
31
|
function analyzeDependencies(arch, options = {}) {
|
|
62
32
|
const violations = [];
|
|
@@ -96,15 +66,15 @@ function analyzeDependencies(arch, options = {}) {
|
|
|
96
66
|
const fullPath = path_1.default.join(absoluteFolderPath, entry);
|
|
97
67
|
const stat = fs_extra_1.default.statSync(fullPath);
|
|
98
68
|
if (stat.isDirectory()) {
|
|
99
|
-
if (["node_modules", "
|
|
69
|
+
if (["node_modules", ".git", "dist"].includes(entry))
|
|
100
70
|
continue;
|
|
101
71
|
scanFolder(fullPath);
|
|
102
72
|
}
|
|
103
73
|
else if (stat.isFile()) {
|
|
104
|
-
if (options.ignoreTests && (entry.includes(".spec") || entry.includes("
|
|
74
|
+
if (options.ignoreTests && (entry.includes(".spec") || entry.includes(".test")))
|
|
105
75
|
continue;
|
|
106
76
|
const ext = path_1.default.extname(entry);
|
|
107
|
-
if ([".ts", ".js", ".
|
|
77
|
+
if ([".ts", ".js", ".tsx", ".jsx"].includes(ext)) {
|
|
108
78
|
checkFileImports(fullPath, ext);
|
|
109
79
|
}
|
|
110
80
|
}
|
|
@@ -118,15 +88,12 @@ function analyzeDependencies(arch, options = {}) {
|
|
|
118
88
|
let imports = [];
|
|
119
89
|
if ([".ts", ".tsx", ".js", ".jsx"].includes(ext))
|
|
120
90
|
imports = parseImportsTS(content, filePath);
|
|
121
|
-
else if (ext === ".py")
|
|
122
|
-
imports = parseImportsPython(content);
|
|
123
|
-
else if (ext === ".go")
|
|
124
|
-
imports = parseImportsGo(content);
|
|
125
91
|
for (const importStr of imports) {
|
|
126
92
|
const importedLayer = resolveImportedLayer(filePath, importStr);
|
|
127
93
|
if (!importedLayer || importedLayer.name === currentLayer.name)
|
|
128
94
|
continue;
|
|
129
|
-
|
|
95
|
+
const canImport = currentLayer.canImport || currentLayer.allowedImports || [];
|
|
96
|
+
if (!canImport.includes(importedLayer.name)) {
|
|
130
97
|
violations.push({
|
|
131
98
|
file: path_1.default.relative(projectRoot, filePath),
|
|
132
99
|
fromLayer: currentLayer.name,
|
|
@@ -136,16 +103,6 @@ function analyzeDependencies(arch, options = {}) {
|
|
|
136
103
|
severity: "error"
|
|
137
104
|
});
|
|
138
105
|
}
|
|
139
|
-
if (currentLayer.allowedImports && !currentLayer.allowedImports.includes(importedLayer.name)) {
|
|
140
|
-
violations.push({
|
|
141
|
-
file: path_1.default.relative(projectRoot, filePath),
|
|
142
|
-
fromLayer: currentLayer.name,
|
|
143
|
-
importedLayer: importedLayer.name,
|
|
144
|
-
importPath: importStr,
|
|
145
|
-
type: "allowed",
|
|
146
|
-
severity: "warning"
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
106
|
}
|
|
150
107
|
}
|
|
151
108
|
arch.layers.forEach((layer) => scanFolder(layer.path));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const express_1 = require("express");
|
|
4
|
+
const user_service_1 = require("../../services/user.service");
|
|
5
|
+
const memory_cache_1 = require("../../infrastructure/cache/memory.cache");
|
|
6
|
+
const http_status_codes_1 = require("http-status-codes");
|
|
7
|
+
const router = (0, express_1.Router)();
|
|
8
|
+
const cache = new memory_cache_1.MemoryCache();
|
|
9
|
+
const userService = new user_service_1.UserService(cache);
|
|
10
|
+
router.post("/", async (req, res) => {
|
|
11
|
+
const user = await userService.create(req.body.name, req.body.email);
|
|
12
|
+
res.status(http_status_codes_1.StatusCodes.CREATED).json(user);
|
|
13
|
+
});
|
|
14
|
+
router.get("/:id", async (req, res) => {
|
|
15
|
+
const user = await userService.getById(req.params.id);
|
|
16
|
+
res.status(http_status_codes_1.StatusCodes.OK).json(user);
|
|
17
|
+
});
|
|
18
|
+
exports.default = router;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/cli/commands/init-template.ts
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.initTemplateCommand = initTemplateCommand;
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const resolver_1 = require("../../discovery/resolver");
|
|
11
|
+
const fetcher_1 = require("../../orchestration/fetcher");
|
|
12
|
+
const configurator_1 = require("../../orchestration/configurator");
|
|
13
|
+
const installer_1 = require("../../orchestration/installer");
|
|
14
|
+
const compatibility_1 = require("../../validation/compatibility");
|
|
15
|
+
async function initTemplateCommand(options) {
|
|
16
|
+
try {
|
|
17
|
+
console.log(chalk_1.default.blue.bold('\nš ArchForge X - Template Initialization\n'));
|
|
18
|
+
// Step 1: Resolve template
|
|
19
|
+
console.log(chalk_1.default.cyan('š Step 1: Resolving template...'));
|
|
20
|
+
const resolver = new resolver_1.TemplateResolver();
|
|
21
|
+
const resolved = await resolver.resolve({
|
|
22
|
+
language: options.language,
|
|
23
|
+
framework: options.framework,
|
|
24
|
+
architecture: options.architecture,
|
|
25
|
+
orm: options.orm,
|
|
26
|
+
database: options.database,
|
|
27
|
+
templateId: options.templateId,
|
|
28
|
+
templateUrl: options.templateUrl,
|
|
29
|
+
version: options.version,
|
|
30
|
+
});
|
|
31
|
+
// Step 2: Fetch template
|
|
32
|
+
console.log(chalk_1.default.cyan('\nš„ Step 2: Fetching template...'));
|
|
33
|
+
const fetcher = new fetcher_1.TemplateFetcher();
|
|
34
|
+
const { templatePath, metadata } = await fetcher.fetch(resolved, {
|
|
35
|
+
cache: true,
|
|
36
|
+
shallow: true,
|
|
37
|
+
});
|
|
38
|
+
// Step 3: Check compatibility
|
|
39
|
+
console.log(chalk_1.default.cyan('\nš Step 3: Checking compatibility...'));
|
|
40
|
+
const checker = new compatibility_1.CompatibilityChecker();
|
|
41
|
+
const compatibility = await checker.checkCompatibility(metadata, { strict: false });
|
|
42
|
+
checker.displayReport(compatibility, metadata);
|
|
43
|
+
if (!compatibility.compatible) {
|
|
44
|
+
console.log(chalk_1.default.red('\nā Compatibility check failed. Use --skip-compatibility to proceed anyway.'));
|
|
45
|
+
if (!options.skipInstall) {
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Step 4: Configure template
|
|
50
|
+
console.log(chalk_1.default.cyan('\nš§ Step 4: Configuring template...'));
|
|
51
|
+
const configurator = new configurator_1.TemplateConfigurator();
|
|
52
|
+
const projectName = options.projectName || 'my-project';
|
|
53
|
+
const projectConfig = {
|
|
54
|
+
projectName,
|
|
55
|
+
language: options.language,
|
|
56
|
+
framework: options.framework,
|
|
57
|
+
architecture: options.architecture,
|
|
58
|
+
orm: options.orm,
|
|
59
|
+
database: options.database,
|
|
60
|
+
modules: options.modules,
|
|
61
|
+
authorName: options.authorName,
|
|
62
|
+
authorEmail: options.authorEmail,
|
|
63
|
+
license: options.license,
|
|
64
|
+
};
|
|
65
|
+
const { configuredPath } = await configurator.configure(templatePath, projectConfig, path_1.default.resolve(projectName));
|
|
66
|
+
// Step 5: Install dependencies
|
|
67
|
+
if (!options.skipInstall) {
|
|
68
|
+
console.log(chalk_1.default.cyan('\nš¦ Step 5: Installing dependencies...'));
|
|
69
|
+
const installer = new installer_1.DependencyInstaller();
|
|
70
|
+
const installResult = await installer.install(configuredPath, metadata, {
|
|
71
|
+
packageManager: options.packageManager,
|
|
72
|
+
production: false,
|
|
73
|
+
skipPostInstall: options.skipPostInstall,
|
|
74
|
+
});
|
|
75
|
+
if (!installResult.success) {
|
|
76
|
+
console.log(chalk_1.default.yellow('\nā ļø Dependency installation had issues. You may need to install manually.'));
|
|
77
|
+
}
|
|
78
|
+
// Display post-install instructions
|
|
79
|
+
installer.displayInstructions(metadata);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.log(chalk_1.default.yellow('\nāļø Skipping dependency installation'));
|
|
83
|
+
}
|
|
84
|
+
// Success message
|
|
85
|
+
console.log(chalk_1.default.green.bold(`\nā
Project "${projectName}" created successfully!`));
|
|
86
|
+
console.log(chalk_1.default.blue('\nš Location:'), path_1.default.resolve(configuredPath));
|
|
87
|
+
console.log(chalk_1.default.blue('\nš Next steps:'));
|
|
88
|
+
console.log(chalk_1.default.gray(` cd ${projectName}`));
|
|
89
|
+
if (options.skipInstall) {
|
|
90
|
+
console.log(chalk_1.default.gray(` npm install`));
|
|
91
|
+
}
|
|
92
|
+
// Get start command from template or use default
|
|
93
|
+
const startCommand = metadata.postInstall?.scripts?.find((s) => s.includes('start')) || 'npm run start:dev';
|
|
94
|
+
console.log(chalk_1.default.gray(` ${startCommand}`));
|
|
95
|
+
console.log(chalk_1.default.blue('\nš” Tip: Run "archforge validate" to check your project architecture\n'));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error(chalk_1.default.red.bold('\nā Initialization failed:'));
|
|
99
|
+
console.error(chalk_1.default.red(error.message));
|
|
100
|
+
if (error.stack) {
|
|
101
|
+
console.error(chalk_1.default.gray(error.stack));
|
|
102
|
+
}
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -9,14 +9,22 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
9
9
|
async function syncCommand() {
|
|
10
10
|
const projectRoot = process.cwd();
|
|
11
11
|
const validator = new validator_1.ArchitectureValidator();
|
|
12
|
-
console.log(chalk_1.default.blue("š Syncing architecture with
|
|
12
|
+
console.log(chalk_1.default.blue("š Syncing architecture with architecture-rules.json..."));
|
|
13
13
|
const result = await validator.validate(projectRoot);
|
|
14
|
+
if (result.warnings.length > 0) {
|
|
15
|
+
console.log(chalk_1.default.yellow("\nā ļø Warnings:"));
|
|
16
|
+
result.warnings.forEach(warn => console.log(chalk_1.default.yellow(` - ${warn}`)));
|
|
17
|
+
}
|
|
14
18
|
if (result.success) {
|
|
15
|
-
console.log(chalk_1.default.green.bold("ā
Architecture is valid and in sync!"));
|
|
19
|
+
console.log(chalk_1.default.green.bold("\nā
Architecture is valid and in sync!"));
|
|
20
|
+
if (result.warnings.length > 0) {
|
|
21
|
+
console.log(chalk_1.default.gray(" (Some warnings were found but do not block sync)"));
|
|
22
|
+
}
|
|
16
23
|
}
|
|
17
24
|
else {
|
|
18
|
-
console.log(chalk_1.default.red.bold("ā Architecture violations found:"));
|
|
25
|
+
console.log(chalk_1.default.red.bold("\nā Architecture violations found:"));
|
|
19
26
|
result.errors.forEach(err => console.log(chalk_1.default.red(` - ${err}`)));
|
|
27
|
+
console.log(chalk_1.default.yellow("\nš” Tip: Fix these violations to ensure architectural compliance."));
|
|
20
28
|
process.exit(1);
|
|
21
29
|
}
|
|
22
30
|
}
|