@aifabrix/builder 2.31.1 → 2.32.1

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.
Files changed (118) hide show
  1. package/README.md +9 -9
  2. package/integration/hubspot/README.md +2 -2
  3. package/integration/hubspot/hubspot-deploy-company.json +17 -14
  4. package/integration/hubspot/hubspot-deploy-contact.json +19 -16
  5. package/integration/hubspot/hubspot-deploy-deal.json +21 -18
  6. package/lib/api/types/datasources.types.js +31 -5
  7. package/lib/api/types/wizard.types.js +142 -0
  8. package/lib/api/wizard.api.js +177 -0
  9. package/lib/{app-config.js → app/config.js} +4 -4
  10. package/lib/{app-deploy.js → app/deploy.js} +8 -8
  11. package/lib/app/display.js +90 -0
  12. package/lib/{app-dockerfile.js → app/dockerfile.js} +4 -4
  13. package/lib/{app-down.js → app/down.js} +4 -4
  14. package/lib/app/helpers.js +218 -0
  15. package/lib/app/index.js +298 -0
  16. package/lib/{app-list.js → app/list.js} +6 -6
  17. package/lib/{app-push.js → app/push.js} +4 -4
  18. package/lib/{app-readme.js → app/readme.js} +34 -13
  19. package/lib/{app-register.js → app/register.js} +9 -9
  20. package/lib/{app-rotate-secret.js → app/rotate-secret.js} +10 -10
  21. package/lib/{app-run-helpers.js → app/run-helpers.js} +10 -10
  22. package/lib/{app-run.js → app/run.js} +6 -6
  23. package/lib/{build.js → build/index.js} +59 -32
  24. package/lib/build/package.json +7 -0
  25. package/lib/cli.js +245 -179
  26. package/lib/commands/app.js +3 -3
  27. package/lib/commands/datasource.js +4 -4
  28. package/lib/commands/login-credentials.js +209 -0
  29. package/lib/commands/login-device.js +254 -0
  30. package/lib/commands/login.js +67 -378
  31. package/lib/commands/logout.js +1 -1
  32. package/lib/commands/secrets-set.js +1 -1
  33. package/lib/commands/secure.js +2 -2
  34. package/lib/commands/wizard.js +498 -0
  35. package/lib/{audit-logger.js → core/audit-logger.js} +1 -1
  36. package/lib/{config.js → core/config.js} +28 -26
  37. package/lib/{diff.js → core/diff.js} +157 -72
  38. package/lib/{secrets.js → core/secrets.js} +86 -49
  39. package/lib/{templates.js → core/templates-env.js} +14 -222
  40. package/lib/core/templates.js +279 -0
  41. package/lib/{datasource-deploy.js → datasource/deploy.js} +6 -6
  42. package/lib/{datasource-diff.js → datasource/diff.js} +2 -2
  43. package/lib/datasource/list.js +223 -0
  44. package/lib/{datasource-validate.js → datasource/validate.js} +2 -2
  45. package/lib/{deployer.js → deployment/deployer.js} +48 -18
  46. package/lib/{environment-deploy.js → deployment/environment.js} +163 -84
  47. package/lib/{push.js → deployment/push.js} +1 -1
  48. package/lib/external-system/deploy-helpers.js +145 -0
  49. package/lib/{external-system-deploy.js → external-system/deploy.js} +156 -111
  50. package/lib/external-system/download-helpers.js +114 -0
  51. package/lib/{external-system-download.js → external-system/download.js} +92 -135
  52. package/lib/{external-system-generator.js → external-system/generator.js} +15 -11
  53. package/lib/external-system/test-auth.js +40 -0
  54. package/lib/external-system/test-execution.js +84 -0
  55. package/lib/external-system/test-helpers.js +109 -0
  56. package/lib/{external-system-test.js → external-system/test.js} +174 -192
  57. package/lib/{generator-builders.js → generator/builders.js} +87 -10
  58. package/lib/{generator-external.js → generator/external.js} +115 -52
  59. package/lib/{github-generator.js → generator/github.js} +116 -15
  60. package/lib/{generator-helpers.js → generator/helpers.js} +92 -42
  61. package/lib/{generator.js → generator/index.js} +49 -22
  62. package/lib/{generator-split.js → generator/split.js} +108 -55
  63. package/lib/generator/wizard-prompts.js +357 -0
  64. package/lib/generator/wizard.js +490 -0
  65. package/lib/{infra.js → infrastructure/index.js} +49 -22
  66. package/lib/schema/external-datasource.schema.json +145 -133
  67. package/lib/schema/external-system.schema.json +42 -0
  68. package/lib/utils/api.js +9 -5
  69. package/lib/utils/app-register-api.js +60 -32
  70. package/lib/utils/app-register-auth.js +172 -47
  71. package/lib/utils/app-register-config.js +130 -59
  72. package/lib/utils/app-run-containers.js +29 -8
  73. package/lib/utils/build-helpers.js +1 -1
  74. package/lib/utils/cli-utils.js +78 -30
  75. package/lib/utils/compose-generator.js +145 -65
  76. package/lib/utils/config-paths.js +2 -0
  77. package/lib/utils/deployment-errors.js +1 -1
  78. package/lib/utils/device-code.js +99 -41
  79. package/lib/utils/env-config-loader.js +1 -1
  80. package/lib/utils/env-copy.js +21 -18
  81. package/lib/utils/env-endpoints.js +115 -67
  82. package/lib/utils/env-map.js +13 -14
  83. package/lib/utils/env-ports.js +45 -25
  84. package/lib/utils/env-template.js +84 -42
  85. package/lib/utils/error-formatter.js +26 -9
  86. package/lib/utils/error-formatters/error-parser.js +90 -4
  87. package/lib/utils/error-formatters/http-status-errors.js +54 -17
  88. package/lib/utils/error-formatters/network-errors.js +103 -26
  89. package/lib/utils/external-system-display.js +184 -90
  90. package/lib/utils/external-system-validators.js +164 -42
  91. package/lib/utils/file-upload.js +109 -0
  92. package/lib/utils/health-check.js +199 -83
  93. package/lib/utils/infra-containers.js +1 -1
  94. package/lib/utils/infra-status.js +66 -15
  95. package/lib/utils/local-secrets.js +45 -25
  96. package/lib/utils/paths.js +45 -33
  97. package/lib/utils/schema-loader.js +42 -25
  98. package/lib/utils/schema-resolver.js +123 -74
  99. package/lib/utils/secrets-encryption.js +62 -25
  100. package/lib/utils/secrets-helpers.js +126 -63
  101. package/lib/utils/secrets-path.js +1 -1
  102. package/lib/utils/secrets-url.js +1 -1
  103. package/lib/utils/token-manager-refresh.js +181 -0
  104. package/lib/utils/token-manager.js +76 -123
  105. package/lib/utils/variable-transformer.js +154 -77
  106. package/lib/utils/yaml-preserve.js +41 -47
  107. package/lib/{template-validator.js → validation/template.js} +54 -23
  108. package/lib/{validate.js → validation/validate.js} +205 -125
  109. package/lib/{validator.js → validation/validator.js} +58 -39
  110. package/package.json +31 -2
  111. package/templates/external-system/deploy.ps1.hbs +34 -0
  112. package/templates/external-system/deploy.sh.hbs +34 -0
  113. package/templates/external-system/external-datasource.json.hbs +31 -12
  114. package/lib/app.js +0 -467
  115. package/lib/datasource-list.js +0 -141
  116. /package/lib/{app-prompts.js → app/prompts.js} +0 -0
  117. /package/lib/{env-reader.js → core/env-reader.js} +0 -0
  118. /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('./api/external-systems.api');
18
- const { getDeploymentAuth } = require('./utils/token-manager');
19
- const { getDataplaneUrl } = require('./datasource-deploy');
20
- const { getConfig } = require('./config');
21
- const { detectAppType } = require('./utils/paths');
22
- const logger = require('./utils/logger');
23
- const { generateEnvTemplate } = require('./utils/external-system-env-helpers');
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
- function validateDownloadedData(application, dataSources) {
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
- if (!datasource.key || typeof datasource.key !== 'string') {
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
- async function generateFilesInTempDir(tempDir, systemKey, application, dataSources) {
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
- // Generate datasource files
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 entityKey = datasource.entityKey || datasource.key.split('-').pop();
278
- const datasourceFileName = `${systemKey}-deploy-${entityKey}.json`;
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
- // Handle partial downloads
288
- if (datasourceErrors.length > 0) {
289
- handlePartialDownload(systemKey, application, datasourceErrors);
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('./utils/logger');
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
- entityKey: config.entityKey || datasourceKey.split('-').pop(),
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 entityKey = `entity${i + 1}`;
125
- // For datasource key, use just the entity key (will be prefixed with app-name-deploy-)
126
- const datasourceKey = entityKey;
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
- entityKey: entityKey,
133
+ entityType: entityType,
132
134
  resourceType: resourceType,
133
135
  systemType: config.systemType || 'openapi',
134
- datasourceDisplayName: `${config.systemDisplayName || systemKey} ${entityKey}`,
135
- datasourceDescription: `External datasource for ${entityKey} entity`
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
+