@aifabrix/builder 2.40.2 → 2.42.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/.cursor/rules/docs-rules.mdc +30 -0
- package/README.md +7 -5
- package/integration/hubspot/README.md +8 -4
- package/integration/hubspot/application.json +54 -0
- package/integration/hubspot/create-hubspot.js +9 -136
- package/integration/hubspot/env.template +3 -4
- package/integration/hubspot/hubspot-datasource-company.json +343 -5
- package/integration/hubspot/hubspot-datasource-contact.json +413 -5
- package/integration/hubspot/hubspot-datasource-deal.json +341 -4
- package/integration/hubspot/hubspot-datasource-users.json +116 -0
- package/integration/hubspot/hubspot-deploy.json +1250 -108
- package/integration/hubspot/hubspot-system.json +15 -32
- package/integration/hubspot/test-dataplane-down-tests.js +17 -16
- package/integration/hubspot/test-dataplane-down.js +2 -2
- package/integration/hubspot/test.js +1 -1
- package/jest.config.manual.js +2 -1
- package/lib/api/credential.api.js +40 -0
- package/lib/api/dev.api.js +423 -0
- package/lib/api/external-test.api.js +111 -0
- package/lib/api/index.js +42 -19
- package/lib/api/pipeline.api.js +66 -120
- package/lib/api/types/credential.types.js +23 -0
- package/lib/api/types/dev.types.js +140 -0
- package/lib/api/types/pipeline.types.js +37 -0
- package/lib/api/wizard-platform.api.js +61 -0
- package/lib/api/wizard.api.js +34 -1
- package/lib/app/config.js +44 -11
- package/lib/app/down.js +2 -1
- package/lib/app/index.js +12 -1
- package/lib/app/prompts.js +44 -29
- package/lib/app/push.js +36 -12
- package/lib/app/readme.js +9 -6
- package/lib/app/run-env-compose.js +264 -0
- package/lib/app/run-helpers.js +121 -118
- package/lib/app/run.js +148 -28
- package/lib/app/show-display.js +1 -1
- package/lib/app/show.js +5 -2
- package/lib/build/index.js +11 -3
- package/lib/cli/setup-app.js +172 -15
- package/lib/cli/setup-credential-deployment.js +31 -6
- package/lib/cli/setup-dev.js +206 -16
- package/lib/cli/setup-environment.js +16 -6
- package/lib/cli/setup-external-system.js +89 -24
- package/lib/cli/setup-infra.js +82 -15
- package/lib/cli/setup-secrets.js +52 -5
- package/lib/cli/setup-utility.js +129 -24
- package/lib/commands/app-install.js +172 -0
- package/lib/commands/app-shell.js +75 -0
- package/lib/commands/app-test.js +282 -0
- package/lib/commands/app.js +1 -1
- package/lib/commands/credential-env.js +162 -0
- package/lib/commands/credential-list.js +17 -22
- package/lib/commands/credential-push.js +96 -0
- package/lib/commands/datasource.js +77 -6
- package/lib/commands/dev-cli-handlers.js +141 -0
- package/lib/commands/dev-down.js +114 -0
- package/lib/commands/dev-init.js +347 -0
- package/lib/commands/repair-auth-config.js +99 -0
- package/lib/commands/repair-datasource-keys.js +208 -0
- package/lib/commands/repair-datasource.js +235 -0
- package/lib/commands/repair-env-template.js +348 -0
- package/lib/commands/repair-internal.js +85 -0
- package/lib/commands/repair-rbac.js +158 -0
- package/lib/commands/repair.js +507 -0
- package/lib/commands/secrets-list.js +118 -0
- package/lib/commands/secrets-remove.js +97 -0
- package/lib/commands/secrets-set.js +30 -17
- package/lib/commands/secrets-validate.js +50 -0
- package/lib/commands/test-e2e-external.js +165 -0
- package/lib/commands/up-dataplane.js +2 -2
- package/lib/commands/up-miso.js +0 -25
- package/lib/commands/upload.js +96 -40
- package/lib/commands/wizard-core-helpers.js +226 -4
- package/lib/commands/wizard-core.js +67 -29
- package/lib/commands/wizard-dataplane.js +1 -1
- package/lib/commands/wizard-entity-selection.js +43 -0
- package/lib/commands/wizard-headless.js +44 -5
- package/lib/commands/wizard-helpers.js +7 -3
- package/lib/commands/wizard.js +86 -64
- package/lib/core/admin-secrets.js +96 -0
- package/lib/core/config.js +7 -1
- package/lib/core/secrets-ensure.js +378 -0
- package/lib/core/secrets-env-write.js +157 -0
- package/lib/core/secrets.js +176 -89
- package/lib/datasource/deploy.js +12 -3
- package/lib/datasource/field-reference-validator.js +91 -0
- package/lib/datasource/test-e2e.js +219 -0
- package/lib/datasource/test-integration.js +154 -0
- package/lib/datasource/validate.js +21 -3
- package/lib/deployment/deployer.js +7 -5
- package/lib/deployment/environment-config.js +137 -0
- package/lib/deployment/environment.js +21 -98
- package/lib/deployment/push.js +32 -2
- package/lib/external-system/download.js +188 -203
- package/lib/external-system/generator.js +204 -56
- package/lib/external-system/test-auth.js +7 -3
- package/lib/external-system/test-execution.js +2 -1
- package/lib/external-system/test-system-level.js +73 -0
- package/lib/external-system/test.js +56 -19
- package/lib/generator/external-controller-manifest.js +29 -2
- package/lib/generator/external-schema-utils.js +1 -1
- package/lib/generator/external.js +10 -3
- package/lib/generator/index.js +177 -25
- package/lib/generator/split-readme.js +1 -0
- package/lib/generator/split-variables.js +7 -1
- package/lib/generator/split.js +194 -54
- package/lib/generator/wizard-prompts-secondary.js +294 -0
- package/lib/generator/wizard-prompts.js +105 -106
- package/lib/generator/wizard-readme.js +88 -0
- package/lib/generator/wizard.js +155 -158
- package/lib/infrastructure/compose.js +11 -1
- package/lib/infrastructure/helpers.js +103 -20
- package/lib/infrastructure/index.js +98 -12
- package/lib/infrastructure/services.js +88 -22
- package/lib/schema/application-schema.json +32 -8
- package/lib/schema/external-datasource.schema.json +49 -26
- package/lib/schema/external-system.schema.json +509 -411
- package/lib/schema/wizard-config.schema.json +16 -0
- package/lib/utils/api.js +41 -13
- package/lib/utils/app-register-auth.js +25 -3
- package/lib/utils/auth-headers.js +8 -7
- package/lib/utils/cli-utils.js +20 -0
- package/lib/utils/compose-generator.js +77 -76
- package/lib/utils/compose-handlebars-helpers.js +54 -0
- package/lib/utils/compose-vector-helper.js +18 -0
- package/lib/utils/config-format-preference.js +51 -0
- package/lib/utils/config-format.js +36 -0
- package/lib/utils/config-paths.js +127 -2
- package/lib/utils/configuration-env-resolver.js +179 -0
- package/lib/utils/credential-display.js +83 -0
- package/lib/utils/credential-secrets-env.js +357 -0
- package/lib/utils/dataplane-pipeline-warning.js +28 -0
- package/lib/utils/deployment-validation-helpers.js +4 -4
- package/lib/utils/dev-ca-install.js +139 -0
- package/lib/utils/dev-cert-helper.js +122 -0
- package/lib/utils/device-code-helpers.js +224 -0
- package/lib/utils/device-code.js +37 -336
- package/lib/utils/docker-build.js +40 -8
- package/lib/utils/env-copy.js +103 -13
- package/lib/utils/env-map.js +35 -5
- package/lib/utils/env-template.js +6 -5
- package/lib/utils/error-formatters/http-status-errors.js +20 -2
- package/lib/utils/error-formatters/permission-errors.js +0 -1
- package/lib/utils/error-formatters/validation-errors.js +0 -1
- package/lib/utils/external-readme.js +56 -29
- package/lib/utils/external-system-display.js +59 -1
- package/lib/utils/external-system-test-helpers.js +21 -8
- package/lib/utils/external-system-validators.js +3 -0
- package/lib/utils/file-upload.js +20 -50
- package/lib/utils/help-builder.js +16 -2
- package/lib/utils/infra-status.js +80 -45
- package/lib/utils/local-secrets.js +7 -52
- package/lib/utils/mutagen-install.js +195 -0
- package/lib/utils/mutagen.js +146 -0
- package/lib/utils/paths.js +128 -37
- package/lib/utils/port-resolver.js +28 -16
- package/lib/utils/remote-dev-auth.js +38 -0
- package/lib/utils/remote-docker-env.js +43 -0
- package/lib/utils/remote-secrets-loader.js +60 -0
- package/lib/utils/secrets-canonical.js +93 -0
- package/lib/utils/secrets-generator.js +114 -6
- package/lib/utils/secrets-helpers.js +108 -114
- package/lib/utils/secrets-path.js +2 -2
- package/lib/utils/secrets-utils.js +52 -1
- package/lib/utils/secrets-validation.js +84 -0
- package/lib/utils/ssh-key-helper.js +116 -0
- package/lib/utils/test-log-writer.js +56 -0
- package/lib/utils/token-manager-messages.js +90 -0
- package/lib/utils/token-manager.js +29 -36
- package/lib/utils/variable-transformer.js +3 -3
- package/lib/validation/env-template-auth.js +157 -0
- package/lib/validation/env-template-kv.js +41 -0
- package/lib/validation/external-manifest-validator.js +25 -0
- package/lib/validation/external-system-auth-rules.js +86 -0
- package/lib/validation/validate-batch.js +149 -0
- package/lib/validation/validate-datasource-keys-api.js +33 -0
- package/lib/validation/validate-display.js +94 -16
- package/lib/validation/validate.js +25 -12
- package/lib/validation/validator.js +72 -9
- package/lib/validation/wizard-datasource-validation.js +50 -0
- package/package.json +8 -3
- package/scripts/install-local.js +34 -15
- package/templates/README.md +0 -1
- package/templates/applications/README.md.hbs +4 -4
- package/templates/applications/dataplane/application.yaml +6 -5
- package/templates/applications/dataplane/env.template +15 -10
- package/templates/applications/dataplane/rbac.yaml +2 -2
- package/templates/applications/keycloak/env.template +2 -0
- package/templates/applications/miso-controller/application.yaml +1 -0
- package/templates/applications/miso-controller/env.template +12 -10
- package/templates/external-system/README.md.hbs +65 -25
- package/templates/external-system/deploy.js.hbs +4 -2
- package/templates/external-system/external-datasource.yaml.hbs +217 -0
- package/templates/external-system/external-system.json.hbs +1 -18
- package/templates/infra/compose.yaml.hbs +6 -0
- package/templates/python/docker-compose.hbs +49 -23
- package/templates/typescript/docker-compose.hbs +48 -22
- package/integration/hubspot/application.yaml +0 -37
package/lib/cli/setup-dev.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI developer configuration command setup (dev config, dev set-id).
|
|
2
|
+
* CLI developer configuration command setup (dev config, dev set-id, dev init, dev add/update/pin/delete/list).
|
|
3
3
|
*
|
|
4
4
|
* @fileoverview Developer command definitions for AI Fabrix Builder CLI
|
|
5
5
|
* @author AI Fabrix Team
|
|
@@ -11,20 +11,38 @@ const config = require('../core/config');
|
|
|
11
11
|
const devConfig = require('../utils/dev-config');
|
|
12
12
|
const logger = require('../utils/logger');
|
|
13
13
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
14
|
+
const { runDevInit, runDevRefresh } = require('../commands/dev-init');
|
|
15
|
+
const {
|
|
16
|
+
handleDevList,
|
|
17
|
+
handleDevAdd,
|
|
18
|
+
handleDevUpdate,
|
|
19
|
+
handleDevPin,
|
|
20
|
+
handleDevDelete
|
|
21
|
+
} = require('../commands/dev-cli-handlers');
|
|
14
22
|
|
|
15
23
|
/**
|
|
16
|
-
* Display developer configuration
|
|
24
|
+
* Display developer configuration (local ports and config; remote/settings keys always shown).
|
|
25
|
+
* Always shows environment, controller, and remote keys (value or "(not set)").
|
|
17
26
|
* @param {string} devId - Developer ID
|
|
18
27
|
* @returns {Promise<void>}
|
|
19
28
|
*/
|
|
20
29
|
async function displayDevConfig(devId) {
|
|
21
30
|
const devIdNum = parseInt(devId, 10);
|
|
22
31
|
const ports = devConfig.getDevPorts(devIdNum);
|
|
23
|
-
const
|
|
32
|
+
const environment = await config.getCurrentEnvironment();
|
|
33
|
+
const controller = await config.getControllerUrl();
|
|
34
|
+
|
|
35
|
+
const optionalConfigVars = [
|
|
36
|
+
{ key: 'format', value: (await config.getFormat()) ?? '(not set)' },
|
|
24
37
|
{ key: 'aifabrix-home', value: await config.getAifabrixHomeOverride() },
|
|
25
38
|
{ key: 'aifabrix-secrets', value: await config.getAifabrixSecretsPath() },
|
|
26
|
-
{ key: 'aifabrix-env-config', value: await config.getAifabrixEnvConfigPath() }
|
|
27
|
-
|
|
39
|
+
{ key: 'aifabrix-env-config', value: await config.getAifabrixEnvConfigPath() },
|
|
40
|
+
{ key: 'remote-server', value: await config.getRemoteServer() },
|
|
41
|
+
{ key: 'docker-endpoint', value: await config.getDockerEndpoint() },
|
|
42
|
+
{ key: 'user-mutagen-folder', value: await config.getUserMutagenFolder() },
|
|
43
|
+
{ key: 'sync-ssh-user', value: await config.getSyncSshUser() },
|
|
44
|
+
{ key: 'sync-ssh-host', value: await config.getSyncSshHost() }
|
|
45
|
+
];
|
|
28
46
|
|
|
29
47
|
logger.log('\n🔧 Developer Configuration\n');
|
|
30
48
|
logger.log(`Developer ID: ${devId}`);
|
|
@@ -35,22 +53,30 @@ async function displayDevConfig(devId) {
|
|
|
35
53
|
logger.log(` pgAdmin: ${ports.pgadmin}`);
|
|
36
54
|
logger.log(` Redis Commander: ${ports.redisCommander}`);
|
|
37
55
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
56
|
+
logger.log('\nConfiguration:');
|
|
57
|
+
logger.log(` environment: '${environment}'`);
|
|
58
|
+
logger.log(controller ? ` controller: '${controller}'` : ' controller: (not set)');
|
|
59
|
+
optionalConfigVars.forEach(v => logger.log(` ${v.key}: ${v.value || '(not set)'}`));
|
|
42
60
|
logger.log('');
|
|
43
61
|
}
|
|
44
62
|
|
|
45
63
|
/**
|
|
46
|
-
*
|
|
47
|
-
* @param {
|
|
64
|
+
* Handle dev set-format command
|
|
65
|
+
* @param {string} format - Format value (json | yaml)
|
|
66
|
+
* @returns {Promise<void>}
|
|
48
67
|
*/
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
async function handleSetFormat(format) {
|
|
69
|
+
await config.setFormat(format);
|
|
70
|
+
logger.log(chalk.green(`✓ Format set to ${format.toLowerCase()}`));
|
|
71
|
+
const devId = await config.getDeveloperId();
|
|
72
|
+
await displayDevConfig(devId);
|
|
73
|
+
}
|
|
53
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Register dev config and set-id commands.
|
|
77
|
+
* @param {Command} dev - dev subcommand group
|
|
78
|
+
*/
|
|
79
|
+
function setupDevConfigCommands(dev) {
|
|
54
80
|
dev
|
|
55
81
|
.command('config')
|
|
56
82
|
.description('Show or set developer configuration')
|
|
@@ -69,7 +95,6 @@ function setupDevCommands(program) {
|
|
|
69
95
|
await displayDevConfig(setIdValue);
|
|
70
96
|
return;
|
|
71
97
|
}
|
|
72
|
-
|
|
73
98
|
const devId = await config.getDeveloperId();
|
|
74
99
|
await displayDevConfig(devId);
|
|
75
100
|
} catch (error) {
|
|
@@ -78,6 +103,18 @@ function setupDevCommands(program) {
|
|
|
78
103
|
}
|
|
79
104
|
});
|
|
80
105
|
|
|
106
|
+
dev
|
|
107
|
+
.command('set-format <format>')
|
|
108
|
+
.description('Set default output format for download/convert (json | yaml); used when --format not passed')
|
|
109
|
+
.action(async(format) => {
|
|
110
|
+
try {
|
|
111
|
+
await handleSetFormat(format);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
handleCommandError(error, 'dev set-format');
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
81
118
|
dev
|
|
82
119
|
.command('set-id <id>')
|
|
83
120
|
.description('Set developer ID (convenience alias for "dev config --set-id")')
|
|
@@ -98,4 +135,157 @@ function setupDevCommands(program) {
|
|
|
98
135
|
});
|
|
99
136
|
}
|
|
100
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Register dev init and refresh commands.
|
|
140
|
+
* @param {Command} dev - dev subcommand group
|
|
141
|
+
*/
|
|
142
|
+
function setupDevInitCommand(dev) {
|
|
143
|
+
dev
|
|
144
|
+
.command('init')
|
|
145
|
+
.description('Onboard with Builder Server (issue certificate, fetch settings, register SSH key for Mutagen)')
|
|
146
|
+
.requiredOption('--developer-id <id>', 'Developer ID (same as dev add; e.g. 01)')
|
|
147
|
+
.requiredOption('--server <url>', 'Builder Server base URL (e.g. https://dev.aifabrix.dev)')
|
|
148
|
+
.requiredOption('--pin <pin>', 'One-time PIN from your admin')
|
|
149
|
+
.option('-y, --yes', 'Auto-install development CA without prompt when certificate is untrusted')
|
|
150
|
+
.option('--no-install-ca', 'Do not offer CA install; fail with manual instructions on untrusted certificate')
|
|
151
|
+
.action(async(options) => {
|
|
152
|
+
try {
|
|
153
|
+
await runDevInit(options);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
handleCommandError(error, 'dev init');
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
dev
|
|
161
|
+
.command('refresh')
|
|
162
|
+
.description('Fetch settings from Builder Server and update config; refresh certificate if expiring within 14 days or --cert')
|
|
163
|
+
.option('--cert', 'Force certificate refresh (create PIN + issue-cert) even when cert is still valid')
|
|
164
|
+
.action(async(options) => {
|
|
165
|
+
try {
|
|
166
|
+
await runDevRefresh(options);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
handleCommandError(error, 'dev refresh');
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Register dev list and add commands (remote only).
|
|
176
|
+
* @param {Command} dev - dev subcommand group
|
|
177
|
+
*/
|
|
178
|
+
function setupDevListAddCommands(dev) {
|
|
179
|
+
dev
|
|
180
|
+
.command('list')
|
|
181
|
+
.description('List developer users (remote Builder Server only)')
|
|
182
|
+
.action(async() => {
|
|
183
|
+
try {
|
|
184
|
+
await handleDevList();
|
|
185
|
+
} catch (error) {
|
|
186
|
+
handleCommandError(error, 'dev list');
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
dev
|
|
192
|
+
.command('add')
|
|
193
|
+
.description('Register a new developer (remote Builder Server only; admin)')
|
|
194
|
+
.requiredOption('--developer-id <id>', 'Developer ID (unique, e.g. 01)')
|
|
195
|
+
.requiredOption('--name <name>', 'Display name')
|
|
196
|
+
.requiredOption('--email <email>', 'Email address')
|
|
197
|
+
.option('--groups <items>', 'Comma-separated groups (admin, secret-manager, developer)', 'developer')
|
|
198
|
+
.action(async(options) => {
|
|
199
|
+
try {
|
|
200
|
+
await handleDevAdd(options);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
handleCommandError(error, 'dev add');
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Register dev update/pin/delete commands (remote only).
|
|
210
|
+
* @param {Command} dev - dev subcommand group
|
|
211
|
+
*/
|
|
212
|
+
function setupDevUpdatePinDeleteCommands(dev) {
|
|
213
|
+
dev
|
|
214
|
+
.command('update [developerId]')
|
|
215
|
+
.description('Update a developer (name, email, groups); use --developer-id like dev add')
|
|
216
|
+
.option('--developer-id <id>', 'Developer ID (same as dev add)')
|
|
217
|
+
.option('--name <name>', 'Display name')
|
|
218
|
+
.option('--email <email>', 'Email address')
|
|
219
|
+
.option('--groups <items>', 'Comma-separated groups (admin, secret-manager, developer)')
|
|
220
|
+
.action(async(developerId, options) => {
|
|
221
|
+
try {
|
|
222
|
+
await handleDevUpdate(developerId, options);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
handleCommandError(error, 'dev update');
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
dev
|
|
230
|
+
.command('pin [developerId]')
|
|
231
|
+
.description('Create or regenerate one-time PIN for onboarding (admin; show once to developer)')
|
|
232
|
+
.action(async(developerId) => {
|
|
233
|
+
try {
|
|
234
|
+
await handleDevPin(developerId);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
handleCommandError(error, 'dev pin');
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
dev
|
|
242
|
+
.command('delete <developerId>')
|
|
243
|
+
.description('Remove a developer (remote Builder Server only; admin)')
|
|
244
|
+
.action(async(developerId) => {
|
|
245
|
+
try {
|
|
246
|
+
await handleDevDelete(developerId);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
handleCommandError(error, 'dev delete');
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
dev
|
|
254
|
+
.command('down')
|
|
255
|
+
.description('Stop Mutagen sync sessions for this developer (and optionally app containers)')
|
|
256
|
+
.option('--apps', 'Also stop running app containers for this developer')
|
|
257
|
+
.action(async(options) => {
|
|
258
|
+
try {
|
|
259
|
+
const { handleDevDown } = require('../commands/dev-down');
|
|
260
|
+
await handleDevDown(options);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
handleCommandError(error, 'dev down');
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Register dev list/add/update/pin/delete commands (remote only).
|
|
270
|
+
* @param {Command} dev - dev subcommand group
|
|
271
|
+
*/
|
|
272
|
+
function setupDevUserCommands(dev) {
|
|
273
|
+
setupDevListAddCommands(dev);
|
|
274
|
+
setupDevUpdatePinDeleteCommands(dev);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Sets up developer configuration commands
|
|
279
|
+
* @param {Command} program - Commander program instance
|
|
280
|
+
*/
|
|
281
|
+
function setupDevCommands(program) {
|
|
282
|
+
const dev = program
|
|
283
|
+
.command('dev')
|
|
284
|
+
.description('Developer configuration and isolation');
|
|
285
|
+
|
|
286
|
+
setupDevConfigCommands(dev);
|
|
287
|
+
setupDevInitCommand(dev);
|
|
288
|
+
setupDevUserCommands(dev);
|
|
289
|
+
}
|
|
290
|
+
|
|
101
291
|
module.exports = { setupDevCommands };
|
|
@@ -25,28 +25,38 @@ function setupEnvironmentCommands(program) {
|
|
|
25
25
|
|
|
26
26
|
const environment = program
|
|
27
27
|
.command('environment')
|
|
28
|
-
.description('
|
|
28
|
+
.description('Deploy and manage Miso Controller environments (dev, tst, pro, miso)');
|
|
29
|
+
|
|
30
|
+
const deployExamples = `
|
|
31
|
+
Examples:
|
|
32
|
+
$ aifabrix environment deploy dev
|
|
33
|
+
$ aifabrix environment deploy tst --preset m
|
|
34
|
+
$ aifabrix environment deploy dev --config ./env-config.json --no-poll`;
|
|
29
35
|
|
|
30
36
|
environment
|
|
31
37
|
.command('deploy <env>')
|
|
32
|
-
.description('Deploy
|
|
33
|
-
.option('--config <file>', 'Environment configuration file')
|
|
38
|
+
.description('Deploy environment infrastructure in Miso Controller (run before deploy <app>)')
|
|
39
|
+
.option('--config <file>', 'Environment configuration file (optional if --preset is used)')
|
|
40
|
+
.option('--preset <size>', 'Environment size preset: s, m, l, xl (default: s)', 's')
|
|
34
41
|
.option('--skip-validation', 'Skip environment validation')
|
|
35
42
|
.option('--poll', 'Poll for deployment status', true)
|
|
36
43
|
.option('--no-poll', 'Do not poll for status')
|
|
44
|
+
.addHelpText('after', deployExamples)
|
|
37
45
|
.action(deployEnvHandler);
|
|
38
46
|
|
|
39
47
|
const env = program
|
|
40
48
|
.command('env')
|
|
41
|
-
.description('
|
|
49
|
+
.description('Deploy and manage Miso Controller environments (alias for environment)');
|
|
42
50
|
|
|
43
51
|
env
|
|
44
52
|
.command('deploy <env>')
|
|
45
|
-
.description('Deploy
|
|
46
|
-
.option('--config <file>', 'Environment configuration file')
|
|
53
|
+
.description('Deploy environment infrastructure in Miso Controller (run before deploy <app>)')
|
|
54
|
+
.option('--config <file>', 'Environment configuration file (optional if --preset is used)')
|
|
55
|
+
.option('--preset <size>', 'Environment size preset: s, m, l, xl (default: s)', 's')
|
|
47
56
|
.option('--skip-validation', 'Skip environment validation')
|
|
48
57
|
.option('--poll', 'Poll for deployment status', true)
|
|
49
58
|
.option('--no-poll', 'Do not poll for status')
|
|
59
|
+
.addHelpText('after', deployExamples)
|
|
50
60
|
.action(deployEnvHandler);
|
|
51
61
|
}
|
|
52
62
|
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI external system command setup (download,
|
|
2
|
+
* CLI external system command setup (download, upload, delete, test-integration).
|
|
3
|
+
*
|
|
4
|
+
* Registers these commands on the Commander program:
|
|
5
|
+
* - download <system-key> – Download external system from dataplane to integration/<system-key>/
|
|
6
|
+
* - upload <system-key> – Upload to dataplane (validate → publish; no controller deploy)
|
|
7
|
+
* - delete <system-key> – Delete external system and associated datasources from dataplane
|
|
8
|
+
* - test-integration <app> – Run integration tests (builder: in container; external: via dataplane pipeline)
|
|
3
9
|
*
|
|
4
10
|
* @fileoverview External system command definitions for AI Fabrix Builder CLI
|
|
5
11
|
* @author AI Fabrix Team
|
|
6
12
|
* @version 2.0.0
|
|
13
|
+
* @see docs/commands/external-integration.md - User-facing command reference
|
|
14
|
+
* @see docs/external-systems.md - External systems guide and workflow
|
|
7
15
|
*/
|
|
8
16
|
|
|
9
17
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
@@ -11,11 +19,18 @@ const { handleCommandError } = require('../utils/cli-utils');
|
|
|
11
19
|
function setupDownloadCommand(program) {
|
|
12
20
|
program.command('download <system-key>')
|
|
13
21
|
.description('Download external system from dataplane to local development structure')
|
|
22
|
+
.option('--format <format>', 'Output format: json | yaml (default: yaml or config format)')
|
|
14
23
|
.option('--dry-run', 'Show what would be downloaded without actually downloading')
|
|
24
|
+
.option('--force', 'Overwrite existing README.md without prompting')
|
|
15
25
|
.action(async(systemKey, options) => {
|
|
16
26
|
try {
|
|
27
|
+
const config = require('../core/config');
|
|
28
|
+
const effectiveFormat = (options.format || (await config.getFormat()) || 'yaml').trim().toLowerCase();
|
|
29
|
+
if (effectiveFormat !== 'json' && effectiveFormat !== 'yaml') {
|
|
30
|
+
throw new Error('Option --format must be \'json\' or \'yaml\'');
|
|
31
|
+
}
|
|
17
32
|
const download = require('../external-system/download');
|
|
18
|
-
await download.downloadExternalSystem(systemKey, options);
|
|
33
|
+
await download.downloadExternalSystem(systemKey, { ...options, format: effectiveFormat });
|
|
19
34
|
} catch (error) {
|
|
20
35
|
handleCommandError(error, 'download');
|
|
21
36
|
process.exit(1);
|
|
@@ -27,7 +42,6 @@ function setupUploadCommand(program) {
|
|
|
27
42
|
program.command('upload <system-key>')
|
|
28
43
|
.description('Upload external system to dataplane (upload → validate → publish; no controller deploy)')
|
|
29
44
|
.option('--dry-run', 'Validate and build payload only; no API calls')
|
|
30
|
-
.option('--dataplane <url>', 'Dataplane URL (default: discovered from controller)')
|
|
31
45
|
.action(async(systemKey, options) => {
|
|
32
46
|
try {
|
|
33
47
|
const upload = require('../commands/upload');
|
|
@@ -56,35 +70,86 @@ function setupDeleteCommand(program) {
|
|
|
56
70
|
});
|
|
57
71
|
}
|
|
58
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Try to run builder-style test integration when app is not in builder or has no externalIntegration.
|
|
75
|
+
* @param {string} appName - App or system key
|
|
76
|
+
* @param {Object} options - CLI options
|
|
77
|
+
* @returns {Promise<boolean>} True if builder test was run, false otherwise
|
|
78
|
+
*/
|
|
79
|
+
async function tryBuilderTestIntegration(appName, options) {
|
|
80
|
+
const fsSync = require('fs');
|
|
81
|
+
const pathsUtil = require('../utils/paths');
|
|
82
|
+
const { getIntegrationPath, getBuilderPath } = pathsUtil;
|
|
83
|
+
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
84
|
+
const { loadConfigFile } = require('../utils/config-format');
|
|
85
|
+
const integrationPath = getIntegrationPath(appName);
|
|
86
|
+
let hasExternalIntegration = false;
|
|
87
|
+
try {
|
|
88
|
+
const integrationConfig = loadConfigFile(resolveApplicationConfigPath(integrationPath));
|
|
89
|
+
hasExternalIntegration = !!(integrationConfig && integrationConfig.externalIntegration);
|
|
90
|
+
} catch {
|
|
91
|
+
// integration path or config missing
|
|
92
|
+
}
|
|
93
|
+
if (!hasExternalIntegration) {
|
|
94
|
+
const builderPath = getBuilderPath(appName);
|
|
95
|
+
const builderConfigPath = resolveApplicationConfigPath(builderPath);
|
|
96
|
+
if (fsSync.existsSync(builderPath) && fsSync.existsSync(builderConfigPath)) {
|
|
97
|
+
const { runAppTestIntegration } = require('../commands/app-test');
|
|
98
|
+
const opts = { env: options.env || options.environment || 'dev' };
|
|
99
|
+
await runAppTestIntegration(appName, opts);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run external system integration test via dataplane and exit on failure.
|
|
108
|
+
* @param {string} appName - App or system key
|
|
109
|
+
* @param {Object} options - CLI options
|
|
110
|
+
* @returns {Promise<void>}
|
|
111
|
+
*/
|
|
112
|
+
async function runExternalSystemTestIntegration(appName, options) {
|
|
113
|
+
const test = require('../external-system/test');
|
|
114
|
+
const opts = { ...options, environment: options.env || options.environment, debug: options.debug };
|
|
115
|
+
const results = await test.testExternalSystemIntegration(appName, opts);
|
|
116
|
+
test.displayIntegrationTestResults(results, options.verbose);
|
|
117
|
+
if (!results.success) process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Run test-integration command: builder app in container or external system via dataplane.
|
|
122
|
+
* @param {string} appName - App or system key
|
|
123
|
+
* @param {Object} options - CLI options (datasource, payload, env, verbose, timeout)
|
|
124
|
+
* @returns {Promise<void>}
|
|
125
|
+
*/
|
|
126
|
+
async function runTestIntegrationCommand(appName, options) {
|
|
127
|
+
const pathsUtil = require('../utils/paths');
|
|
128
|
+
const appType = await pathsUtil.detectAppType(appName).catch(() => null);
|
|
129
|
+
if (appType && appType.baseDir === 'builder') {
|
|
130
|
+
const { runAppTestIntegration } = require('../commands/app-test');
|
|
131
|
+
const opts = { env: options.env || options.environment || 'dev' };
|
|
132
|
+
await runAppTestIntegration(appName, opts);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const ranBuilder = await tryBuilderTestIntegration(appName, options);
|
|
136
|
+
if (ranBuilder) return;
|
|
137
|
+
await runExternalSystemTestIntegration(appName, options);
|
|
138
|
+
}
|
|
139
|
+
|
|
59
140
|
function setupExternalSystemTestCommands(program) {
|
|
60
|
-
|
|
61
|
-
.description('Run unit tests for external system (local validation, no API calls)')
|
|
62
|
-
.option('-d, --datasource <key>', 'Test specific datasource only')
|
|
63
|
-
.option('-v, --verbose', 'Show detailed validation output')
|
|
64
|
-
.action(async(appName, options) => {
|
|
65
|
-
try {
|
|
66
|
-
const test = require('../external-system/test');
|
|
67
|
-
const results = await test.testExternalSystem(appName, options);
|
|
68
|
-
test.displayTestResults(results, options.verbose);
|
|
69
|
-
if (!results.valid) process.exit(1);
|
|
70
|
-
} catch (error) {
|
|
71
|
-
handleCommandError(error, 'test');
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
141
|
+
// 'test <app>' is registered in setup-app.js and dispatches by app type (builder vs external)
|
|
75
142
|
program.command('test-integration <app>')
|
|
76
|
-
.description('Run integration tests via dataplane pipeline API')
|
|
143
|
+
.description('Run integration tests (builder/docker app: in container; external system: via dataplane pipeline API)')
|
|
77
144
|
.option('-d, --datasource <key>', 'Test specific datasource only')
|
|
78
145
|
.option('-p, --payload <file>', 'Path to custom test payload file')
|
|
79
|
-
.option('--
|
|
146
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro (default: from aifabrix auth config)')
|
|
80
147
|
.option('-v, --verbose', 'Show detailed test output')
|
|
148
|
+
.option('--debug', 'Include debug output and write log to integration/<app>/logs/')
|
|
81
149
|
.option('--timeout <ms>', 'Request timeout in milliseconds', '30000')
|
|
82
150
|
.action(async(appName, options) => {
|
|
83
151
|
try {
|
|
84
|
-
|
|
85
|
-
const results = await test.testExternalSystemIntegration(appName, options);
|
|
86
|
-
test.displayIntegrationTestResults(results, options.verbose);
|
|
87
|
-
if (!results.success) process.exit(1);
|
|
152
|
+
await runTestIntegrationCommand(appName, options);
|
|
88
153
|
} catch (error) {
|
|
89
154
|
handleCommandError(error, 'test-integration');
|
|
90
155
|
process.exit(1);
|
package/lib/cli/setup-infra.js
CHANGED
|
@@ -12,13 +12,41 @@ const appLib = require('../app');
|
|
|
12
12
|
const validator = require('../validation/validator');
|
|
13
13
|
const config = require('../core/config');
|
|
14
14
|
const logger = require('../utils/logger');
|
|
15
|
-
const { handleCommandError } = require('../utils/cli-utils');
|
|
15
|
+
const { handleCommandError, isAuthenticationError } = require('../utils/cli-utils');
|
|
16
|
+
const { resolveControllerUrl } = require('../utils/controller-url');
|
|
17
|
+
const { handleLogin } = require('../commands/login');
|
|
16
18
|
const { handleUpMiso } = require('../commands/up-miso');
|
|
17
19
|
const { handleUpDataplane } = require('../commands/up-dataplane');
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {Object}
|
|
22
|
+
* Persists optional service flag to config when explicitly set.
|
|
23
|
+
* @param {Object} cfg - Config object (mutated)
|
|
24
|
+
* @param {string} key - Config key (traefik, pgadmin, redisCommander)
|
|
25
|
+
* @param {boolean} value - Value to set
|
|
26
|
+
* @param {string} label - Label for log message
|
|
27
|
+
*/
|
|
28
|
+
async function persistOptionalServiceFlag(cfg, key, value, label) {
|
|
29
|
+
cfg[key] = value;
|
|
30
|
+
await config.saveConfig(cfg);
|
|
31
|
+
logger.log(chalk.green(`✓ ${label} ${value ? 'enabled' : 'disabled'} and saved to config`));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolves effective boolean from option vs config.
|
|
36
|
+
* @param {*} optValue - options.traefik | options.pgAdmin | options.redisAdmin
|
|
37
|
+
* @param {*} cfgValue - cfg.traefik | cfg.pgadmin | cfg.redisCommander
|
|
38
|
+
* @param {boolean} defaultWhenUndef - Default when config value is undefined
|
|
39
|
+
* @returns {boolean}
|
|
40
|
+
*/
|
|
41
|
+
function resolveFlag(optValue, cfgValue, defaultWhenUndef = true) {
|
|
42
|
+
if (optValue === true) return true;
|
|
43
|
+
if (optValue === false) return false;
|
|
44
|
+
return cfgValue !== false && (cfgValue === true || defaultWhenUndef);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Runs the up-infra command: resolves developer ID, traefik, pgAdmin, redisAdmin, and starts infra.
|
|
49
|
+
* @param {Object} options - Commander options (developer, traefik, pgAdmin, redisAdmin)
|
|
22
50
|
* @returns {Promise<void>}
|
|
23
51
|
*/
|
|
24
52
|
async function runUpInfraCommand(options) {
|
|
@@ -35,23 +63,33 @@ async function runUpInfraCommand(options) {
|
|
|
35
63
|
logger.log(chalk.green(`✓ Developer ID set to ${id}`));
|
|
36
64
|
}
|
|
37
65
|
const cfg = await config.getConfig();
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
66
|
+
const flagSpecs = [
|
|
67
|
+
{ opt: options.traefik, key: 'traefik', label: 'Traefik' },
|
|
68
|
+
{ opt: options.pgAdmin, key: 'pgadmin', label: 'pgAdmin' },
|
|
69
|
+
{ opt: options.redisAdmin, key: 'redisCommander', label: 'Redis Commander' }
|
|
70
|
+
];
|
|
71
|
+
for (const { opt, key, label } of flagSpecs) {
|
|
72
|
+
if (opt === true || opt === false) {
|
|
73
|
+
await persistOptionalServiceFlag(cfg, key, opt, label);
|
|
74
|
+
}
|
|
46
75
|
}
|
|
47
|
-
|
|
48
|
-
|
|
76
|
+
await infra.startInfra(developerId, {
|
|
77
|
+
traefik: resolveFlag(options.traefik, cfg.traefik, false),
|
|
78
|
+
pgadmin: resolveFlag(options.pgAdmin, cfg.pgadmin, true),
|
|
79
|
+
redisCommander: resolveFlag(options.redisAdmin, cfg.redisCommander, true),
|
|
80
|
+
adminPwd: options.adminPwd
|
|
81
|
+
});
|
|
49
82
|
}
|
|
50
83
|
|
|
51
84
|
function setupUpInfraCommand(program) {
|
|
52
85
|
program.command('up-infra')
|
|
53
|
-
.description('Start local infrastructure: Postgres, Redis, optional Traefik')
|
|
86
|
+
.description('Start local infrastructure: Postgres, Redis, optional pgAdmin, Redis Commander, Traefik')
|
|
54
87
|
.option('-d, --developer <id>', 'Set developer ID and start infrastructure')
|
|
88
|
+
.option('--adminPwd <password>', 'Override default admin password for new install (Postgres, pgAdmin, Redis Commander)')
|
|
89
|
+
.option('--pgAdmin', 'Include pgAdmin web UI and save to config')
|
|
90
|
+
.option('--no-pgAdmin', 'Exclude pgAdmin and save to config')
|
|
91
|
+
.option('--redisAdmin', 'Include Redis Commander web UI and save to config')
|
|
92
|
+
.option('--no-redisAdmin', 'Exclude Redis Commander and save to config')
|
|
55
93
|
.option('--traefik', 'Include Traefik reverse proxy and save to config')
|
|
56
94
|
.option('--no-traefik', 'Exclude Traefik and save to config')
|
|
57
95
|
.action(async(options) => {
|
|
@@ -75,6 +113,18 @@ function setupUpPlatformCommand(program) {
|
|
|
75
113
|
await handleUpMiso(options);
|
|
76
114
|
await handleUpDataplane(options);
|
|
77
115
|
} catch (error) {
|
|
116
|
+
if (isAuthenticationError(error)) {
|
|
117
|
+
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
118
|
+
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
119
|
+
try {
|
|
120
|
+
await handleLogin({ method: 'device', controller: controllerUrl });
|
|
121
|
+
await handleUpDataplane(options);
|
|
122
|
+
return;
|
|
123
|
+
} catch (loginOrRetryError) {
|
|
124
|
+
handleCommandError(loginOrRetryError, 'up-platform');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
78
128
|
handleCommandError(error, 'up-platform');
|
|
79
129
|
process.exit(1);
|
|
80
130
|
}
|
|
@@ -107,6 +157,18 @@ function setupUpDataplaneCommand(program) {
|
|
|
107
157
|
try {
|
|
108
158
|
await handleUpDataplane(options);
|
|
109
159
|
} catch (error) {
|
|
160
|
+
if (isAuthenticationError(error)) {
|
|
161
|
+
const controllerUrl = error.controllerUrl || await resolveControllerUrl();
|
|
162
|
+
logger.log(chalk.blue('\nAuthentication required. Running aifabrix login...\n'));
|
|
163
|
+
try {
|
|
164
|
+
await handleLogin({ method: 'device', controller: controllerUrl });
|
|
165
|
+
await handleUpDataplane(options);
|
|
166
|
+
return;
|
|
167
|
+
} catch (loginOrRetryError) {
|
|
168
|
+
handleCommandError(loginOrRetryError, 'up-dataplane');
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
110
172
|
handleCommandError(error, 'up-dataplane');
|
|
111
173
|
process.exit(1);
|
|
112
174
|
}
|
|
@@ -148,7 +210,12 @@ function setupDoctorCommand(program) {
|
|
|
148
210
|
}
|
|
149
211
|
if (result.docker === 'ok') {
|
|
150
212
|
try {
|
|
151
|
-
const
|
|
213
|
+
const cfg = await config.getConfig();
|
|
214
|
+
const health = await infra.checkInfraHealth(null, {
|
|
215
|
+
pgadmin: cfg.pgadmin !== false,
|
|
216
|
+
redisCommander: cfg.redisCommander !== false,
|
|
217
|
+
traefik: !!cfg.traefik
|
|
218
|
+
});
|
|
152
219
|
logger.log('\n🏥 Infrastructure Health:');
|
|
153
220
|
Object.entries(health).forEach(([service, status]) => {
|
|
154
221
|
const icon = status === 'healthy' ? '✅' : status === 'unknown' ? '❓' : '❌';
|