@aifabrix/builder 2.40.0 → 2.40.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 +1 -1
- package/jest.config.manual.js +29 -0
- package/lib/cli/setup-auth.js +1 -0
- package/lib/cli/setup-utility.js +7 -1
- package/lib/commands/auth-status.js +36 -3
- package/lib/generator/wizard.js +5 -1
- package/lib/utils/paths.js +6 -0
- package/lib/validation/validate.js +1 -1
- package/package.json +3 -1
- package/templates/external-system/external-system.json.hbs +1 -16
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Install the AI Fabrix platform and test it locally. Then add external integratio
|
|
|
16
16
|
- **Full lifecycle in your version control:** Configuration, apps, and integrations live in your own VCS (GitHub, GitLab, Azure DevOps).
|
|
17
17
|
- **One tool from day one:** Single CLI for local infra, app and integration creation, build, run, and deploy—same workflow for apps and integrations.
|
|
18
18
|
- **Consistency and production readiness:** Schema-driven; deploy apps and integrations to the same controller/dataplane; production-ready secrets with `kv://` and Azure Key Vault.
|
|
19
|
-
- **Application development:** Use **[miso-client](https://github.com/esystemsdev/aifabrix-miso-client)**
|
|
19
|
+
- **Application development:** Use **[miso-client](https://github.com/esystemsdev/aifabrix-miso-client)** (TypeScript and Python) to talk to the dataplane and controller. The repo includes both TypeScript and Python SDKs; see [templates/applications/dataplane/README.md](templates/applications/dataplane/README.md) and the repo for usage.
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jest Configuration for Manual Tests (real API calls)
|
|
3
|
+
* Runs only tests/manual; requires user to be logged in (validated before run).
|
|
4
|
+
*
|
|
5
|
+
* @fileoverview Jest config for manual tests that call real Controller/Dataplane APIs
|
|
6
|
+
* @author AI Fabrix Team
|
|
7
|
+
* @version 2.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const baseProject = require('./jest.config').projects[0];
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
projects: [
|
|
14
|
+
{
|
|
15
|
+
...baseProject,
|
|
16
|
+
displayName: 'manual',
|
|
17
|
+
testMatch: [
|
|
18
|
+
'**/tests/manual/**/*.test.js'
|
|
19
|
+
],
|
|
20
|
+
testPathIgnorePatterns: [
|
|
21
|
+
'/node_modules/',
|
|
22
|
+
'\\\\node_modules\\\\'
|
|
23
|
+
],
|
|
24
|
+
setupFilesAfterEnv: ['<rootDir>/tests/manual/setup.js'],
|
|
25
|
+
testTimeout: 60000,
|
|
26
|
+
maxWorkers: 1
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
};
|
package/lib/cli/setup-auth.js
CHANGED
|
@@ -63,6 +63,7 @@ function setupAuthSubcommands(program) {
|
|
|
63
63
|
const auth = program.command('auth').description('Authentication commands');
|
|
64
64
|
auth.command('status')
|
|
65
65
|
.description('Display authentication status for current controller and environment')
|
|
66
|
+
.option('--validate', 'Exit with code 1 when not authenticated (for scripted use, e.g. manual test setup)')
|
|
66
67
|
.action(authStatusHandler);
|
|
67
68
|
auth.command('config')
|
|
68
69
|
.description('Configure authentication settings (controller, environment)')
|
package/lib/cli/setup-utility.js
CHANGED
|
@@ -183,11 +183,17 @@ function setupSplitJsonConvertShowCommands(program) {
|
|
|
183
183
|
function setupValidateDiffCommands(program) {
|
|
184
184
|
program.command('validate <appOrFile>')
|
|
185
185
|
.description('Validate application or external integration file')
|
|
186
|
+
.option('--format <format>', 'Output format: json | default (human-readable)')
|
|
186
187
|
.action(async(appOrFile, options) => {
|
|
187
188
|
try {
|
|
188
189
|
const validate = require('../validation/validate');
|
|
189
190
|
const result = await validate.validateAppOrFile(appOrFile, options);
|
|
190
|
-
|
|
191
|
+
const outFormat = (options.format || 'default').toLowerCase();
|
|
192
|
+
if (outFormat === 'json') {
|
|
193
|
+
logger.log(JSON.stringify(result, null, 2));
|
|
194
|
+
} else {
|
|
195
|
+
validate.displayValidationResults(result);
|
|
196
|
+
}
|
|
191
197
|
if (!result.valid) process.exit(1);
|
|
192
198
|
} catch (error) {
|
|
193
199
|
handleCommandError(error, 'validate');
|
|
@@ -317,10 +317,11 @@ function displayStatus(controllerUrl, environment, tokenInfo, dataplaneInfo) {
|
|
|
317
317
|
* Controller and environment come from config.yaml (set via aifabrix login or aifabrix auth config).
|
|
318
318
|
* @async
|
|
319
319
|
* @function handleAuthStatus
|
|
320
|
-
* @param {Object}
|
|
320
|
+
* @param {Object} options - Command options
|
|
321
|
+
* @param {boolean} [options.validate] - If true, exit with code 1 when not authenticated
|
|
321
322
|
* @returns {Promise<void>} Resolves when status is displayed
|
|
322
323
|
*/
|
|
323
|
-
async function handleAuthStatus(
|
|
324
|
+
async function handleAuthStatus(options = {}) {
|
|
324
325
|
const { resolveEnvironment } = require('../core/config');
|
|
325
326
|
const controllerUrl = await resolveControllerUrl();
|
|
326
327
|
const environment = await resolveEnvironment();
|
|
@@ -342,6 +343,38 @@ async function handleAuthStatus(_options) {
|
|
|
342
343
|
}
|
|
343
344
|
|
|
344
345
|
displayStatus(controllerUrl, environment, tokenInfo, dataplaneInfo);
|
|
346
|
+
|
|
347
|
+
if (options.validate && (!tokenInfo || !tokenInfo.authenticated)) {
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get resolved auth context (controller URL, environment, authConfig) for use after validation.
|
|
354
|
+
* Call only when auth status --validate has already passed (e.g. in manual tests).
|
|
355
|
+
* @async
|
|
356
|
+
* @function getValidatedAuthContext
|
|
357
|
+
* @returns {Promise<{controllerUrl: string, environment: string, authConfig: Object, dataplaneUrl: string|null}>}
|
|
358
|
+
* @throws {Error} If not authenticated
|
|
359
|
+
*/
|
|
360
|
+
async function getValidatedAuthContext() {
|
|
361
|
+
const { resolveEnvironment } = require('../core/config');
|
|
362
|
+
const controllerUrl = await resolveControllerUrl();
|
|
363
|
+
const environment = await resolveEnvironment();
|
|
364
|
+
|
|
365
|
+
let tokenInfo = await checkDeviceToken(controllerUrl);
|
|
366
|
+
if (!tokenInfo) {
|
|
367
|
+
tokenInfo = await checkClientToken(controllerUrl, environment);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!tokenInfo || !tokenInfo.authenticated || !tokenInfo.token) {
|
|
371
|
+
throw new Error('Not authenticated. Run "aifabrix login" or configure client credentials.');
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const authConfig = { type: 'bearer', token: tokenInfo.token };
|
|
375
|
+
const dataplaneUrl = await resolveDataplaneUrlSilent(controllerUrl, environment, authConfig);
|
|
376
|
+
|
|
377
|
+
return { controllerUrl, environment, authConfig, dataplaneUrl };
|
|
345
378
|
}
|
|
346
379
|
|
|
347
|
-
module.exports = { handleAuthStatus };
|
|
380
|
+
module.exports = { handleAuthStatus, getValidatedAuthContext };
|
package/lib/generator/wizard.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* @fileoverview Wizard file generator - saves dataplane-generated configurations to files
|
|
3
3
|
* @author AI Fabrix Team
|
|
4
4
|
* @version 2.0.0
|
|
5
|
+
*
|
|
6
|
+
* Standard credential-backed variable names (supplied at runtime from the selected credential;
|
|
7
|
+
* do not list in configuration array): CLIENTID, CLIENTSECRET, TOKENURL, APIKEY, USERNAME,
|
|
8
|
+
* PASSWORD, BASEURL. See docs/external-systems.md and docs/wizard.md.
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
const fs = require('fs').promises;
|
|
@@ -322,7 +326,7 @@ function addAuthenticationLines(lines, auth, authType) {
|
|
|
322
326
|
function addBaseUrlLines(lines, systemConfig) {
|
|
323
327
|
if (systemConfig.baseUrl || systemConfig.baseURL) {
|
|
324
328
|
lines.push('# API Base URL');
|
|
325
|
-
lines.push(`
|
|
329
|
+
lines.push(`BASEURL=${systemConfig.baseUrl || systemConfig.baseURL}`);
|
|
326
330
|
lines.push('');
|
|
327
331
|
}
|
|
328
332
|
}
|
package/lib/utils/paths.js
CHANGED
|
@@ -178,6 +178,12 @@ function checkGlobalProjectRoot() {
|
|
|
178
178
|
return null;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
// In test environment, allow temp dir as project root (Jest sets NODE_ENV=test / JEST_WORKER_ID)
|
|
182
|
+
const isTestEnv = process.env.NODE_ENV === 'test' || typeof process.env.JEST_WORKER_ID !== 'undefined';
|
|
183
|
+
if (isTestEnv) {
|
|
184
|
+
return globalRoot;
|
|
185
|
+
}
|
|
186
|
+
|
|
181
187
|
// Verify that __dirname is actually within globalRoot
|
|
182
188
|
const dirnameNormalized = path.resolve(__dirname);
|
|
183
189
|
const globalRootNormalized = path.resolve(globalRoot);
|
|
@@ -452,7 +452,7 @@ async function validateAppOrFile(appOrFile, options = {}) {
|
|
|
452
452
|
logOfflinePathWhenType(appPath);
|
|
453
453
|
|
|
454
454
|
if (isExternal) {
|
|
455
|
-
return await validateExternalSystemComplete(appName);
|
|
455
|
+
return await validateExternalSystemComplete(appName, options);
|
|
456
456
|
}
|
|
457
457
|
|
|
458
458
|
const appValidation = await validator.validateApplication(appName, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.40.
|
|
3
|
+
"version": "2.40.2",
|
|
4
4
|
"description": "AI Fabrix Local Fabric & Deployment SDK",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
"test:integration": "jest --config jest.config.integration.js --runInBand",
|
|
17
17
|
"test:integration:python": "cross-env TEST_LANGUAGE=python jest --config jest.config.integration.js --runInBand",
|
|
18
18
|
"test:integration:typescript": "cross-env TEST_LANGUAGE=typescript jest --config jest.config.integration.js --runInBand",
|
|
19
|
+
"test:manual": "jest --config jest.config.manual.js --runInBand",
|
|
19
20
|
"lint": "eslint . --ext .js",
|
|
20
21
|
"lint:fix": "eslint . --ext .js --fix",
|
|
21
22
|
"lint:ci": "eslint . --ext .js --format json --output-file eslint-report.json",
|
|
22
23
|
"dev": "node bin/aifabrix.js",
|
|
23
24
|
"build": "npm run lint && npm run test",
|
|
25
|
+
"build:ci": "npm run lint && npm run test:ci",
|
|
24
26
|
"pack": "npm run build && npm pack",
|
|
25
27
|
"validate": "npm run build",
|
|
26
28
|
"prepublishOnly": "npm run validate",
|
|
@@ -30,22 +30,7 @@
|
|
|
30
30
|
"toolPrefix": "{{systemKey}}"
|
|
31
31
|
}{{/if}},
|
|
32
32
|
"tags": [],
|
|
33
|
-
"configuration": [
|
|
34
|
-
{
|
|
35
|
-
"name": "BASE_URL",
|
|
36
|
-
"value": "{{#if baseUrl}}{{baseUrl}}{{else}}https://api.example.com{{/if}}",
|
|
37
|
-
"location": "variable",
|
|
38
|
-
"required": true,
|
|
39
|
-
"portalInput": {
|
|
40
|
-
"field": "text",
|
|
41
|
-
"label": "Base URL",
|
|
42
|
-
"placeholder": "https://api.example.com",
|
|
43
|
-
"validation": {
|
|
44
|
-
"required": true
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
]{{#if roles}},
|
|
33
|
+
"configuration": []{{#if roles}},
|
|
49
34
|
"roles": [
|
|
50
35
|
{{#each roles}}
|
|
51
36
|
{
|