@aifabrix/builder 2.0.8 → 2.1.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/lib/app-config.js +2 -0
- package/lib/app-readme.js +107 -0
- package/lib/utils/health-check.js +3 -3
- package/package.json +1 -1
- package/templates/applications/README.md.hbs +70 -0
package/lib/app-config.js
CHANGED
|
@@ -13,6 +13,7 @@ const path = require('path');
|
|
|
13
13
|
const chalk = require('chalk');
|
|
14
14
|
const { generateVariablesYaml, generateEnvTemplate, generateRbacYaml } = require('./templates');
|
|
15
15
|
const { generateEnvTemplate: generateEnvTemplateFromReader } = require('./env-reader');
|
|
16
|
+
const { generateReadmeMdFile } = require('./app-readme');
|
|
16
17
|
const logger = require('./utils/logger');
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -146,6 +147,7 @@ async function generateConfigFiles(appPath, appName, config, existingEnv) {
|
|
|
146
147
|
await generateEnvTemplateFile(appPath, config, existingEnv);
|
|
147
148
|
await generateRbacYamlFile(appPath, appName, config);
|
|
148
149
|
await generateDeployJsonFile(appPath, appName, config);
|
|
150
|
+
await generateReadmeMdFile(appPath, appName, config);
|
|
149
151
|
} catch (error) {
|
|
150
152
|
throw new Error(`Failed to generate configuration files: ${error.message}`);
|
|
151
153
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application README.md Generation
|
|
3
|
+
*
|
|
4
|
+
* Generates README.md files for applications based on configuration
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview README.md generation for AI Fabrix Builder
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs').promises;
|
|
12
|
+
const fsSync = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const handlebars = require('handlebars');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Checks if a file exists
|
|
18
|
+
* @async
|
|
19
|
+
* @param {string} filePath - Path to file
|
|
20
|
+
* @returns {Promise<boolean>} True if file exists
|
|
21
|
+
*/
|
|
22
|
+
async function fileExists(filePath) {
|
|
23
|
+
try {
|
|
24
|
+
await fs.access(filePath);
|
|
25
|
+
return true;
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Formats application name for display (capitalize first letter of each word)
|
|
33
|
+
* @param {string} appName - Application name
|
|
34
|
+
* @returns {string} Formatted display name
|
|
35
|
+
*/
|
|
36
|
+
function formatAppDisplayName(appName) {
|
|
37
|
+
return appName
|
|
38
|
+
.split('-')
|
|
39
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
40
|
+
.join(' ');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Loads and compiles README.md template
|
|
45
|
+
* @returns {Function} Compiled Handlebars template
|
|
46
|
+
* @throws {Error} If template not found
|
|
47
|
+
*/
|
|
48
|
+
function loadReadmeTemplate() {
|
|
49
|
+
const templatePath = path.join(__dirname, '..', 'templates', 'applications', 'README.md.hbs');
|
|
50
|
+
if (!fsSync.existsSync(templatePath)) {
|
|
51
|
+
throw new Error(`README template not found at ${templatePath}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const templateContent = fsSync.readFileSync(templatePath, 'utf8');
|
|
55
|
+
return handlebars.compile(templateContent);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Generates README.md content for an application using Handlebars template
|
|
60
|
+
* @param {string} appName - Application name
|
|
61
|
+
* @param {Object} config - Application configuration
|
|
62
|
+
* @returns {string} README.md content
|
|
63
|
+
*/
|
|
64
|
+
function generateReadmeMd(appName, config) {
|
|
65
|
+
const template = loadReadmeTemplate();
|
|
66
|
+
const displayName = formatAppDisplayName(appName);
|
|
67
|
+
const imageName = `aifabrix/${appName}`;
|
|
68
|
+
const port = config.port || 3000;
|
|
69
|
+
|
|
70
|
+
const context = {
|
|
71
|
+
appName,
|
|
72
|
+
displayName,
|
|
73
|
+
imageName,
|
|
74
|
+
port,
|
|
75
|
+
hasDatabase: config.database || false,
|
|
76
|
+
hasRedis: config.redis || false,
|
|
77
|
+
hasStorage: config.storage || false,
|
|
78
|
+
hasAuthentication: config.authentication || false
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return template(context);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Generates README.md file if it doesn't exist
|
|
86
|
+
* @async
|
|
87
|
+
* @function generateReadmeMdFile
|
|
88
|
+
* @param {string} appPath - Path to application directory
|
|
89
|
+
* @param {string} appName - Application name
|
|
90
|
+
* @param {Object} config - Application configuration
|
|
91
|
+
* @returns {Promise<void>} Resolves when README.md is generated or skipped
|
|
92
|
+
* @throws {Error} If file generation fails
|
|
93
|
+
*/
|
|
94
|
+
async function generateReadmeMdFile(appPath, appName, config) {
|
|
95
|
+
const readmePath = path.join(appPath, 'README.md');
|
|
96
|
+
if (!(await fileExists(readmePath))) {
|
|
97
|
+
const readmeContent = generateReadmeMd(appName, config);
|
|
98
|
+
await fs.writeFile(readmePath, readmeContent);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
generateReadmeMdFile,
|
|
104
|
+
generateReadmeMd,
|
|
105
|
+
formatAppDisplayName
|
|
106
|
+
};
|
|
107
|
+
|
|
@@ -171,9 +171,9 @@ async function checkHealthEndpoint(healthCheckUrl) {
|
|
|
171
171
|
async function waitForHealthCheck(appName, timeout = 90, port = null, config = null) {
|
|
172
172
|
await waitForDbInit(appName);
|
|
173
173
|
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
const healthCheckPort = port
|
|
174
|
+
// Use provided port if given, otherwise detect from Docker
|
|
175
|
+
// Port provided should be the host port (CLI --port or config.port, NOT localPort)
|
|
176
|
+
const healthCheckPort = port !== null && port !== undefined ? port : await getContainerPort(appName);
|
|
177
177
|
|
|
178
178
|
const healthCheckPath = config?.healthCheck?.path || '/health';
|
|
179
179
|
const healthCheckUrl = `http://localhost:${healthCheckPort}${healthCheckPath}`;
|
package/package.json
CHANGED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# {{displayName}} Builder
|
|
2
|
+
|
|
3
|
+
Build, run, and deploy {{displayName}} using `@aifabrix/builder`.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @aifabrix/builder
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Build
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
aifabrix build {{appName}}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Builds Docker image: `{{imageName}}:latest`
|
|
18
|
+
|
|
19
|
+
## Run Locally
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
aifabrix run {{appName}}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Access:** http://localhost:{{port}}
|
|
26
|
+
|
|
27
|
+
**Logs:**
|
|
28
|
+
```bash
|
|
29
|
+
docker logs {{appName}} -f
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Stop:**
|
|
33
|
+
```bash
|
|
34
|
+
docker stop {{appName}}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Push to Azure Container Registry
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
aifabrix push {{appName}} --action acr --tag latest
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Note:** ACR push requires `az login` or ACR credentials in `variables.yaml`
|
|
44
|
+
|
|
45
|
+
## Prerequisites
|
|
46
|
+
|
|
47
|
+
- `@aifabrix/builder` installed globally
|
|
48
|
+
- Docker Desktop running
|
|
49
|
+
- Infrastructure running (`aifabrix up`)
|
|
50
|
+
{{#if hasDatabase}}
|
|
51
|
+
- PostgreSQL database
|
|
52
|
+
{{/if}}
|
|
53
|
+
{{#if hasRedis}}
|
|
54
|
+
- Redis
|
|
55
|
+
{{/if}}
|
|
56
|
+
{{#if hasStorage}}
|
|
57
|
+
- File storage configured
|
|
58
|
+
{{/if}}
|
|
59
|
+
{{#if hasAuthentication}}
|
|
60
|
+
- Authentication/RBAC configured
|
|
61
|
+
{{/if}}
|
|
62
|
+
|
|
63
|
+
## Troubleshooting
|
|
64
|
+
|
|
65
|
+
**Build fails:** Check Docker is running and `variables.yaml` → `build.secrets` path is correct
|
|
66
|
+
|
|
67
|
+
**Can't connect:** Verify infrastructure is running (`aifabrix up`){{#if hasDatabase}} and PostgreSQL is accessible{{/if}}
|
|
68
|
+
|
|
69
|
+
**Port in use:** Change `build.localPort` in `variables.yaml` (default: {{port}})
|
|
70
|
+
|