@aifabrix/builder 2.44.4 → 2.44.6
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/cli-layout.mdc +1 -1
- package/.cursor/rules/project-rules.mdc +1 -1
- package/.npmrc.token +1 -1
- package/README.md +15 -23
- package/integration/hubspot-test/README.md +2 -0
- package/integration/hubspot-test/test.js +5 -3
- package/jest.projects.js +68 -17
- package/lib/api/controller-health.api.js +49 -0
- package/lib/api/dimension-values.api.js +82 -0
- package/lib/api/dimensions.api.js +114 -0
- package/lib/api/external-systems.api.js +1 -0
- package/lib/api/integration-clients.api.js +168 -0
- package/lib/api/types/dimension-values.types.js +28 -0
- package/lib/api/types/dimensions.types.js +31 -0
- package/lib/api/types/integration-clients.types.js +45 -0
- package/lib/api/types/wizard.types.js +2 -1
- package/lib/api/validation-runner.js +46 -25
- package/lib/app/deploy-config.js +11 -1
- package/lib/app/deploy-status-display.js +3 -3
- package/lib/app/deploy.js +36 -14
- package/lib/app/display.js +15 -11
- package/lib/app/push.js +46 -23
- package/lib/app/register.js +1 -1
- package/lib/app/restart-display.js +95 -0
- package/lib/app/rotate-secret.js +1 -1
- package/lib/app/run-container-start.js +12 -6
- package/lib/app/run-env-compose.js +30 -1
- package/lib/app/run-helpers.js +44 -12
- package/lib/app/run-reload-sync.js +148 -0
- package/lib/app/run-resolve-image.js +51 -1
- package/lib/app/run.js +99 -73
- package/lib/build/index.js +75 -45
- package/lib/cli/doctor-check.js +117 -0
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided.js +445 -0
- package/lib/cli/setup-app.help.js +1 -1
- package/lib/cli/setup-app.js +20 -2
- package/lib/cli/setup-app.test-commands.js +9 -5
- package/lib/cli/setup-auth.js +26 -0
- package/lib/cli/setup-dev-path-commands.js +50 -3
- package/lib/cli/setup-infra.js +138 -61
- package/lib/cli/setup-integration-client.js +182 -0
- package/lib/cli/setup-parameters.js +21 -2
- package/lib/cli/setup-platform.js +102 -0
- package/lib/cli/setup-secrets.js +18 -6
- package/lib/cli/setup-utility.js +97 -33
- package/lib/commands/datasource-capability-dimension-cli.js +128 -0
- package/lib/commands/datasource-capability-output.js +29 -0
- package/lib/commands/datasource-capability-relate-cli.js +140 -0
- package/lib/commands/datasource-capability.js +411 -0
- package/lib/commands/datasource-unified-test-cli.options.js +1 -1
- package/lib/commands/datasource.js +53 -13
- package/lib/commands/dev-down.js +3 -3
- package/lib/commands/dev-infra-gate.js +32 -0
- package/lib/commands/dev-init.js +13 -7
- package/lib/commands/dimension-value.js +179 -0
- package/lib/commands/dimension.js +330 -0
- package/lib/commands/integration-client.js +430 -0
- package/lib/commands/login-device.js +65 -30
- package/lib/commands/login.js +21 -10
- package/lib/commands/parameters-validate.js +78 -13
- package/lib/commands/repair-datasource-auto-rbac.js +166 -0
- package/lib/commands/repair-datasource-keys.js +10 -5
- package/lib/commands/repair-datasource.js +19 -7
- package/lib/commands/repair-env-template.js +4 -1
- package/lib/commands/repair-openapi-sync.js +172 -0
- package/lib/commands/repair-persist.js +102 -0
- package/lib/commands/repair-rbac-extract.js +27 -0
- package/lib/commands/repair-rbac-migrate.js +186 -0
- package/lib/commands/repair-rbac.js +225 -19
- package/lib/commands/repair-system-alignment.js +246 -0
- package/lib/commands/repair-system-permissions.js +168 -0
- package/lib/commands/repair.js +120 -354
- package/lib/commands/secure.js +1 -1
- package/lib/commands/setup-modes.js +455 -0
- package/lib/commands/setup-prompts.js +388 -0
- package/lib/commands/setup.js +149 -0
- package/lib/commands/teardown.js +228 -0
- package/lib/commands/test-e2e-external.js +4 -3
- package/lib/commands/up-common.js +97 -12
- package/lib/commands/up-dataplane.js +33 -11
- package/lib/commands/up-miso.js +7 -11
- package/lib/commands/upload.js +109 -23
- package/lib/commands/wizard-core-helpers.js +14 -11
- package/lib/commands/wizard-core.js +58 -15
- package/lib/commands/wizard-dataplane.js +2 -2
- package/lib/commands/wizard-entity-selection.js +72 -14
- package/lib/commands/wizard-headless.js +7 -3
- package/lib/commands/wizard-helpers.js +13 -1
- package/lib/commands/wizard.js +210 -61
- package/lib/constants/infra-compose-service-names.js +40 -0
- package/lib/core/env-reader.js +16 -3
- package/lib/core/secrets-admin-env.js +101 -0
- package/lib/core/secrets-ensure-infra.js +34 -1
- package/lib/core/secrets-ensure.js +88 -66
- package/lib/core/secrets-env-content.js +432 -0
- package/lib/core/secrets-env-write.js +27 -1
- package/lib/core/secrets-load.js +248 -0
- package/lib/core/secrets-names.js +32 -0
- package/lib/core/secrets.js +17 -757
- package/lib/datasource/capability/basic-exposure.js +76 -0
- package/lib/datasource/capability/capability-diff-slice.js +41 -0
- package/lib/datasource/capability/capability-key.js +34 -0
- package/lib/datasource/capability/capability-resolve.js +172 -0
- package/lib/datasource/capability/capability-storage-keys.js +22 -0
- package/lib/datasource/capability/copy-operations.js +348 -0
- package/lib/datasource/capability/copy-test-payload.js +139 -0
- package/lib/datasource/capability/create-operations.js +235 -0
- package/lib/datasource/capability/dimension-operations.js +151 -0
- package/lib/datasource/capability/dimension-validate.js +219 -0
- package/lib/datasource/capability/json-pointer.js +31 -0
- package/lib/datasource/capability/reference-rewrite.js +51 -0
- package/lib/datasource/capability/relate-operations.js +325 -0
- package/lib/datasource/capability/relate-validate.js +219 -0
- package/lib/datasource/capability/remove-operations.js +275 -0
- package/lib/datasource/capability/run-capability-copy.js +152 -0
- package/lib/datasource/capability/run-capability-diff.js +135 -0
- package/lib/datasource/capability/run-capability-dimension.js +291 -0
- package/lib/datasource/capability/run-capability-edit.js +377 -0
- package/lib/datasource/capability/run-capability-relate.js +193 -0
- package/lib/datasource/capability/run-capability-remove.js +105 -0
- package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
- package/lib/datasource/capability/validate-capability-slice.js +35 -0
- package/lib/datasource/list.js +136 -23
- package/lib/datasource/log-viewer.js +2 -4
- package/lib/datasource/unified-validation-run.js +51 -16
- package/lib/datasource/validate.js +53 -1
- package/lib/deployment/deploy-poll-ui.js +60 -0
- package/lib/deployment/deployer-status.js +29 -3
- package/lib/deployment/deployer.js +48 -30
- package/lib/deployment/environment.js +7 -2
- package/lib/deployment/poll-interval.js +72 -0
- package/lib/deployment/push.js +11 -9
- package/lib/external-system/deploy.js +4 -1
- package/lib/external-system/download.js +61 -32
- package/lib/external-system/sync-deploy-manifest.js +33 -0
- package/lib/generator/wizard-prompts.js +7 -1
- package/lib/generator/wizard.js +34 -0
- package/lib/infrastructure/index.js +49 -19
- package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
- package/lib/parameters/infra-kv-discovery.js +29 -4
- package/lib/parameters/infra-parameter-catalog.js +6 -3
- package/lib/parameters/infra-parameter-validate.js +67 -19
- package/lib/resolvers/datasource-resolver.js +53 -0
- package/lib/resolvers/dimension-file.js +52 -0
- package/lib/resolvers/manifest-resolver.js +133 -0
- package/lib/schema/external-datasource.schema.json +183 -53
- package/lib/schema/external-system.schema.json +23 -10
- package/lib/schema/infra.parameter.yaml +26 -11
- package/lib/schema/wizard-config.schema.json +2 -2
- package/lib/utils/aifabrix-config-dir-walk.js +40 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
- package/lib/utils/app-run-containers.js +2 -2
- package/lib/utils/bash-secret-env.js +59 -0
- package/lib/utils/cli-secrets-error-format.js +78 -0
- package/lib/utils/cli-test-layout-chalk.js +31 -9
- package/lib/utils/cli-utils.js +4 -36
- package/lib/utils/datasource-test-run-display.js +8 -0
- package/lib/utils/dev-hosts-helper.js +3 -2
- package/lib/utils/dev-init-ssh-merge.js +2 -1
- package/lib/utils/docker-build.js +17 -9
- package/lib/utils/docker-reload-mount.js +127 -0
- package/lib/utils/external-readme.js +117 -4
- package/lib/utils/external-system-local-test-tty.js +3 -2
- package/lib/utils/external-system-readiness-core.js +45 -12
- package/lib/utils/external-system-readiness-deploy-display.js +3 -3
- package/lib/utils/external-system-readiness-display-internals.js +33 -3
- package/lib/utils/external-system-readiness-display.js +10 -1
- package/lib/utils/file-upload.js +40 -3
- package/lib/utils/health-check-db-init.js +107 -0
- package/lib/utils/health-check-public-warn.js +69 -0
- package/lib/utils/health-check-url.js +19 -4
- package/lib/utils/health-check.js +135 -105
- package/lib/utils/help-builder.js +5 -1
- package/lib/utils/image-name.js +34 -7
- package/lib/utils/integration-file-backup.js +74 -0
- package/lib/utils/mutagen-install.js +30 -3
- package/lib/utils/paths.js +108 -25
- package/lib/utils/postgres-wipe.js +212 -0
- package/lib/utils/register-aifabrix-shell-env.js +15 -0
- package/lib/utils/remote-dev-auth.js +21 -5
- package/lib/utils/remote-docker-env.js +9 -1
- package/lib/utils/remote-secrets-loader.js +42 -3
- package/lib/utils/resolve-docker-image-ref.js +9 -3
- package/lib/utils/secrets-ancestor-paths.js +47 -0
- package/lib/utils/secrets-helpers.js +17 -10
- package/lib/utils/secrets-kv-refs.js +42 -0
- package/lib/utils/secrets-kv-scope.js +19 -2
- package/lib/utils/secrets-materialize-local.js +134 -0
- package/lib/utils/secrets-path.js +24 -10
- package/lib/utils/secrets-utils.js +2 -2
- package/lib/utils/system-builder-root.js +34 -0
- package/lib/utils/url-declarative-resolve-build.js +6 -1
- package/lib/utils/url-declarative-runtime-base-path.js +32 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
- package/lib/utils/urls-local-registry.js +73 -20
- package/lib/utils/validation-poll-ui.js +81 -0
- package/lib/utils/validation-run-poll.js +29 -5
- package/lib/utils/with-muted-logger.js +53 -0
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/env.template +8 -6
- package/templates/applications/miso-controller/application.yaml +7 -0
- package/templates/applications/miso-controller/env.template +7 -7
- package/templates/applications/miso-controller/rbac.yaml +9 -9
- package/templates/external-system/README.md.hbs +89 -102
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/lib/api/service-users.api.js +0 -150
- package/lib/api/types/service-users.types.js +0 -65
- package/lib/cli/setup-service-user.js +0 -187
- package/lib/commands/service-user.js +0 -429
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Integration clients API (Controller /api/v1/integration-clients)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ApiClient } = require('./index');
|
|
8
|
+
|
|
9
|
+
const BASE = '/api/v1/integration-clients';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create integration client; returns one-time clientSecret
|
|
13
|
+
* @requiresPermission {Controller} integration-client:create
|
|
14
|
+
* @async
|
|
15
|
+
* @function createIntegrationClient
|
|
16
|
+
* @param {string} controllerUrl - Controller base URL
|
|
17
|
+
* @param {Object} authConfig - Authentication configuration (bearer or client-credentials)
|
|
18
|
+
* @param {Object} body - Request body
|
|
19
|
+
* @param {string} body.key - Key (required)
|
|
20
|
+
* @param {string} body.displayName - Display name (required)
|
|
21
|
+
* @param {string[]} body.redirectUris - Redirect URIs (required, min 1)
|
|
22
|
+
* @param {string[]} [body.groupNames] - Group names (optional)
|
|
23
|
+
* @param {string} [body.description] - Optional description
|
|
24
|
+
* @param {string} [body.keycloakClientId] - Optional Keycloak client id
|
|
25
|
+
* @returns {Promise<Object>} API response
|
|
26
|
+
* @throws {Error} If request fails
|
|
27
|
+
*/
|
|
28
|
+
async function createIntegrationClient(controllerUrl, authConfig, body) {
|
|
29
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
30
|
+
const payload = {
|
|
31
|
+
key: body.key,
|
|
32
|
+
displayName: body.displayName,
|
|
33
|
+
redirectUris: body.redirectUris,
|
|
34
|
+
groupNames: Array.isArray(body.groupNames) ? body.groupNames : []
|
|
35
|
+
};
|
|
36
|
+
if (body.description !== undefined && body.description !== null && body.description !== '') {
|
|
37
|
+
payload.description = body.description;
|
|
38
|
+
}
|
|
39
|
+
if (body.keycloakClientId) {
|
|
40
|
+
payload.keycloakClientId = body.keycloakClientId;
|
|
41
|
+
}
|
|
42
|
+
return await client.post(BASE, { body: payload });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* List integration clients
|
|
47
|
+
* @requiresPermission {Controller} integration-client:read
|
|
48
|
+
* @async
|
|
49
|
+
* @function listIntegrationClients
|
|
50
|
+
* @param {string} controllerUrl - Controller base URL
|
|
51
|
+
* @param {Object} authConfig - Authentication configuration
|
|
52
|
+
* @param {Object} [options] - Query options
|
|
53
|
+
* @param {number} [options.page] - Page number
|
|
54
|
+
* @param {number} [options.pageSize] - Page size
|
|
55
|
+
* @param {string} [options.sort] - Sort
|
|
56
|
+
* @param {string} [options.filter] - Filter
|
|
57
|
+
* @param {string} [options.search] - Search
|
|
58
|
+
* @returns {Promise<Object>} API response
|
|
59
|
+
* @throws {Error} If request fails
|
|
60
|
+
*/
|
|
61
|
+
async function listIntegrationClients(controllerUrl, authConfig, options = {}) {
|
|
62
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
63
|
+
const params = {};
|
|
64
|
+
if (options.page !== undefined && options.page !== null) params.page = options.page;
|
|
65
|
+
if (options.pageSize !== undefined && options.pageSize !== null) params.pageSize = options.pageSize;
|
|
66
|
+
if (options.sort) params.sort = options.sort;
|
|
67
|
+
if (options.filter) params.filter = options.filter;
|
|
68
|
+
if (options.search) params.search = options.search;
|
|
69
|
+
return await client.get(BASE, { params });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get integration client by id
|
|
74
|
+
* @requiresPermission {Controller} integration-client:read
|
|
75
|
+
* @async
|
|
76
|
+
* @function getIntegrationClient
|
|
77
|
+
* @param {string} controllerUrl - Controller base URL
|
|
78
|
+
* @param {Object} authConfig - Authentication configuration
|
|
79
|
+
* @param {string} id - Integration client id
|
|
80
|
+
* @returns {Promise<Object>} API response
|
|
81
|
+
* @throws {Error} If request fails
|
|
82
|
+
*/
|
|
83
|
+
async function getIntegrationClient(controllerUrl, authConfig, id) {
|
|
84
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
85
|
+
return await client.get(`${BASE}/${encodeURIComponent(id)}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Regenerate client secret (shown once)
|
|
90
|
+
* @requiresPermission {Controller} integration-client:update
|
|
91
|
+
* @async
|
|
92
|
+
* @function regenerateIntegrationClientSecret
|
|
93
|
+
* @param {string} controllerUrl - Controller base URL
|
|
94
|
+
* @param {Object} authConfig - Authentication configuration
|
|
95
|
+
* @param {string} id - Integration client id
|
|
96
|
+
* @returns {Promise<Object>} API response
|
|
97
|
+
* @throws {Error} If request fails
|
|
98
|
+
*/
|
|
99
|
+
async function regenerateIntegrationClientSecret(controllerUrl, authConfig, id) {
|
|
100
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
101
|
+
return await client.post(`${BASE}/${encodeURIComponent(id)}/regenerate-secret`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Deactivate integration client
|
|
106
|
+
* @requiresPermission {Controller} integration-client:delete
|
|
107
|
+
* @async
|
|
108
|
+
* @function deleteIntegrationClient
|
|
109
|
+
* @param {string} controllerUrl - Controller base URL
|
|
110
|
+
* @param {Object} authConfig - Authentication configuration
|
|
111
|
+
* @param {string} id - Integration client id
|
|
112
|
+
* @returns {Promise<Object>} API response
|
|
113
|
+
* @throws {Error} If request fails
|
|
114
|
+
*/
|
|
115
|
+
async function deleteIntegrationClient(controllerUrl, authConfig, id) {
|
|
116
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
117
|
+
return await client.delete(`${BASE}/${encodeURIComponent(id)}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Replace group memberships
|
|
122
|
+
* @requiresPermission {Controller} integration-client:update
|
|
123
|
+
* @async
|
|
124
|
+
* @function updateIntegrationClientGroups
|
|
125
|
+
* @param {string} controllerUrl - Controller base URL
|
|
126
|
+
* @param {Object} authConfig - Authentication configuration
|
|
127
|
+
* @param {string} id - Integration client id
|
|
128
|
+
* @param {Object} body - Body with groupNames
|
|
129
|
+
* @param {string[]} body.groupNames - Group names
|
|
130
|
+
* @returns {Promise<Object>} API response
|
|
131
|
+
* @throws {Error} If request fails
|
|
132
|
+
*/
|
|
133
|
+
async function updateIntegrationClientGroups(controllerUrl, authConfig, id, body) {
|
|
134
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
135
|
+
return await client.put(`${BASE}/${encodeURIComponent(id)}/groups`, {
|
|
136
|
+
body: { groupNames: body.groupNames }
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Replace redirect URIs
|
|
142
|
+
* @requiresPermission {Controller} integration-client:update
|
|
143
|
+
* @async
|
|
144
|
+
* @function updateIntegrationClientRedirectUris
|
|
145
|
+
* @param {string} controllerUrl - Controller base URL
|
|
146
|
+
* @param {Object} authConfig - Authentication configuration
|
|
147
|
+
* @param {string} id - Integration client id
|
|
148
|
+
* @param {Object} body - Body with redirectUris
|
|
149
|
+
* @param {string[]} body.redirectUris - Redirect URIs (min 1)
|
|
150
|
+
* @returns {Promise<Object>} API response
|
|
151
|
+
* @throws {Error} If request fails
|
|
152
|
+
*/
|
|
153
|
+
async function updateIntegrationClientRedirectUris(controllerUrl, authConfig, id, body) {
|
|
154
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
155
|
+
return await client.put(`${BASE}/${encodeURIComponent(id)}/redirect-uris`, {
|
|
156
|
+
body: { redirectUris: body.redirectUris }
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = {
|
|
161
|
+
createIntegrationClient,
|
|
162
|
+
listIntegrationClients,
|
|
163
|
+
getIntegrationClient,
|
|
164
|
+
regenerateIntegrationClientSecret,
|
|
165
|
+
deleteIntegrationClient,
|
|
166
|
+
updateIntegrationClientGroups,
|
|
167
|
+
updateIntegrationClientRedirectUris
|
|
168
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dimension values API type definitions (Controller)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create dimension value payload
|
|
9
|
+
* @typedef {Object} DimensionValueCreateRequest
|
|
10
|
+
* @property {string} value
|
|
11
|
+
* @property {string} [displayName]
|
|
12
|
+
* @property {string} [description]
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Dimension value entity
|
|
17
|
+
* @typedef {Object} DimensionValue
|
|
18
|
+
* @property {string} id
|
|
19
|
+
* @property {string} dimensionId
|
|
20
|
+
* @property {string} value
|
|
21
|
+
* @property {string|null} [displayName]
|
|
22
|
+
* @property {string|null} [description]
|
|
23
|
+
* @property {string|null} [createdBy]
|
|
24
|
+
* @property {string|null} [updatedBy]
|
|
25
|
+
* @property {string} [createdAt]
|
|
26
|
+
* @property {string} [updatedAt]
|
|
27
|
+
*/
|
|
28
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dimensions API type definitions (Controller)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Dimension create/update payload (Controller catalog)
|
|
9
|
+
* @typedef {Object} DimensionCreateRequest
|
|
10
|
+
* @property {string} key
|
|
11
|
+
* @property {string} displayName
|
|
12
|
+
* @property {string} [description]
|
|
13
|
+
* @property {'string'|'number'|'boolean'} dataType
|
|
14
|
+
* @property {boolean} [isRequired]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Dimension entity
|
|
19
|
+
* @typedef {Object} Dimension
|
|
20
|
+
* @property {string} id
|
|
21
|
+
* @property {string} key
|
|
22
|
+
* @property {string} displayName
|
|
23
|
+
* @property {string|null} [description]
|
|
24
|
+
* @property {'string'|'number'|'boolean'} dataType
|
|
25
|
+
* @property {boolean} isRequired
|
|
26
|
+
* @property {string|null} [createdBy]
|
|
27
|
+
* @property {string|null} [updatedBy]
|
|
28
|
+
* @property {string} [createdAt]
|
|
29
|
+
* @property {string} [updatedAt]
|
|
30
|
+
*/
|
|
31
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Integration clients API type definitions (Controller camelCase)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Integration client create request body (builder → controller)
|
|
9
|
+
* @typedef {Object} IntegrationClientCreateRequest
|
|
10
|
+
* @property {string} key - Stable key (lowercase alphanumeric + hyphens)
|
|
11
|
+
* @property {string} displayName - Human-readable name
|
|
12
|
+
* @property {string[]} redirectUris - Allowed redirect URIs for OAuth2 (min 1)
|
|
13
|
+
* @property {string[]} [groupNames] - Optional group names (RBAC); omit or empty for OAuth-only clients
|
|
14
|
+
* @property {string} [description] - Optional description
|
|
15
|
+
* @property {string} [keycloakClientId] - Optional fixed Keycloak client id
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create response (clientSecret is one-time-only)
|
|
20
|
+
* @typedef {Object} IntegrationClientCreateResponseData
|
|
21
|
+
* @property {Object} [integrationClient] - Created record
|
|
22
|
+
* @property {string} [integrationClient.id] - Integration client id
|
|
23
|
+
* @property {string} [integrationClient.key] - Key
|
|
24
|
+
* @property {string} [integrationClient.displayName] - Display name
|
|
25
|
+
* @property {string} [integrationClient.keycloakClientId] - OAuth client id in Keycloak
|
|
26
|
+
* @property {string} [integrationClient.status] - Status
|
|
27
|
+
* @property {string} [clientSecret] - One-time secret
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Single integration client in list response
|
|
32
|
+
* @typedef {Object} ListIntegrationClientItem
|
|
33
|
+
* @property {string} id - Integration client id
|
|
34
|
+
* @property {string} [key] - Key
|
|
35
|
+
* @property {string} [displayName] - Display name
|
|
36
|
+
* @property {string} [keycloakClientId] - OAuth client id
|
|
37
|
+
* @property {string} [status] - Status (e.g. active)
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Regenerate secret response
|
|
42
|
+
* @typedef {Object} RegenerateIntegrationClientSecretResponse
|
|
43
|
+
* @property {Object} [data] - Nested data
|
|
44
|
+
* @property {string} [data.clientSecret] - New secret (one-time)
|
|
45
|
+
*/
|
|
@@ -260,12 +260,13 @@
|
|
|
260
260
|
* @property {string} [source.serverUrl] - MCP server URL (for mcp-server)
|
|
261
261
|
* @property {string} [source.token] - MCP token (for mcp-server, supports ${ENV_VAR})
|
|
262
262
|
* @property {string} [source.platform] - Known platform (for known-platform)
|
|
263
|
+
* @property {string} [source.entityName] - Entity from discover-entities (openapi-file / openapi-url); skips interactive Step 4.5 when valid
|
|
263
264
|
* @property {Object} [credential] - Credential configuration
|
|
264
265
|
* @property {string} credential.action - Action ('create' | 'select' | 'skip')
|
|
265
266
|
* @property {string} [credential.credentialIdOrKey] - Credential ID/key (for select)
|
|
266
267
|
* @property {Object} [credential.config] - Credential config (for create)
|
|
267
268
|
* @property {Object} [preferences] - Generation preferences
|
|
268
|
-
* @property {string} [preferences.intent] - User intent (any descriptive text)
|
|
269
|
+
* @property {string} [preferences.intent] - User intent (any descriptive text, max 1000 chars)
|
|
269
270
|
* @property {string} [preferences.fieldOnboardingLevel] - Field level ('full' | 'standard' | 'minimal')
|
|
270
271
|
* @property {boolean} [preferences.enableOpenAPIGeneration] - Enable OpenAPI generation
|
|
271
272
|
* @property {boolean} [preferences.enableMCP] - Enable MCP
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
const { extractTestRunId } = require('./validation-run.api');
|
|
10
10
|
const { postValidationRunWithTransportRetry } = require('../utils/validation-run-post-retry');
|
|
11
11
|
const { pollValidationRunUntilComplete } = require('../utils/validation-run-poll');
|
|
12
|
+
const { createValidationPollHandlers } = require('../utils/validation-poll-ui');
|
|
13
|
+
const logger = require('../utils/logger');
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* POST /api/v1/validation/run and (when async) poll GET until reportCompleteness is full.
|
|
@@ -20,6 +22,8 @@ const { pollValidationRunUntilComplete } = require('../utils/validation-run-poll
|
|
|
20
22
|
* @param {number} opts.timeoutMs
|
|
21
23
|
* @param {boolean} opts.useAsync
|
|
22
24
|
* @param {boolean} opts.noAsync
|
|
25
|
+
* @param {boolean} [opts.verbosePoll] - Throttled poll lines when no TTY poll UI (see validation-run-poll)
|
|
26
|
+
* @param {Function} [opts.onPollProgress] - Extra hook: `(envelope, attemptIndex, meta)` during poll
|
|
23
27
|
* @returns {Promise<{ envelope: Object|null, apiError: Object|null, pollTimedOut: boolean, incompleteNoAsync: boolean }>}
|
|
24
28
|
*/
|
|
25
29
|
/* eslint-disable max-lines-per-function, max-statements, complexity -- POST + poll orchestration */
|
|
@@ -54,31 +58,48 @@ async function postValidationRunAndOptionalPoll(opts) {
|
|
|
54
58
|
if (needsPoll && testRunId) {
|
|
55
59
|
const elapsed = Date.now() - started;
|
|
56
60
|
const remaining = Math.max(0, timeoutMs - elapsed);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
61
|
+
const deadlineMs = Date.now() + remaining;
|
|
62
|
+
|
|
63
|
+
logger.log('');
|
|
64
|
+
const pollUi = createValidationPollHandlers(deadlineMs);
|
|
65
|
+
const mergeOnPollProgress =
|
|
66
|
+
typeof opts.onPollProgress === 'function'
|
|
67
|
+
? (envelope, attemptIndex, meta) => {
|
|
68
|
+
pollUi.onPollProgress(envelope, attemptIndex, meta);
|
|
69
|
+
opts.onPollProgress(envelope, attemptIndex, meta);
|
|
70
|
+
}
|
|
71
|
+
: pollUi.onPollProgress;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const pollResult = await pollValidationRunUntilComplete({
|
|
75
|
+
dataplaneUrl,
|
|
76
|
+
authConfig,
|
|
77
|
+
testRunId,
|
|
78
|
+
budgetMs: remaining,
|
|
79
|
+
verbosePoll: verbosePoll === true,
|
|
80
|
+
pollRequestTimeoutMs:
|
|
81
|
+
Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined,
|
|
82
|
+
onPollProgress: mergeOnPollProgress
|
|
83
|
+
});
|
|
84
|
+
if (!pollResult.lastApiResult || !pollResult.lastApiResult.success) {
|
|
85
|
+
return {
|
|
86
|
+
envelope: pollResult.envelope,
|
|
87
|
+
apiError: pollResult.lastApiResult,
|
|
88
|
+
pollTimedOut: pollResult.timedOut,
|
|
89
|
+
incompleteNoAsync: false
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
envelope = pollResult.envelope;
|
|
93
|
+
if (pollResult.timedOut) {
|
|
94
|
+
return {
|
|
95
|
+
envelope,
|
|
96
|
+
apiError: null,
|
|
97
|
+
pollTimedOut: true,
|
|
98
|
+
incompleteNoAsync: false
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
} finally {
|
|
102
|
+
pollUi.finish();
|
|
82
103
|
}
|
|
83
104
|
}
|
|
84
105
|
|
package/lib/app/deploy-config.js
CHANGED
|
@@ -62,11 +62,21 @@ async function extractDeploymentConfig(options, _variables) {
|
|
|
62
62
|
const controllerUrl = await resolveControllerUrl();
|
|
63
63
|
const envKey = await resolveEnvironment();
|
|
64
64
|
|
|
65
|
+
const pollIntervalExplicit =
|
|
66
|
+
options.pollInterval !== undefined && options.pollInterval !== null
|
|
67
|
+
? Number(options.pollInterval)
|
|
68
|
+
: undefined;
|
|
69
|
+
|
|
65
70
|
return {
|
|
66
71
|
controllerUrl,
|
|
67
72
|
envKey,
|
|
68
73
|
poll: options.poll !== false,
|
|
69
|
-
|
|
74
|
+
// When true, polling still happens but is not rendered (no nested ora spinner).
|
|
75
|
+
// Used by guided installers which already show a top-level spinner.
|
|
76
|
+
silentPoll: options.silentPoll === true,
|
|
77
|
+
repositoryUrl: options.repositoryUrl,
|
|
78
|
+
// Omit default here so deployer can resolve 2s vs 5s from controller deploymentType (GET /api/v1/health)
|
|
79
|
+
pollInterval: Number.isFinite(pollIntervalExplicit) ? pollIntervalExplicit : undefined,
|
|
70
80
|
pollMaxAttempts: options.pollMaxAttempts || 60
|
|
71
81
|
};
|
|
72
82
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* @version 2.0.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const chalk = require('chalk');
|
|
9
8
|
const logger = require('../utils/logger');
|
|
9
|
+
const { formatSuccessLine, metadata } = require('../utils/cli-test-layout-chalk');
|
|
10
10
|
const { getApplicationStatus } = require('../api/applications.api');
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -69,9 +69,9 @@ async function displayAppUrlFromController(controllerUrl, envKey, appKey, authCo
|
|
|
69
69
|
url = buildAppUrlFromControllerAndPort(controllerUrl, port);
|
|
70
70
|
}
|
|
71
71
|
if (url) {
|
|
72
|
-
logger.log(
|
|
72
|
+
logger.log(formatSuccessLine(`App running at ${url}`));
|
|
73
73
|
} else {
|
|
74
|
-
logger.log(
|
|
74
|
+
logger.log(metadata('App deployed. Resolve URL from the controller dashboard.'));
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
package/lib/app/deploy.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const {
|
|
2
|
+
formatSuccessLine,
|
|
3
|
+
formatSuccessParagraph,
|
|
4
|
+
sectionTitle,
|
|
5
|
+
headerKeyValue,
|
|
6
|
+
metadata
|
|
7
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
2
8
|
/**
|
|
3
9
|
* AI Fabrix Builder Application Deployment Module
|
|
4
10
|
*
|
|
@@ -13,6 +19,8 @@ const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test
|
|
|
13
19
|
const fs = require('fs').promises;
|
|
14
20
|
const chalk = require('chalk');
|
|
15
21
|
const pushUtils = require('../deployment/push');
|
|
22
|
+
|
|
23
|
+
const SEP = chalk.gray('────────────────────────────────────────');
|
|
16
24
|
const logger = require('../utils/logger');
|
|
17
25
|
const { detectAppType, getBuilderPath, getIntegrationPath } = require('../utils/paths');
|
|
18
26
|
const { checkApplicationExists } = require('../utils/app-existence');
|
|
@@ -156,7 +164,10 @@ async function pushApp(appName, options = {}) {
|
|
|
156
164
|
* @throws {Error} If generation or validation fails
|
|
157
165
|
*/
|
|
158
166
|
async function generateAndValidateManifest(appName, options = {}) {
|
|
159
|
-
logger.log(
|
|
167
|
+
logger.log('');
|
|
168
|
+
logger.log(sectionTitle('Deployment manifest'));
|
|
169
|
+
logger.log(SEP);
|
|
170
|
+
logger.log(metadata(`Generating manifest for ${appName}...`));
|
|
160
171
|
const generator = require('../generator');
|
|
161
172
|
|
|
162
173
|
// generateDeployJson already validates against schema and throws on error
|
|
@@ -175,10 +186,10 @@ async function generateAndValidateManifest(appName, options = {}) {
|
|
|
175
186
|
*/
|
|
176
187
|
function displayDeploymentInfo(manifest, manifestPath) {
|
|
177
188
|
logger.log(formatSuccessLine(`Manifest generated: ${manifestPath}`));
|
|
178
|
-
logger.log(
|
|
179
|
-
logger.log(
|
|
180
|
-
logger.log(
|
|
181
|
-
logger.log(
|
|
189
|
+
logger.log(headerKeyValue('Key:', manifest.key));
|
|
190
|
+
logger.log(headerKeyValue('Display Name:', manifest.displayName));
|
|
191
|
+
logger.log(headerKeyValue('Image:', manifest.image));
|
|
192
|
+
logger.log(headerKeyValue('Port:', String(manifest.port)));
|
|
182
193
|
}
|
|
183
194
|
|
|
184
195
|
/**
|
|
@@ -189,7 +200,11 @@ function displayDeploymentInfo(manifest, manifestPath) {
|
|
|
189
200
|
* @returns {Promise<Object>} Deployment result
|
|
190
201
|
*/
|
|
191
202
|
async function executeDeployment(manifest, deploymentConfig) {
|
|
192
|
-
logger.log(
|
|
203
|
+
logger.log('');
|
|
204
|
+
logger.log(sectionTitle('Deploy to controller'));
|
|
205
|
+
logger.log(SEP);
|
|
206
|
+
logger.log(headerKeyValue('URL:', deploymentConfig.controllerUrl));
|
|
207
|
+
logger.log(headerKeyValue('Environment:', deploymentConfig.envKey));
|
|
193
208
|
const deployer = require('../deployment/deployer');
|
|
194
209
|
return await deployer.deployToController(
|
|
195
210
|
manifest,
|
|
@@ -199,7 +214,9 @@ async function executeDeployment(manifest, deploymentConfig) {
|
|
|
199
214
|
{
|
|
200
215
|
poll: deploymentConfig.poll,
|
|
201
216
|
pollInterval: deploymentConfig.pollInterval,
|
|
202
|
-
pollMaxAttempts: deploymentConfig.pollMaxAttempts
|
|
217
|
+
pollMaxAttempts: deploymentConfig.pollMaxAttempts,
|
|
218
|
+
repositoryUrl: deploymentConfig.repositoryUrl,
|
|
219
|
+
silentPoll: deploymentConfig.silentPoll === true
|
|
203
220
|
}
|
|
204
221
|
);
|
|
205
222
|
}
|
|
@@ -209,17 +226,22 @@ async function executeDeployment(manifest, deploymentConfig) {
|
|
|
209
226
|
* @param {Object} result - Deployment result
|
|
210
227
|
*/
|
|
211
228
|
function displayDeploymentResults(result) {
|
|
212
|
-
logger.log(
|
|
229
|
+
logger.log(formatSuccessParagraph('Deployment initiated successfully'));
|
|
213
230
|
if (result.deploymentUrl) {
|
|
214
|
-
logger.log(
|
|
231
|
+
logger.log(headerKeyValue('URL:', result.deploymentUrl));
|
|
215
232
|
}
|
|
216
233
|
if (result.deploymentId) {
|
|
217
|
-
logger.log(
|
|
234
|
+
logger.log(headerKeyValue('Deployment ID:', result.deploymentId));
|
|
218
235
|
}
|
|
219
236
|
if (result.status) {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
237
|
+
const st = result.status.status;
|
|
238
|
+
const statusText =
|
|
239
|
+
st === 'completed'
|
|
240
|
+
? formatSuccessLine(st)
|
|
241
|
+
: st === 'failed' || st === 'cancelled'
|
|
242
|
+
? chalk.red(`✖ ${st}`)
|
|
243
|
+
: chalk.yellow(`⏳ ${st}`);
|
|
244
|
+
logger.log(`${chalk.gray('Status:')} ${statusText}`);
|
|
223
245
|
}
|
|
224
246
|
}
|
|
225
247
|
|
package/lib/app/display.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
|
+
const { formatNextActions, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
2
2
|
/**
|
|
3
3
|
* Application Display Utilities
|
|
4
4
|
*
|
|
@@ -24,11 +24,13 @@ const logger = require('../utils/logger');
|
|
|
24
24
|
function displayExternalSystemSuccess(appName, config, location) {
|
|
25
25
|
logger.log(chalk.blue('Type: External System'));
|
|
26
26
|
logger.log(chalk.blue(`System Key: ${config.systemKey || appName}`));
|
|
27
|
-
logger.log(
|
|
28
|
-
logger.log(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
logger.log('');
|
|
28
|
+
logger.log(formatNextActions([
|
|
29
|
+
`Edit external system JSON files in ${location}`,
|
|
30
|
+
`Run: aifabrix validate ${appName}`,
|
|
31
|
+
'Run: aifabrix login',
|
|
32
|
+
`Run: aifabrix deploy ${appName}`
|
|
33
|
+
]));
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/**
|
|
@@ -49,11 +51,13 @@ function displayWebappSuccess(appName, config, envConversionMessage) {
|
|
|
49
51
|
|
|
50
52
|
logger.log(chalk.gray(envConversionMessage));
|
|
51
53
|
|
|
52
|
-
logger.log(
|
|
53
|
-
logger.log(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
logger.log('');
|
|
55
|
+
logger.log(formatNextActions([
|
|
56
|
+
'Copy env.template to .env and fill in your values',
|
|
57
|
+
'Run: aifabrix up-infra',
|
|
58
|
+
`Run: aifabrix build ${appName}`,
|
|
59
|
+
`Run: aifabrix run ${appName}`
|
|
60
|
+
]));
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
/**
|