@aifabrix/builder 2.36.2 → 2.37.5
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/.cursor/rules/project-rules.mdc +19 -0
- package/README.md +68 -104
- package/integration/hubspot/test.js +1 -1
- package/lib/api/wizard.api.js +24 -1
- package/lib/app/deploy.js +43 -7
- package/lib/app/display.js +1 -1
- package/lib/app/list.js +3 -1
- package/lib/app/run-helpers.js +1 -1
- package/lib/build/index.js +3 -4
- package/lib/cli/index.js +45 -0
- package/lib/cli/setup-app.js +230 -0
- package/lib/cli/setup-auth.js +88 -0
- package/lib/cli/setup-dev.js +101 -0
- package/lib/cli/setup-environment.js +53 -0
- package/lib/cli/setup-external-system.js +87 -0
- package/lib/cli/setup-infra.js +219 -0
- package/lib/cli/setup-secrets.js +48 -0
- package/lib/cli/setup-utility.js +202 -0
- package/lib/cli.js +7 -961
- package/lib/commands/up-common.js +31 -1
- package/lib/commands/up-miso.js +6 -2
- package/lib/commands/wizard-core.js +32 -7
- package/lib/core/config.js +10 -0
- package/lib/core/ensure-encryption-key.js +56 -0
- package/lib/deployment/deployer-status.js +101 -0
- package/lib/deployment/deployer.js +62 -110
- package/lib/deployment/environment.js +133 -34
- package/lib/external-system/deploy.js +5 -1
- package/lib/external-system/test-auth.js +14 -7
- package/lib/generator/wizard.js +37 -41
- package/lib/infrastructure/helpers.js +1 -1
- package/lib/schema/environment-deploy-request.schema.json +64 -0
- package/lib/utils/help-builder.js +5 -2
- package/lib/utils/paths.js +22 -4
- package/lib/utils/secrets-generator.js +23 -8
- package/lib/utils/secrets-helpers.js +46 -21
- package/package.json +1 -1
- package/scripts/install-local.js +11 -2
- package/templates/applications/README.md.hbs +3 -3
- package/templates/applications/dataplane/variables.yaml +0 -2
- package/templates/applications/miso-controller/variables.yaml +0 -2
- package/templates/external-system/deploy.js.hbs +69 -0
- package/templates/infra/environment-dev.json +10 -0
|
@@ -70,6 +70,23 @@ lib/
|
|
|
70
70
|
└── schema/ # JSON schemas
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
### Generated Output (integration/ and builder/)
|
|
74
|
+
|
|
75
|
+
Files under **integration/** and **builder/** are **auto-generated** by the CLI. When fixing bugs or changing behavior, validate **where** each file is produced so fixes go into the generator, not only into the generated artifact.
|
|
76
|
+
|
|
77
|
+
- **integration/** – External system / wizard output:
|
|
78
|
+
- Path: `integration/<appName>/` (see `lib/utils/paths.js` → `getIntegrationPath`).
|
|
79
|
+
- Generated by: `lib/generator/wizard.js` (`generateWizardFiles`, `generateConfigFilesForWizard`), `lib/external-system/download.js`, wizard commands in `lib/commands/wizard-core.js` and `lib/commands/wizard.js`.
|
|
80
|
+
- Typical outputs: `variables.yaml`, `env.template`, `README.md`, `*-system.json`, `*-datasource*.json`, `*-deploy.json`, deploy script (`deploy.js`), and optionally `wizard.yaml`, `error.log`.
|
|
81
|
+
- **builder/** – Application (non-external) output:
|
|
82
|
+
- Path: `builder/<appName>/` or custom root via `AIFABRIX_BUILDER_DIR` (see `lib/utils/paths.js` → `getBuilderPath`).
|
|
83
|
+
- Generated by: app create/register flow, `lib/generator/index.js`, `lib/commands/up-common.js`, `lib/core/secrets.js`, and related app/deploy logic.
|
|
84
|
+
- Typical outputs: `variables.yaml`, `env.template`, deploy JSON, `.env` (from secrets), and app-specific config.
|
|
85
|
+
|
|
86
|
+
**Editable vs generated:**
|
|
87
|
+
- Some generated files are **intended to be edited** (e.g. `variables.yaml`, `env.template`, `README.md`, `wizard.yaml`). Improvements to defaults or structure still belong in the generator/templates.
|
|
88
|
+
- **When debugging:** First identify the **source of generation** (which module and function write the file). Fix bugs in that generator or template; avoid treating a one-off edit in integration/ or builder/ as the permanent fix unless it’s a deliberate local override.
|
|
89
|
+
|
|
73
90
|
### CLI Command Pattern
|
|
74
91
|
Commands are defined in `lib/cli.js` using Commander.js:
|
|
75
92
|
```javascript
|
|
@@ -850,6 +867,7 @@ Define request/response types using JSDoc `@typedef`:
|
|
|
850
867
|
|
|
851
868
|
### Must Do (✅)
|
|
852
869
|
- ✅ Validate all inputs (app names, file paths, URLs)
|
|
870
|
+
- ✅ When fixing bugs in integration/ or builder/ output: identify the generator that produces the file and fix the source (lib/generator, lib/commands, templates), not only the generated artifact
|
|
853
871
|
- ✅ Use try-catch for all async operations
|
|
854
872
|
- ✅ Provide meaningful error messages with context
|
|
855
873
|
- ✅ Use JSDoc for all public functions
|
|
@@ -874,6 +892,7 @@ Define request/response types using JSDoc `@typedef`:
|
|
|
874
892
|
- ❌ Never use `eval()` or `Function()` constructor
|
|
875
893
|
- ❌ Never use raw paths (always use path.join)
|
|
876
894
|
- ❌ Never make direct API calls using `makeApiCall` in new code (use `lib/api/` modules)
|
|
895
|
+
- ❌ Never treat one-off edits in integration/ or builder/ as the permanent fix for a bug—update the generator or template that produces the file
|
|
877
896
|
- ❌ Never skip type definitions for API request/response types
|
|
878
897
|
- ❌ Never log authentication tokens or secrets in API calls
|
|
879
898
|
|
package/README.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
# AI Fabrix - Builder
|
|
1
|
+
# AI Fabrix - Builder
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@aifabrix/builder)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Install the AI Fabrix platform and test it locally. Then add external integrations or build your own applications.
|
|
7
|
+
|
|
8
|
+
← **Full documentation:** [docs/README.md](docs/README.md) (table of contents for all guides)
|
|
9
|
+
|
|
10
|
+
---
|
|
7
11
|
|
|
8
12
|
## Install
|
|
9
13
|
|
|
@@ -11,126 +15,86 @@ Local development infrastructure + Azure deployment tool.
|
|
|
11
15
|
npm install -g @aifabrix/builder
|
|
12
16
|
```
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
**Alias:** You can use `aifx` instead of `aifabrix` in any command.
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
aifabrix up # Start Postgres + Redis
|
|
18
|
-
aifabrix create myapp # Create your app
|
|
19
|
-
aifabrix build myapp # Build Docker image
|
|
20
|
-
aifabrix run myapp # Run locally
|
|
21
|
-
# Stop the app (optionally remove its data volume)
|
|
22
|
-
aifabrix down myapp
|
|
23
|
-
# aifabrix down myapp --volumes
|
|
24
|
-
```
|
|
20
|
+
---
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
## Goal 1: Start and test the AI Fabrix platform
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
Get the platform running locally so you can try it.
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
- **Auto-generated Dockerfiles** - TypeScript and Python templates
|
|
32
|
-
- **Environment variable management** - Secret resolution with kv:// references
|
|
33
|
-
- **Azure deployment pipeline** - Push to ACR and deploy via controller
|
|
26
|
+
1. **Start local infrastructure** (Postgres, Redis, optional Traefik):
|
|
34
27
|
|
|
35
|
-
|
|
28
|
+
```bash
|
|
29
|
+
aifabrix up-infra
|
|
30
|
+
```
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
2. **Start the platform** (Keycloak, Miso Controller, Dataplane) from community images:
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
aifabrix up-miso # Install Keycloak + Miso Controller from images (auto-generated secrets for testing)
|
|
43
|
-
```
|
|
34
|
+
```bash
|
|
35
|
+
aifabrix up-platform
|
|
36
|
+
```
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
# Keycloak for authentication
|
|
48
|
-
aifabrix create keycloak --port 8082 --database --template keycloak
|
|
49
|
-
aifabrix build keycloak
|
|
50
|
-
aifabrix run keycloak
|
|
51
|
-
|
|
52
|
-
# Miso Controller for Azure deployments
|
|
53
|
-
aifabrix create miso-controller --port 3000 --database --redis --template miso-controller
|
|
54
|
-
aifabrix build miso-controller
|
|
55
|
-
aifabrix run miso-controller
|
|
56
|
-
```
|
|
38
|
+
Or run platform apps separately: `aifabrix up-miso` then `aifabrix up-dataplane`. Infra must be up first.
|
|
57
39
|
|
|
58
|
-
**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
40
|
+
3. **Configure secrets** – You need either **OpenAI** or **Azure OpenAI**:
|
|
41
|
+
|
|
42
|
+
- **OpenAI:** set your API key:
|
|
43
|
+
```bash
|
|
44
|
+
aifabrix secrets set secrets-openaiApiKeyVault <your-openai-secret-key>
|
|
45
|
+
```
|
|
46
|
+
- **Azure OpenAI:** set endpoint and API key:
|
|
47
|
+
```bash
|
|
48
|
+
aifabrix secrets set azure-openaiapi-urlKeyVault <your-azure-openai-endpoint-url>
|
|
49
|
+
aifabrix secrets set secrets-azureOpenaiApiKeyVault <your-azure-openai-secret-key>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Secrets are stored in `~/.aifabrix/secrets.local.yaml` or the file from `aifabrix-secrets` in your config (e.g. `builder/secrets.local.yaml`).
|
|
53
|
+
|
|
54
|
+
→ [Infrastructure guide](docs/infrastructure.md)
|
|
63
55
|
|
|
64
|
-
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Goal 2: External system integration
|
|
59
|
+
|
|
60
|
+
Create and deploy an external system (e.g. HubSpot): wizard or manual setup, then validate and deploy.
|
|
61
|
+
|
|
62
|
+
**Example: HubSpot**
|
|
63
|
+
|
|
64
|
+
- Create: `aifabrix create hubspot-test --type external` (or `aifabrix wizard` for guided setup).
|
|
65
|
+
- Configure auth and datasources under `integration/hubspot-test/`.
|
|
66
|
+
- Validate: `aifabrix validate hubspot-test`
|
|
67
|
+
- Deploy: `aifabrix deploy hubspot-test`
|
|
68
|
+
|
|
69
|
+
→ [External systems guide](docs/external-systems.md) · [Wizard](docs/wizard.md)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Goal 3: Build your own application
|
|
74
|
+
|
|
75
|
+
Create, configure, and run your own AI Fabrix application locally or deploy it (create app → configure → build → run / deploy).
|
|
76
|
+
|
|
77
|
+
→ [Your own applications](docs/your-own-applications.md)
|
|
78
|
+
|
|
79
|
+
---
|
|
65
80
|
|
|
66
81
|
## Documentation
|
|
67
82
|
|
|
68
|
-
|
|
69
|
-
- [Infrastructure](docs/infrastructure.md) - What runs and why
|
|
70
|
-
- [Configuration](docs/configuration.md) - Config file reference
|
|
71
|
-
- [Building](docs/building.md) - Build process explained
|
|
72
|
-
- [Running](docs/running.md) - Run apps locally
|
|
73
|
-
- [Deploying](docs/deploying.md) - Deploy to Azure
|
|
74
|
-
- [CLI Reference](docs/cli-reference.md) - All commands
|
|
75
|
-
|
|
76
|
-
## How It Works
|
|
77
|
-
|
|
78
|
-
1. **Infrastructure** - Minimal baseline (Postgres + Redis)
|
|
79
|
-
2. **Create** - Generate config files for your app
|
|
80
|
-
3. **Build** - Auto-detect runtime and build Docker image
|
|
81
|
-
4. **Run** - Start locally, connected to infrastructure
|
|
82
|
-
5. **Deploy** - Push to ACR and deploy via controller
|
|
83
|
-
|
|
84
|
-
```mermaid
|
|
85
|
-
%%{init: {
|
|
86
|
-
"theme": "base",
|
|
87
|
-
"themeVariables": {
|
|
88
|
-
"fontFamily": "Poppins, Arial Rounded MT Bold, Arial, sans-serif",
|
|
89
|
-
"fontSize": "16px",
|
|
90
|
-
"background": "#FFFFFF",
|
|
91
|
-
"primaryColor": "#F8FAFC",
|
|
92
|
-
"primaryTextColor": "#0B0E15",
|
|
93
|
-
"primaryBorderColor": "#E2E8F0",
|
|
94
|
-
"lineColor": "#E2E8F0",
|
|
95
|
-
"textColor": "#0B0E15",
|
|
96
|
-
"borderRadius": 16
|
|
97
|
-
},
|
|
98
|
-
"flowchart": {
|
|
99
|
-
"curve": "linear",
|
|
100
|
-
"nodeSpacing": 34,
|
|
101
|
-
"rankSpacing": 34,
|
|
102
|
-
"padding": 10
|
|
103
|
-
}
|
|
104
|
-
}}%%
|
|
105
|
-
|
|
106
|
-
flowchart TD
|
|
107
|
-
|
|
108
|
-
%% =======================
|
|
109
|
-
%% Styles
|
|
110
|
-
%% =======================
|
|
111
|
-
classDef base fill:#FFFFFF,color:#0B0E15,stroke:#E2E8F0,stroke-width:1.5px;
|
|
112
|
-
classDef primary fill:#0062FF,color:#ffffff,stroke-width:0px;
|
|
113
|
-
|
|
114
|
-
%% =======================
|
|
115
|
-
%% Flow
|
|
116
|
-
%% =======================
|
|
117
|
-
Install[Install CLI]:::primary --> Up[Start Infrastructure]:::base
|
|
118
|
-
Up --> Create[Create App]:::base
|
|
119
|
-
Create --> Build[Build Image]:::base
|
|
120
|
-
Build --> Run[Run Locally]:::base
|
|
121
|
-
Run --> Deploy[Deploy to Azure]:::primary
|
|
122
|
-
```
|
|
83
|
+
All guides and references are listed in **[docs/README.md](docs/README.md)** (table of contents).
|
|
123
84
|
|
|
124
|
-
|
|
85
|
+
- [CLI Reference](docs/cli-reference.md) – All commands
|
|
86
|
+
- [Infrastructure](docs/infrastructure.md) – What runs and why
|
|
87
|
+
- [Configuration](docs/configuration.md) – Config files
|
|
125
88
|
|
|
126
|
-
|
|
127
|
-
- **Coverage**: `npm run test:coverage` — runs tests with coverage through the same wrapper. May take 3–5 minutes for the full suite. If the process exits with a signal after "Ran all test suites", the wrapper treats it as success and coverage is written to `coverage/`. Use `test:coverage:nyc` only if you need nyc-specific reporters.
|
|
89
|
+
---
|
|
128
90
|
|
|
129
91
|
## Requirements
|
|
130
92
|
|
|
131
|
-
- **Docker Desktop**
|
|
132
|
-
- **Node.js 18+**
|
|
133
|
-
- **Azure CLI**
|
|
93
|
+
- **Docker Desktop** – For running containers
|
|
94
|
+
- **Node.js 18+** – For running the CLI
|
|
95
|
+
- **Azure CLI** – For deploying to Azure (optional)
|
|
96
|
+
|
|
97
|
+
---
|
|
134
98
|
|
|
135
99
|
## License
|
|
136
100
|
|
|
@@ -511,7 +511,7 @@ async function checkAppDirectory(appPath) {
|
|
|
511
511
|
* @throws {Error} If required files are missing
|
|
512
512
|
*/
|
|
513
513
|
async function validateRequiredFiles(appPath, entries) {
|
|
514
|
-
const requiredFiles = ['variables.yaml', 'env.template', 'README.md', 'deploy.
|
|
514
|
+
const requiredFiles = ['variables.yaml', 'env.template', 'README.md', 'deploy.js'];
|
|
515
515
|
const missingFiles = [];
|
|
516
516
|
for (const fileName of requiredFiles) {
|
|
517
517
|
const filePath = path.join(appPath, fileName);
|
package/lib/api/wizard.api.js
CHANGED
|
@@ -311,7 +311,7 @@ async function testMcpConnection(dataplaneUrl, authConfig, serverUrl, token) {
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
/**
|
|
314
|
-
* Get deployment documentation for a system
|
|
314
|
+
* Get deployment documentation for a system (from dataplane DB only)
|
|
315
315
|
* GET /api/v1/wizard/deployment-docs/{systemKey}
|
|
316
316
|
* @async
|
|
317
317
|
* @function getDeploymentDocs
|
|
@@ -326,6 +326,28 @@ async function getDeploymentDocs(dataplaneUrl, authConfig, systemKey) {
|
|
|
326
326
|
return await client.get(`/api/v1/wizard/deployment-docs/${systemKey}`);
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Generate deployment documentation with variables.yaml and deploy JSON for better quality
|
|
331
|
+
* POST /api/v1/wizard/deployment-docs/{systemKey}
|
|
332
|
+
* Sends deployJson and variablesYaml in the request body so the dataplane can align README with the integration folder.
|
|
333
|
+
* @async
|
|
334
|
+
* @function postDeploymentDocs
|
|
335
|
+
* @param {string} dataplaneUrl - Dataplane base URL
|
|
336
|
+
* @param {Object} authConfig - Authentication configuration
|
|
337
|
+
* @param {string} systemKey - System key identifier
|
|
338
|
+
* @param {Object} [body] - Optional request body (WizardDeploymentDocsRequest)
|
|
339
|
+
* @param {Object} [body.deployJson] - Deploy JSON object (e.g. *-deploy.json content)
|
|
340
|
+
* @param {string} [body.variablesYaml] - variables.yaml file content as string
|
|
341
|
+
* @returns {Promise<Object>} Deployment documentation response (content, contentType, systemKey)
|
|
342
|
+
* @throws {Error} If request fails
|
|
343
|
+
*/
|
|
344
|
+
async function postDeploymentDocs(dataplaneUrl, authConfig, systemKey, body = null) {
|
|
345
|
+
const client = new ApiClient(dataplaneUrl, authConfig);
|
|
346
|
+
return await client.post(`/api/v1/wizard/deployment-docs/${systemKey}`, {
|
|
347
|
+
body: body || {}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
329
351
|
/**
|
|
330
352
|
* Get known wizard platforms from dataplane.
|
|
331
353
|
* GET /api/v1/wizard/platforms
|
|
@@ -365,5 +387,6 @@ module.exports = {
|
|
|
365
387
|
getPreview,
|
|
366
388
|
testMcpConnection,
|
|
367
389
|
getDeploymentDocs,
|
|
390
|
+
postDeploymentDocs,
|
|
368
391
|
getWizardPlatforms
|
|
369
392
|
};
|
package/lib/app/deploy.js
CHANGED
|
@@ -15,7 +15,7 @@ const yaml = require('js-yaml');
|
|
|
15
15
|
const chalk = require('chalk');
|
|
16
16
|
const pushUtils = require('../deployment/push');
|
|
17
17
|
const logger = require('../utils/logger');
|
|
18
|
-
const { detectAppType } = require('../utils/paths');
|
|
18
|
+
const { detectAppType, getBuilderPath, getIntegrationPath } = require('../utils/paths');
|
|
19
19
|
const { checkApplicationExists } = require('../utils/app-existence');
|
|
20
20
|
const { loadDeploymentConfig } = require('./deploy-config');
|
|
21
21
|
|
|
@@ -219,15 +219,16 @@ function displayDeploymentResults(result) {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
/**
|
|
222
|
-
* Check if app is external and handle external deployment
|
|
222
|
+
* Check if app is external and handle external deployment.
|
|
223
|
+
* When options.type === 'external', forces deployment from integration/<app> (no app register needed).
|
|
223
224
|
* @async
|
|
224
225
|
* @function handleExternalDeployment
|
|
225
226
|
* @param {string} appName - Application name
|
|
226
|
-
* @param {Object} options - Deployment options
|
|
227
|
+
* @param {Object} options - Deployment options (type: 'external' to force integration/<app>)
|
|
227
228
|
* @returns {Promise<Object|null>} Deployment result if external, null otherwise
|
|
228
229
|
*/
|
|
229
230
|
async function handleExternalDeployment(appName, options) {
|
|
230
|
-
const { isExternal } = await detectAppType(appName);
|
|
231
|
+
const { isExternal } = await detectAppType(appName, options);
|
|
231
232
|
if (isExternal) {
|
|
232
233
|
const externalDeploy = require('../external-system/deploy');
|
|
233
234
|
await externalDeploy.deployExternalSystem(appName, options);
|
|
@@ -317,6 +318,37 @@ async function executeStandardDeployment(appName, options) {
|
|
|
317
318
|
}
|
|
318
319
|
}
|
|
319
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Tries external deploy when builder/<app> does not exist but integration/<app> does.
|
|
323
|
+
* @async
|
|
324
|
+
* @param {string} appName - Application name
|
|
325
|
+
* @param {Object} options - Deployment options
|
|
326
|
+
* @returns {Promise<{usedExternalDeploy: boolean, result: Object|null}>}
|
|
327
|
+
*/
|
|
328
|
+
async function tryExternalDeployFallback(appName, options) {
|
|
329
|
+
const builderPath = getBuilderPath(appName);
|
|
330
|
+
const integrationPath = getIntegrationPath(appName);
|
|
331
|
+
let builderExists = false;
|
|
332
|
+
let integrationExists = false;
|
|
333
|
+
try {
|
|
334
|
+
await fs.access(builderPath);
|
|
335
|
+
builderExists = true;
|
|
336
|
+
} catch (e) {
|
|
337
|
+
if (e.code !== 'ENOENT') throw e;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
await fs.access(integrationPath);
|
|
341
|
+
integrationExists = true;
|
|
342
|
+
} catch (e) {
|
|
343
|
+
if (e.code !== 'ENOENT') throw e;
|
|
344
|
+
}
|
|
345
|
+
if (!builderExists && integrationExists) {
|
|
346
|
+
const fallbackResult = await handleExternalDeployment(appName, { ...options, type: 'external' });
|
|
347
|
+
if (fallbackResult) return { usedExternalDeploy: true, result: fallbackResult };
|
|
348
|
+
}
|
|
349
|
+
return { usedExternalDeploy: false, result: null };
|
|
350
|
+
}
|
|
351
|
+
|
|
320
352
|
/**
|
|
321
353
|
* Deploys application to Miso Controller
|
|
322
354
|
* Orchestrates manifest generation, key creation, and deployment
|
|
@@ -338,7 +370,7 @@ async function executeStandardDeployment(appName, options) {
|
|
|
338
370
|
*/
|
|
339
371
|
async function deployApp(appName, options = {}) {
|
|
340
372
|
let controllerUrl = null;
|
|
341
|
-
let usedExternalDeploy =
|
|
373
|
+
let usedExternalDeploy = options.type === 'external';
|
|
342
374
|
|
|
343
375
|
try {
|
|
344
376
|
if (!appName || typeof appName !== 'string' || appName.trim().length === 0) {
|
|
@@ -347,8 +379,12 @@ async function deployApp(appName, options = {}) {
|
|
|
347
379
|
validateAppName(appName);
|
|
348
380
|
|
|
349
381
|
const externalResult = await handleExternalDeployment(appName, options);
|
|
350
|
-
if (externalResult)
|
|
351
|
-
|
|
382
|
+
if (externalResult) return externalResult;
|
|
383
|
+
|
|
384
|
+
const fallback = await tryExternalDeployFallback(appName, options);
|
|
385
|
+
if (fallback.result) {
|
|
386
|
+
usedExternalDeploy = fallback.usedExternalDeploy;
|
|
387
|
+
return fallback.result;
|
|
352
388
|
}
|
|
353
389
|
usedExternalDeploy = false;
|
|
354
390
|
|
package/lib/app/display.js
CHANGED
|
@@ -50,7 +50,7 @@ function displayWebappSuccess(appName, config, envConversionMessage) {
|
|
|
50
50
|
|
|
51
51
|
logger.log(chalk.green('\nNext steps:'));
|
|
52
52
|
logger.log(chalk.white('1. Copy env.template to .env and fill in your values'));
|
|
53
|
-
logger.log(chalk.white('2. Run: aifabrix up'));
|
|
53
|
+
logger.log(chalk.white('2. Run: aifabrix up-infra'));
|
|
54
54
|
logger.log(chalk.white('3. Run: aifabrix build ' + appName));
|
|
55
55
|
logger.log(chalk.white('4. Run: aifabrix run ' + appName));
|
|
56
56
|
}
|
package/lib/app/list.js
CHANGED
|
@@ -164,9 +164,11 @@ function displayApplications(applications, environment, controllerUrl) {
|
|
|
164
164
|
|
|
165
165
|
logger.log(chalk.bold(`\n📱 ${header}:\n`));
|
|
166
166
|
applications.forEach((app) => {
|
|
167
|
+
const isExternal = app.configuration?.type === 'external';
|
|
168
|
+
const externalIcon = isExternal ? '🔗 ' : '';
|
|
167
169
|
const hasPipeline = app.configuration?.pipeline?.isActive ? '✓' : '✗';
|
|
168
170
|
const urlAndPort = formatUrlAndPort(app);
|
|
169
|
-
logger.log(`${hasPipeline} ${chalk.cyan(app.key)} - ${app.displayName} (${app.status || 'unknown'})${urlAndPort}`);
|
|
171
|
+
logger.log(`${externalIcon}${hasPipeline} ${chalk.cyan(app.key)} - ${app.displayName} (${app.status || 'unknown'})${urlAndPort}`);
|
|
170
172
|
});
|
|
171
173
|
logger.log(chalk.gray(' To show details for an app: aifabrix app show <appKey>\n'));
|
|
172
174
|
}
|
package/lib/app/run-helpers.js
CHANGED
|
@@ -177,7 +177,7 @@ async function checkPrerequisites(appName, appConfig, debug = false, skipInfraCh
|
|
|
177
177
|
.map(([service, _]) => service);
|
|
178
178
|
|
|
179
179
|
if (unhealthyServices.length > 0) {
|
|
180
|
-
throw new Error(`Infrastructure services not healthy: ${unhealthyServices.join(', ')}\nRun 'aifabrix up' first`);
|
|
180
|
+
throw new Error(`Infrastructure services not healthy: ${unhealthyServices.join(', ')}\nRun 'aifabrix up-infra' first`);
|
|
181
181
|
}
|
|
182
182
|
logger.log(chalk.green('✓ Infrastructure is running'));
|
|
183
183
|
}
|
package/lib/build/index.js
CHANGED
|
@@ -200,7 +200,7 @@ async function postBuildTasks(appName, buildConfig) {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
|
-
*
|
|
203
|
+
* External apps have no Docker image; deploy JSON is generated by aifabrix json.
|
|
204
204
|
* @async
|
|
205
205
|
* @param {string} appName - Application name
|
|
206
206
|
* @returns {Promise<boolean>} True if external (handled), false if should continue
|
|
@@ -208,9 +208,8 @@ async function postBuildTasks(appName, buildConfig) {
|
|
|
208
208
|
async function checkExternalAppType(appName) {
|
|
209
209
|
const variables = await loadVariablesYaml(appName);
|
|
210
210
|
if (variables.app && variables.app.type === 'external') {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
logger.log(chalk.green(`✓ Generated deployment JSON: ${jsonPath}`));
|
|
211
|
+
logger.log(chalk.blue(`External system: ${appName}`));
|
|
212
|
+
logger.log(chalk.gray('To regenerate deployment JSON, run: aifabrix json ' + appName));
|
|
214
213
|
return true;
|
|
215
214
|
}
|
|
216
215
|
return false;
|
package/lib/cli/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Fabrix Builder CLI Command Definitions
|
|
3
|
+
*
|
|
4
|
+
* This module wires all CLI command setup and re-exports setupCommands,
|
|
5
|
+
* validateCommand, and handleCommandError for backward compatibility.
|
|
6
|
+
*
|
|
7
|
+
* @fileoverview CLI entry for AI Fabrix Builder; command setup orchestration
|
|
8
|
+
* @author AI Fabrix Team
|
|
9
|
+
* @version 2.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { validateCommand, handleCommandError } = require('../utils/cli-utils');
|
|
13
|
+
const { setupAuthCommands } = require('./setup-auth');
|
|
14
|
+
const { setupInfraCommands } = require('./setup-infra');
|
|
15
|
+
const { setupAppCommands } = require('./setup-app');
|
|
16
|
+
const { setupEnvironmentCommands } = require('./setup-environment');
|
|
17
|
+
const { setupUtilityCommands } = require('./setup-utility');
|
|
18
|
+
const { setupDevCommands } = require('./setup-dev');
|
|
19
|
+
const { setupSecretsCommands } = require('./setup-secrets');
|
|
20
|
+
const { setupExternalSystemCommands } = require('./setup-external-system');
|
|
21
|
+
const { setupAppCommands: setupAppManagementCommands } = require('../commands/app');
|
|
22
|
+
const { setupDatasourceCommands } = require('../commands/datasource');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Sets up all CLI commands on the Commander program instance
|
|
26
|
+
* @param {Command} program - Commander program instance
|
|
27
|
+
*/
|
|
28
|
+
function setupCommands(program) {
|
|
29
|
+
setupInfraCommands(program);
|
|
30
|
+
setupAuthCommands(program);
|
|
31
|
+
setupAppCommands(program);
|
|
32
|
+
setupEnvironmentCommands(program);
|
|
33
|
+
setupAppManagementCommands(program);
|
|
34
|
+
setupDatasourceCommands(program);
|
|
35
|
+
setupUtilityCommands(program);
|
|
36
|
+
setupExternalSystemCommands(program);
|
|
37
|
+
setupDevCommands(program);
|
|
38
|
+
setupSecretsCommands(program);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
setupCommands,
|
|
43
|
+
validateCommand,
|
|
44
|
+
handleCommandError
|
|
45
|
+
};
|