@aifabrix/builder 2.31.1 → 2.32.2
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/README.md +9 -9
- package/integration/hubspot/README.md +2 -2
- package/integration/hubspot/hubspot-deploy-company.json +17 -14
- package/integration/hubspot/hubspot-deploy-contact.json +19 -16
- package/integration/hubspot/hubspot-deploy-deal.json +21 -18
- package/lib/api/types/datasources.types.js +31 -5
- package/lib/api/types/wizard.types.js +142 -0
- package/lib/api/wizard.api.js +177 -0
- package/lib/{app-config.js → app/config.js} +4 -4
- package/lib/{app-deploy.js → app/deploy.js} +8 -8
- package/lib/app/display.js +90 -0
- package/lib/{app-dockerfile.js → app/dockerfile.js} +4 -4
- package/lib/{app-down.js → app/down.js} +4 -4
- package/lib/app/helpers.js +218 -0
- package/lib/app/index.js +298 -0
- package/lib/{app-list.js → app/list.js} +6 -6
- package/lib/{app-push.js → app/push.js} +4 -4
- package/lib/{app-readme.js → app/readme.js} +34 -13
- package/lib/{app-register.js → app/register.js} +9 -9
- package/lib/{app-rotate-secret.js → app/rotate-secret.js} +10 -10
- package/lib/{app-run-helpers.js → app/run-helpers.js} +10 -10
- package/lib/{app-run.js → app/run.js} +6 -6
- package/lib/{build.js → build/index.js} +59 -32
- package/lib/build/package.json +7 -0
- package/lib/cli.js +245 -179
- package/lib/commands/app.js +3 -3
- package/lib/commands/datasource.js +4 -4
- package/lib/commands/login-credentials.js +209 -0
- package/lib/commands/login-device.js +254 -0
- package/lib/commands/login.js +67 -378
- package/lib/commands/logout.js +1 -1
- package/lib/commands/secrets-set.js +1 -1
- package/lib/commands/secure.js +2 -2
- package/lib/commands/wizard.js +498 -0
- package/lib/{audit-logger.js → core/audit-logger.js} +1 -1
- package/lib/{config.js → core/config.js} +28 -26
- package/lib/{diff.js → core/diff.js} +157 -72
- package/lib/{secrets.js → core/secrets.js} +86 -49
- package/lib/{templates.js → core/templates-env.js} +14 -222
- package/lib/core/templates.js +279 -0
- package/lib/{datasource-deploy.js → datasource/deploy.js} +6 -6
- package/lib/{datasource-diff.js → datasource/diff.js} +2 -2
- package/lib/datasource/list.js +223 -0
- package/lib/{datasource-validate.js → datasource/validate.js} +2 -2
- package/lib/{deployer.js → deployment/deployer.js} +48 -18
- package/lib/{environment-deploy.js → deployment/environment.js} +163 -84
- package/lib/{push.js → deployment/push.js} +1 -1
- package/lib/external-system/deploy-helpers.js +145 -0
- package/lib/{external-system-deploy.js → external-system/deploy.js} +156 -111
- package/lib/external-system/download-helpers.js +114 -0
- package/lib/{external-system-download.js → external-system/download.js} +92 -135
- package/lib/{external-system-generator.js → external-system/generator.js} +15 -11
- package/lib/external-system/test-auth.js +40 -0
- package/lib/external-system/test-execution.js +84 -0
- package/lib/external-system/test-helpers.js +109 -0
- package/lib/{external-system-test.js → external-system/test.js} +174 -192
- package/lib/{generator-builders.js → generator/builders.js} +87 -10
- package/lib/{generator-external.js → generator/external.js} +115 -52
- package/lib/{github-generator.js → generator/github.js} +116 -15
- package/lib/{generator-helpers.js → generator/helpers.js} +92 -42
- package/lib/{generator.js → generator/index.js} +49 -22
- package/lib/{generator-split.js → generator/split.js} +108 -55
- package/lib/generator/wizard-prompts.js +357 -0
- package/lib/generator/wizard.js +490 -0
- package/lib/{infra.js → infrastructure/index.js} +49 -22
- package/lib/schema/external-datasource.schema.json +158 -136
- package/lib/schema/external-system.schema.json +43 -1
- package/lib/utils/api.js +9 -5
- package/lib/utils/app-register-api.js +60 -32
- package/lib/utils/app-register-auth.js +172 -47
- package/lib/utils/app-register-config.js +130 -59
- package/lib/utils/app-run-containers.js +29 -8
- package/lib/utils/build-helpers.js +1 -1
- package/lib/utils/cli-utils.js +78 -30
- package/lib/utils/compose-generator.js +145 -65
- package/lib/utils/config-paths.js +2 -0
- package/lib/utils/deployment-errors.js +1 -1
- package/lib/utils/device-code.js +99 -41
- package/lib/utils/env-config-loader.js +1 -1
- package/lib/utils/env-copy.js +21 -18
- package/lib/utils/env-endpoints.js +115 -67
- package/lib/utils/env-map.js +13 -14
- package/lib/utils/env-ports.js +45 -25
- package/lib/utils/env-template.js +84 -42
- package/lib/utils/error-formatter.js +26 -9
- package/lib/utils/error-formatters/error-parser.js +90 -4
- package/lib/utils/error-formatters/http-status-errors.js +54 -17
- package/lib/utils/error-formatters/network-errors.js +103 -26
- package/lib/utils/external-system-display.js +184 -90
- package/lib/utils/external-system-validators.js +164 -42
- package/lib/utils/file-upload.js +109 -0
- package/lib/utils/health-check.js +199 -83
- package/lib/utils/infra-containers.js +1 -1
- package/lib/utils/infra-status.js +66 -15
- package/lib/utils/local-secrets.js +45 -25
- package/lib/utils/paths.js +45 -33
- package/lib/utils/schema-loader.js +42 -25
- package/lib/utils/schema-resolver.js +123 -74
- package/lib/utils/secrets-encryption.js +62 -25
- package/lib/utils/secrets-helpers.js +126 -63
- package/lib/utils/secrets-path.js +1 -1
- package/lib/utils/secrets-url.js +1 -1
- package/lib/utils/token-manager-refresh.js +181 -0
- package/lib/utils/token-manager.js +76 -123
- package/lib/utils/variable-transformer.js +154 -77
- package/lib/utils/yaml-preserve.js +41 -47
- package/lib/{template-validator.js → validation/template.js} +54 -23
- package/lib/{validate.js → validation/validate.js} +205 -125
- package/lib/{validator.js → validation/validator.js} +58 -39
- package/package.json +31 -2
- package/templates/external-system/deploy.ps1.hbs +34 -0
- package/templates/external-system/deploy.sh.hbs +34 -0
- package/templates/external-system/external-datasource.json.hbs +31 -12
- package/lib/app.js +0 -467
- package/lib/datasource-list.js +0 -141
- /package/lib/{app-prompts.js → app/prompts.js} +0 -0
- /package/lib/{env-reader.js → core/env-reader.js} +0 -0
- /package/lib/{key-generator.js → core/key-generator.js} +0 -0
|
@@ -14,13 +14,14 @@ const path = require('path');
|
|
|
14
14
|
const os = require('os');
|
|
15
15
|
const yaml = require('js-yaml');
|
|
16
16
|
const chalk = require('chalk');
|
|
17
|
-
const { getExternalSystemConfig } = require('
|
|
18
|
-
const { getDeploymentAuth } = require('
|
|
19
|
-
const { getDataplaneUrl } = require('
|
|
20
|
-
const { getConfig } = require('
|
|
21
|
-
const { detectAppType } = require('
|
|
22
|
-
const logger = require('
|
|
23
|
-
const { generateEnvTemplate } = require('
|
|
17
|
+
const { getExternalSystemConfig } = require('../api/external-systems.api');
|
|
18
|
+
const { getDeploymentAuth } = require('../utils/token-manager');
|
|
19
|
+
const { getDataplaneUrl } = require('../datasource/deploy');
|
|
20
|
+
const { getConfig } = require('../core/config');
|
|
21
|
+
const { detectAppType } = require('../utils/paths');
|
|
22
|
+
const logger = require('../utils/logger');
|
|
23
|
+
const { generateEnvTemplate } = require('../utils/external-system-env-helpers');
|
|
24
|
+
const { generateVariablesYaml, generateReadme } = require('./download-helpers');
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Validates system type from downloaded application
|
|
@@ -49,30 +50,49 @@ function validateSystemType(application) {
|
|
|
49
50
|
* @param {Array} dataSources - Array of datasource configurations
|
|
50
51
|
* @throws {Error} If validation fails
|
|
51
52
|
*/
|
|
52
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Validates application configuration
|
|
55
|
+
* @function validateApplicationConfig
|
|
56
|
+
* @param {Object} application - Application configuration
|
|
57
|
+
* @throws {Error} If validation fails
|
|
58
|
+
*/
|
|
59
|
+
function validateApplicationConfig(application) {
|
|
53
60
|
if (!application || typeof application !== 'object') {
|
|
54
61
|
throw new Error('Application configuration is required');
|
|
55
62
|
}
|
|
56
|
-
|
|
57
63
|
if (!application.key || typeof application.key !== 'string') {
|
|
58
64
|
throw new Error('Application key is required');
|
|
59
65
|
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Validates datasource configuration
|
|
70
|
+
* @function validateDatasourceConfig
|
|
71
|
+
* @param {Object} datasource - Datasource configuration
|
|
72
|
+
* @param {string} applicationKey - Application key
|
|
73
|
+
* @throws {Error} If validation fails
|
|
74
|
+
*/
|
|
75
|
+
function validateDatasourceConfig(datasource, applicationKey) {
|
|
76
|
+
if (!datasource.key || typeof datasource.key !== 'string') {
|
|
77
|
+
throw new Error('Datasource key is required for all datasources');
|
|
78
|
+
}
|
|
79
|
+
if (!datasource.systemKey || typeof datasource.systemKey !== 'string') {
|
|
80
|
+
throw new Error('Datasource systemKey is required for all datasources');
|
|
81
|
+
}
|
|
82
|
+
if (datasource.systemKey !== applicationKey) {
|
|
83
|
+
throw new Error(`Datasource systemKey (${datasource.systemKey}) does not match application key (${applicationKey})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function validateDownloadedData(application, dataSources) {
|
|
88
|
+
validateApplicationConfig(application);
|
|
60
89
|
|
|
61
90
|
if (!Array.isArray(dataSources)) {
|
|
62
91
|
throw new Error('DataSources must be an array');
|
|
63
92
|
}
|
|
64
93
|
|
|
65
|
-
// Validate each datasource has required fields
|
|
66
94
|
for (const datasource of dataSources) {
|
|
67
|
-
|
|
68
|
-
throw new Error('Datasource key is required for all datasources');
|
|
69
|
-
}
|
|
70
|
-
if (!datasource.systemKey || typeof datasource.systemKey !== 'string') {
|
|
71
|
-
throw new Error('Datasource systemKey is required for all datasources');
|
|
72
|
-
}
|
|
73
|
-
if (datasource.systemKey !== application.key) {
|
|
74
|
-
throw new Error(`Datasource systemKey (${datasource.systemKey}) does not match application key (${application.key})`);
|
|
75
|
-
}
|
|
95
|
+
validateDatasourceConfig(datasource, application.key);
|
|
76
96
|
}
|
|
77
97
|
}
|
|
78
98
|
|
|
@@ -95,112 +115,6 @@ function handlePartialDownload(systemKey, systemData, datasourceErrors) {
|
|
|
95
115
|
);
|
|
96
116
|
}
|
|
97
117
|
|
|
98
|
-
/**
|
|
99
|
-
* Extract OAuth2 environment variables
|
|
100
|
-
* @param {Object} oauth2 - OAuth2 configuration
|
|
101
|
-
* @param {string} systemKey - System key
|
|
102
|
-
* @param {Array<string>} lines - Lines array to append to
|
|
103
|
-
*/
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Generates variables.yaml with externalIntegration block
|
|
107
|
-
* @param {string} systemKey - System key
|
|
108
|
-
* @param {Object} application - External system configuration
|
|
109
|
-
* @param {Array} dataSources - Array of datasource configurations
|
|
110
|
-
* @returns {Object} Variables YAML object
|
|
111
|
-
*/
|
|
112
|
-
function generateVariablesYaml(systemKey, application, dataSources) {
|
|
113
|
-
const systemFileName = `${systemKey}-deploy.json`;
|
|
114
|
-
const datasourceFiles = dataSources.map(ds => {
|
|
115
|
-
// Extract entity key from datasource key or use entityKey
|
|
116
|
-
const entityKey = ds.entityKey || ds.key.split('-').pop();
|
|
117
|
-
return `${systemKey}-deploy-${entityKey}.json`;
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
name: systemKey,
|
|
122
|
-
displayName: application.displayName || systemKey,
|
|
123
|
-
description: application.description || `External system integration for ${systemKey}`,
|
|
124
|
-
externalIntegration: {
|
|
125
|
-
schemaBasePath: './',
|
|
126
|
-
systems: [systemFileName],
|
|
127
|
-
dataSources: datasourceFiles,
|
|
128
|
-
autopublish: false,
|
|
129
|
-
version: application.version || '1.0.0'
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Generates README.md with setup instructions
|
|
136
|
-
* @param {string} systemKey - System key
|
|
137
|
-
* @param {Object} application - External system configuration
|
|
138
|
-
* @param {Array} dataSources - Array of datasource configurations
|
|
139
|
-
* @returns {string} README.md content
|
|
140
|
-
*/
|
|
141
|
-
function generateReadme(systemKey, application, dataSources) {
|
|
142
|
-
const displayName = application.displayName || systemKey;
|
|
143
|
-
const description = application.description || `External system integration for ${systemKey}`;
|
|
144
|
-
const systemType = application.type || 'unknown';
|
|
145
|
-
|
|
146
|
-
const lines = [
|
|
147
|
-
`# ${displayName}`,
|
|
148
|
-
'',
|
|
149
|
-
description,
|
|
150
|
-
'',
|
|
151
|
-
'## System Information',
|
|
152
|
-
'',
|
|
153
|
-
`- **System Key**: \`${systemKey}\``,
|
|
154
|
-
`- **System Type**: \`${systemType}\``,
|
|
155
|
-
`- **Datasources**: ${dataSources.length}`,
|
|
156
|
-
'',
|
|
157
|
-
'## Files',
|
|
158
|
-
'',
|
|
159
|
-
'- `variables.yaml` - Application configuration with externalIntegration block',
|
|
160
|
-
`- \`${systemKey}-deploy.json\` - External system definition`
|
|
161
|
-
];
|
|
162
|
-
|
|
163
|
-
dataSources.forEach(ds => {
|
|
164
|
-
const entityKey = ds.entityKey || ds.key.split('-').pop();
|
|
165
|
-
lines.push(`- \`${systemKey}-deploy-${entityKey}.json\` - Datasource: ${ds.displayName || ds.key}`);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
lines.push(
|
|
169
|
-
'- `env.template` - Environment variables template',
|
|
170
|
-
'',
|
|
171
|
-
'## Setup Instructions',
|
|
172
|
-
'',
|
|
173
|
-
'1. Review and update configuration files as needed',
|
|
174
|
-
'2. Set up environment variables in `env.template`',
|
|
175
|
-
'3. Run unit tests: `aifabrix test ${systemKey}`',
|
|
176
|
-
'4. Run integration tests: `aifabrix test-integration ${systemKey}`',
|
|
177
|
-
'5. Deploy: `aifabrix deploy ${systemKey} --environment dev`',
|
|
178
|
-
'',
|
|
179
|
-
'## Testing',
|
|
180
|
-
'',
|
|
181
|
-
'### Unit Tests',
|
|
182
|
-
'Run local validation without API calls:',
|
|
183
|
-
'```bash',
|
|
184
|
-
`aifabrix test ${systemKey}`,
|
|
185
|
-
'```',
|
|
186
|
-
'',
|
|
187
|
-
'### Integration Tests',
|
|
188
|
-
'Run integration tests via dataplane:',
|
|
189
|
-
'```bash',
|
|
190
|
-
`aifabrix test-integration ${systemKey} --environment dev`,
|
|
191
|
-
'```',
|
|
192
|
-
'',
|
|
193
|
-
'## Deployment',
|
|
194
|
-
'',
|
|
195
|
-
'Deploy to dataplane via miso-controller:',
|
|
196
|
-
'```bash',
|
|
197
|
-
`aifabrix deploy ${systemKey} --environment dev`,
|
|
198
|
-
'```'
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
return lines.join('\n');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
118
|
/**
|
|
205
119
|
* Setup authentication and get dataplane URL
|
|
206
120
|
* @async
|
|
@@ -264,18 +178,38 @@ async function downloadSystemConfiguration(dataplaneUrl, systemKey, authConfig)
|
|
|
264
178
|
* @returns {Promise<Object>} Object with file paths
|
|
265
179
|
* @throws {Error} If file generation fails
|
|
266
180
|
*/
|
|
267
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Generates system file
|
|
183
|
+
* @async
|
|
184
|
+
* @function generateSystemFile
|
|
185
|
+
* @param {string} tempDir - Temporary directory
|
|
186
|
+
* @param {string} systemKey - System key
|
|
187
|
+
* @param {Object} application - Application object
|
|
188
|
+
* @returns {Promise<string>} System file path
|
|
189
|
+
*/
|
|
190
|
+
async function generateSystemFile(tempDir, systemKey, application) {
|
|
268
191
|
const systemFileName = `${systemKey}-deploy.json`;
|
|
269
192
|
const systemFilePath = path.join(tempDir, systemFileName);
|
|
270
193
|
await fs.writeFile(systemFilePath, JSON.stringify(application, null, 2), 'utf8');
|
|
194
|
+
return systemFilePath;
|
|
195
|
+
}
|
|
271
196
|
|
|
272
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Generates datasource files
|
|
199
|
+
* @async
|
|
200
|
+
* @function generateDatasourceFiles
|
|
201
|
+
* @param {string} tempDir - Temporary directory
|
|
202
|
+
* @param {string} systemKey - System key
|
|
203
|
+
* @param {Array} dataSources - Array of datasource objects
|
|
204
|
+
* @returns {Promise<Object>} Object with datasourceFiles array and datasourceErrors array
|
|
205
|
+
*/
|
|
206
|
+
async function generateDatasourceFiles(tempDir, systemKey, dataSources) {
|
|
273
207
|
const datasourceErrors = [];
|
|
274
208
|
const datasourceFiles = [];
|
|
275
209
|
for (const datasource of dataSources) {
|
|
276
210
|
try {
|
|
277
|
-
const
|
|
278
|
-
const datasourceFileName = `${systemKey}-deploy-${
|
|
211
|
+
const entityType = datasource.entityType || datasource.entityKey || datasource.key.split('-').pop();
|
|
212
|
+
const datasourceFileName = `${systemKey}-deploy-${entityType}.json`;
|
|
279
213
|
const datasourceFilePath = path.join(tempDir, datasourceFileName);
|
|
280
214
|
await fs.writeFile(datasourceFilePath, JSON.stringify(datasource, null, 2), 'utf8');
|
|
281
215
|
datasourceFiles.push(datasourceFilePath);
|
|
@@ -283,12 +217,20 @@ async function generateFilesInTempDir(tempDir, systemKey, application, dataSourc
|
|
|
283
217
|
datasourceErrors.push(new Error(`Failed to write datasource ${datasource.key}: ${error.message}`));
|
|
284
218
|
}
|
|
285
219
|
}
|
|
220
|
+
return { datasourceFiles, datasourceErrors };
|
|
221
|
+
}
|
|
286
222
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Generates configuration files (variables.yaml, env.template, README.md)
|
|
225
|
+
* @async
|
|
226
|
+
* @function generateConfigFiles
|
|
227
|
+
* @param {string} tempDir - Temporary directory
|
|
228
|
+
* @param {string} systemKey - System key
|
|
229
|
+
* @param {Object} application - Application object
|
|
230
|
+
* @param {Array} dataSources - Array of datasource objects
|
|
231
|
+
* @returns {Promise<Object>} Object with file paths
|
|
232
|
+
*/
|
|
233
|
+
async function generateConfigFiles(tempDir, systemKey, application, dataSources) {
|
|
292
234
|
// Generate variables.yaml
|
|
293
235
|
const variables = generateVariablesYaml(systemKey, application, dataSources);
|
|
294
236
|
const variablesPath = path.join(tempDir, 'variables.yaml');
|
|
@@ -304,6 +246,21 @@ async function generateFilesInTempDir(tempDir, systemKey, application, dataSourc
|
|
|
304
246
|
const readmePath = path.join(tempDir, 'README.md');
|
|
305
247
|
await fs.writeFile(readmePath, readme, 'utf8');
|
|
306
248
|
|
|
249
|
+
return { variablesPath, envTemplatePath, readmePath };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function generateFilesInTempDir(tempDir, systemKey, application, dataSources) {
|
|
253
|
+
const systemFilePath = await generateSystemFile(tempDir, systemKey, application);
|
|
254
|
+
|
|
255
|
+
const { datasourceFiles, datasourceErrors } = await generateDatasourceFiles(tempDir, systemKey, dataSources);
|
|
256
|
+
|
|
257
|
+
// Handle partial downloads
|
|
258
|
+
if (datasourceErrors.length > 0) {
|
|
259
|
+
handlePartialDownload(systemKey, application, datasourceErrors);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const { variablesPath, envTemplatePath, readmePath } = await generateConfigFiles(tempDir, systemKey, application, dataSources);
|
|
263
|
+
|
|
307
264
|
return {
|
|
308
265
|
systemFilePath,
|
|
309
266
|
variablesPath,
|
|
@@ -490,7 +447,7 @@ module.exports = {
|
|
|
490
447
|
validateSystemType,
|
|
491
448
|
validateDownloadedData,
|
|
492
449
|
generateVariablesYaml,
|
|
493
|
-
generateEnvTemplate,
|
|
494
450
|
generateReadme,
|
|
451
|
+
generateEnvTemplate,
|
|
495
452
|
handlePartialDownload
|
|
496
453
|
};
|
|
@@ -14,7 +14,7 @@ const path = require('path');
|
|
|
14
14
|
const handlebars = require('handlebars');
|
|
15
15
|
const yaml = require('js-yaml');
|
|
16
16
|
const chalk = require('chalk');
|
|
17
|
-
const logger = require('
|
|
17
|
+
const logger = require('../utils/logger');
|
|
18
18
|
|
|
19
19
|
// Register Handlebars helper for equality check
|
|
20
20
|
handlebars.registerHelper('eq', (a, b) => a === b);
|
|
@@ -31,7 +31,7 @@ handlebars.registerHelper('eq', (a, b) => a === b);
|
|
|
31
31
|
*/
|
|
32
32
|
async function generateExternalSystemTemplate(appPath, systemKey, config) {
|
|
33
33
|
try {
|
|
34
|
-
const templatePath = path.join(__dirname, '..', 'templates', 'external-system', 'external-system.json.hbs');
|
|
34
|
+
const templatePath = path.join(__dirname, '..', '..', 'templates', 'external-system', 'external-system.json.hbs');
|
|
35
35
|
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
36
36
|
const template = handlebars.compile(templateContent);
|
|
37
37
|
|
|
@@ -70,7 +70,7 @@ async function generateExternalSystemTemplate(appPath, systemKey, config) {
|
|
|
70
70
|
*/
|
|
71
71
|
async function generateExternalDataSourceTemplate(appPath, datasourceKey, config) {
|
|
72
72
|
try {
|
|
73
|
-
const templatePath = path.join(__dirname, '..', 'templates', 'external-system', 'external-datasource.json.hbs');
|
|
73
|
+
const templatePath = path.join(__dirname, '..', '..', 'templates', 'external-system', 'external-datasource.json.hbs');
|
|
74
74
|
const templateContent = await fs.readFile(templatePath, 'utf8');
|
|
75
75
|
const template = handlebars.compile(templateContent);
|
|
76
76
|
|
|
@@ -79,9 +79,11 @@ async function generateExternalDataSourceTemplate(appPath, datasourceKey, config
|
|
|
79
79
|
datasourceDisplayName: config.datasourceDisplayName || datasourceKey.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
|
|
80
80
|
datasourceDescription: config.datasourceDescription || `External datasource for ${datasourceKey}`,
|
|
81
81
|
systemKey: config.systemKey,
|
|
82
|
-
|
|
82
|
+
entityType: config.entityType || datasourceKey.split('-').pop(),
|
|
83
83
|
resourceType: config.resourceType || 'document',
|
|
84
|
-
systemType: config.systemType || 'openapi'
|
|
84
|
+
systemType: config.systemType || 'openapi',
|
|
85
|
+
dimensions: config.dimensions || {},
|
|
86
|
+
attributes: config.attributes || {}
|
|
85
87
|
};
|
|
86
88
|
|
|
87
89
|
const rendered = template(context);
|
|
@@ -121,18 +123,20 @@ async function generateExternalSystemFiles(appPath, appName, config) {
|
|
|
121
123
|
const resourceTypes = ['customer', 'contact', 'person', 'document', 'deal'];
|
|
122
124
|
|
|
123
125
|
for (let i = 0; i < datasourceCount; i++) {
|
|
124
|
-
const
|
|
125
|
-
// For datasource key, use just the entity
|
|
126
|
-
const datasourceKey =
|
|
126
|
+
const entityType = `entity${i + 1}`;
|
|
127
|
+
// For datasource key, use just the entity type (will be prefixed with app-name-deploy-)
|
|
128
|
+
const datasourceKey = entityType;
|
|
127
129
|
const resourceType = resourceTypes[i % resourceTypes.length];
|
|
128
130
|
|
|
129
131
|
const datasourceConfig = {
|
|
130
132
|
systemKey: systemKey,
|
|
131
|
-
|
|
133
|
+
entityType: entityType,
|
|
132
134
|
resourceType: resourceType,
|
|
133
135
|
systemType: config.systemType || 'openapi',
|
|
134
|
-
datasourceDisplayName: `${config.systemDisplayName || systemKey} ${
|
|
135
|
-
datasourceDescription: `External datasource for ${
|
|
136
|
+
datasourceDisplayName: `${config.systemDisplayName || systemKey} ${entityType}`,
|
|
137
|
+
datasourceDescription: `External datasource for ${entityType} entity`,
|
|
138
|
+
dimensions: config.dimensions || {},
|
|
139
|
+
attributes: config.attributes || {}
|
|
136
140
|
};
|
|
137
141
|
|
|
138
142
|
// Generate with full naming: <app-name>-deploy-<entity-key>.json
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External System Test Authentication Helpers
|
|
3
|
+
*
|
|
4
|
+
* Authentication setup for integration tests
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Authentication helpers for external system testing
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { getDeploymentAuth } = require('../utils/token-manager');
|
|
12
|
+
const { getDataplaneUrl } = require('../datasource/deploy');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Setup authentication and get dataplane URL for integration tests
|
|
16
|
+
* @async
|
|
17
|
+
* @param {string} appName - Application name
|
|
18
|
+
* @param {Object} options - Test options
|
|
19
|
+
* @param {Object} config - Configuration object
|
|
20
|
+
* @returns {Promise<Object>} Object with authConfig and dataplaneUrl
|
|
21
|
+
* @throws {Error} If authentication fails
|
|
22
|
+
*/
|
|
23
|
+
async function setupIntegrationTestAuth(appName, options, config) {
|
|
24
|
+
const environment = options.environment || 'dev';
|
|
25
|
+
const controllerUrl = options.controller || config.deployment?.controllerUrl || 'http://localhost:3000';
|
|
26
|
+
const authConfig = await getDeploymentAuth(controllerUrl, environment, appName);
|
|
27
|
+
|
|
28
|
+
if (!authConfig.token && !authConfig.clientId) {
|
|
29
|
+
throw new Error('Authentication required. Run "aifabrix login" or "aifabrix app register" first.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const dataplaneUrl = await getDataplaneUrl(controllerUrl, appName, environment, authConfig);
|
|
33
|
+
|
|
34
|
+
return { authConfig, dataplaneUrl };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
setupIntegrationTestAuth
|
|
39
|
+
};
|
|
40
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External System Test Execution
|
|
3
|
+
*
|
|
4
|
+
* Test execution functions for integration tests
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Test execution utilities for external system testing
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const testHelpers = require('../utils/external-system-test-helpers');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Executes test for a single datasource
|
|
17
|
+
* @async
|
|
18
|
+
* @function executeDatasourceTest
|
|
19
|
+
* @param {string} systemKey - System key
|
|
20
|
+
* @param {string} datasourceKey - Datasource key
|
|
21
|
+
* @param {Object} payloadTemplate - Payload template
|
|
22
|
+
* @param {string} dataplaneUrl - Dataplane URL
|
|
23
|
+
* @param {Object} authConfig - Authentication configuration
|
|
24
|
+
* @param {Object} options - Test options
|
|
25
|
+
* @returns {Promise<Object>} Test result
|
|
26
|
+
*/
|
|
27
|
+
async function executeDatasourceTest(systemKey, datasourceKey, payloadTemplate, dataplaneUrl, authConfig, options) {
|
|
28
|
+
try {
|
|
29
|
+
const datasourceResult = await testHelpers.testSingleDatasource({
|
|
30
|
+
systemKey,
|
|
31
|
+
datasourceKey,
|
|
32
|
+
payloadTemplate,
|
|
33
|
+
dataplaneUrl,
|
|
34
|
+
authConfig,
|
|
35
|
+
timeout: parseInt(options.timeout, 10) || 30000
|
|
36
|
+
});
|
|
37
|
+
return datasourceResult;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
key: datasourceKey,
|
|
41
|
+
skipped: false,
|
|
42
|
+
success: false,
|
|
43
|
+
error: error.message
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Tests a single datasource integration
|
|
50
|
+
* @async
|
|
51
|
+
* @function testSingleDatasourceIntegration
|
|
52
|
+
* @param {Object} datasourceFile - Datasource file object
|
|
53
|
+
* @param {string} systemKey - System key
|
|
54
|
+
* @param {string} dataplaneUrl - Dataplane URL
|
|
55
|
+
* @param {Object} authConfig - Authentication configuration
|
|
56
|
+
* @param {Object} customPayload - Custom payload
|
|
57
|
+
* @param {Object} options - Test options
|
|
58
|
+
* @returns {Promise<Object>} Test result
|
|
59
|
+
*/
|
|
60
|
+
async function testSingleDatasourceIntegration(datasourceFile, systemKey, dataplaneUrl, authConfig, customPayload, options) {
|
|
61
|
+
const datasource = datasourceFile.data;
|
|
62
|
+
const datasourceKey = datasource.key;
|
|
63
|
+
|
|
64
|
+
logger.log(chalk.blue(`\n📡 Testing datasource: ${datasourceKey}`));
|
|
65
|
+
|
|
66
|
+
// Determine payload to use
|
|
67
|
+
const payloadTemplate = testHelpers.determinePayloadTemplate(datasource, datasourceKey, customPayload);
|
|
68
|
+
if (!payloadTemplate) {
|
|
69
|
+
logger.log(chalk.yellow(` ⚠ No test payload found for ${datasourceKey}, skipping...`));
|
|
70
|
+
return {
|
|
71
|
+
key: datasourceKey,
|
|
72
|
+
skipped: true,
|
|
73
|
+
reason: 'No test payload available'
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return await executeDatasourceTest(systemKey, datasourceKey, payloadTemplate, dataplaneUrl, authConfig, options);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
executeDatasourceTest,
|
|
82
|
+
testSingleDatasourceIntegration
|
|
83
|
+
};
|
|
84
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External System Test Helpers
|
|
3
|
+
*
|
|
4
|
+
* Helper functions for external system testing
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Test helper utilities for external system testing
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const externalSystemSchema = require('../schema/external-system.schema.json');
|
|
14
|
+
const { validateAgainstSchema } = require('../utils/external-system-validators');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initialize test results object
|
|
18
|
+
* @function initializeTestResults
|
|
19
|
+
* @returns {Object} Initial test results
|
|
20
|
+
*/
|
|
21
|
+
function initializeTestResults() {
|
|
22
|
+
return {
|
|
23
|
+
valid: true,
|
|
24
|
+
errors: [],
|
|
25
|
+
warnings: [],
|
|
26
|
+
systemResults: [],
|
|
27
|
+
datasourceResults: []
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validates system files against schema
|
|
33
|
+
* @function validateSystemFiles
|
|
34
|
+
* @param {Array} systemFiles - Array of system file objects with data property
|
|
35
|
+
* @param {Object} schema - External system schema
|
|
36
|
+
* @returns {Object} Validation results
|
|
37
|
+
*/
|
|
38
|
+
function validateSystemFiles(systemFiles, schema) {
|
|
39
|
+
const systemResults = [];
|
|
40
|
+
let valid = true;
|
|
41
|
+
const errors = [];
|
|
42
|
+
|
|
43
|
+
for (const systemFile of systemFiles) {
|
|
44
|
+
const validation = validateAgainstSchema(systemFile.data, schema);
|
|
45
|
+
if (!validation.valid) {
|
|
46
|
+
valid = false;
|
|
47
|
+
errors.push(...validation.errors);
|
|
48
|
+
}
|
|
49
|
+
systemResults.push({
|
|
50
|
+
file: systemFile.path || systemFile.file,
|
|
51
|
+
valid: validation.valid,
|
|
52
|
+
errors: validation.errors || []
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { valid, errors, systemResults };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validates system files and updates results
|
|
61
|
+
* @function validateSystemFilesForTest
|
|
62
|
+
* @param {Array} systemFiles - System files
|
|
63
|
+
* @param {Object} results - Test results object
|
|
64
|
+
*/
|
|
65
|
+
function validateSystemFilesForTest(systemFiles, results) {
|
|
66
|
+
logger.log(chalk.blue('📋 Validating system files...'));
|
|
67
|
+
const systemValidation = validateSystemFiles(systemFiles, externalSystemSchema);
|
|
68
|
+
results.valid = systemValidation.valid;
|
|
69
|
+
results.errors.push(...systemValidation.errors);
|
|
70
|
+
results.systemResults = systemValidation.systemResults;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Validates datasource files and updates results
|
|
75
|
+
* @function validateDatasourceFilesForTest
|
|
76
|
+
* @param {Array} datasourceFiles - Datasource files
|
|
77
|
+
* @param {Array} systemFiles - System files
|
|
78
|
+
* @param {Object} results - Test results object
|
|
79
|
+
* @param {Object} options - Test options
|
|
80
|
+
* @param {Function} validateSingleDatasource - Function to validate single datasource
|
|
81
|
+
* @param {Function} determineDatasourcesToTest - Function to determine datasources to test
|
|
82
|
+
*/
|
|
83
|
+
function validateDatasourceFilesForTest(datasourceFiles, systemFiles, results, options, validateSingleDatasource, determineDatasourcesToTest) {
|
|
84
|
+
logger.log(chalk.blue('📋 Validating datasource files...'));
|
|
85
|
+
const datasourcesToTest = determineDatasourcesToTest(datasourceFiles, options.datasource);
|
|
86
|
+
const systemKey = systemFiles.length > 0 ? systemFiles[0].data.key : null;
|
|
87
|
+
|
|
88
|
+
for (const datasourceFile of datasourcesToTest) {
|
|
89
|
+
const datasourceResult = validateSingleDatasource(
|
|
90
|
+
datasourceFile,
|
|
91
|
+
systemKey,
|
|
92
|
+
require('../schema/external-datasource.schema.json'),
|
|
93
|
+
options.verbose
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (!datasourceResult.valid) {
|
|
97
|
+
results.valid = false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
results.datasourceResults.push(datasourceResult);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
initializeTestResults,
|
|
106
|
+
validateSystemFilesForTest,
|
|
107
|
+
validateDatasourceFilesForTest
|
|
108
|
+
};
|
|
109
|
+
|