@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 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
- // Always detect the actual port from Docker to ensure we use the correct mapped port
175
- const detectedPort = await getContainerPort(appName);
176
- const healthCheckPort = port || detectedPort;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.0.8",
3
+ "version": "2.1.0",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -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
+