@axonflow/sdk 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client.d.ts +91 -2
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +315 -54
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/types/config.d.ts +5 -0
- package/dist/cjs/types/config.d.ts.map +1 -1
- package/dist/cjs/types/connector.d.ts +10 -0
- package/dist/cjs/types/connector.d.ts.map +1 -1
- package/dist/cjs/types/policies.d.ts +53 -54
- package/dist/cjs/types/policies.d.ts.map +1 -1
- package/dist/esm/client.d.ts +91 -2
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +315 -54
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/types/config.d.ts +5 -0
- package/dist/esm/types/config.d.ts.map +1 -1
- package/dist/esm/types/connector.d.ts +10 -0
- package/dist/esm/types/connector.d.ts.map +1 -1
- package/dist/esm/types/policies.d.ts +53 -54
- package/dist/esm/types/policies.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/esm/client.js
CHANGED
|
@@ -8,6 +8,7 @@ import { generateRequestId, debugLog } from './utils/helpers.js';
|
|
|
8
8
|
export class AxonFlow {
|
|
9
9
|
constructor(config) {
|
|
10
10
|
this.interceptors = [];
|
|
11
|
+
this.sessionCookie = null;
|
|
11
12
|
// Set defaults first to determine endpoint
|
|
12
13
|
const endpoint = config.endpoint || 'https://staging-eu.getaxonflow.com';
|
|
13
14
|
// Credentials are optional for community/self-hosted deployments
|
|
@@ -19,6 +20,7 @@ export class AxonFlow {
|
|
|
19
20
|
licenseKey: config.licenseKey,
|
|
20
21
|
endpoint,
|
|
21
22
|
orchestratorEndpoint: config.orchestratorEndpoint,
|
|
23
|
+
portalEndpoint: config.portalEndpoint,
|
|
22
24
|
mode: config.mode || (hasCredentials ? 'production' : 'sandbox'),
|
|
23
25
|
tenant: config.tenant || 'default',
|
|
24
26
|
debug: config.debug || false,
|
|
@@ -309,6 +311,56 @@ export class AxonFlow {
|
|
|
309
311
|
};
|
|
310
312
|
}
|
|
311
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Check the health of the AxonFlow Orchestrator service.
|
|
316
|
+
*
|
|
317
|
+
* @returns Promise resolving to health status
|
|
318
|
+
* @example
|
|
319
|
+
* ```typescript
|
|
320
|
+
* const health = await axonflow.orchestratorHealthCheck();
|
|
321
|
+
* if (health.status === 'healthy') {
|
|
322
|
+
* console.log('Orchestrator is healthy');
|
|
323
|
+
* }
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
async orchestratorHealthCheck() {
|
|
327
|
+
const url = `${this.getOrchestratorUrl()}/health`;
|
|
328
|
+
try {
|
|
329
|
+
const response = await fetch(url, {
|
|
330
|
+
method: 'GET',
|
|
331
|
+
signal: AbortSignal.timeout(this.config.timeout),
|
|
332
|
+
});
|
|
333
|
+
if (!response.ok) {
|
|
334
|
+
return {
|
|
335
|
+
status: 'unhealthy',
|
|
336
|
+
components: {
|
|
337
|
+
orchestrator: { status: 'error', message: `HTTP ${response.status}` },
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
const data = await response.json();
|
|
342
|
+
return {
|
|
343
|
+
status: data.status === 'healthy' ? 'healthy' : 'degraded',
|
|
344
|
+
version: data.version,
|
|
345
|
+
uptime: data.uptime,
|
|
346
|
+
components: data.components,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
if (this.config.debug) {
|
|
351
|
+
debugLog('Orchestrator health check failed', error);
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
status: 'unhealthy',
|
|
355
|
+
components: {
|
|
356
|
+
orchestrator: {
|
|
357
|
+
status: 'error',
|
|
358
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
}
|
|
312
364
|
/**
|
|
313
365
|
* Execute a query through AxonFlow with policy enforcement (Proxy Mode).
|
|
314
366
|
*
|
|
@@ -425,15 +477,9 @@ export class AxonFlow {
|
|
|
425
477
|
* List all available MCP connectors from the marketplace
|
|
426
478
|
*/
|
|
427
479
|
async listConnectors() {
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
signal: AbortSignal.timeout(this.config.timeout),
|
|
432
|
-
});
|
|
433
|
-
if (!response.ok) {
|
|
434
|
-
throw new Error(`Failed to list connectors: ${response.status} ${response.statusText}`);
|
|
435
|
-
}
|
|
436
|
-
const connectors = await response.json();
|
|
480
|
+
const response = await this.orchestratorRequest('GET', '/api/v1/connectors');
|
|
481
|
+
// Handle wrapped response
|
|
482
|
+
const connectors = Array.isArray(response) ? response : response.connectors || [];
|
|
437
483
|
if (this.config.debug) {
|
|
438
484
|
debugLog('Listed connectors', { count: connectors.length });
|
|
439
485
|
}
|
|
@@ -443,30 +489,41 @@ export class AxonFlow {
|
|
|
443
489
|
* Install an MCP connector from the marketplace
|
|
444
490
|
*/
|
|
445
491
|
async installConnector(request) {
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (this.config.licenseKey) {
|
|
452
|
-
headers['X-License-Key'] = this.config.licenseKey;
|
|
492
|
+
// Extract connector_id from request for URL path
|
|
493
|
+
const { connector_id, ...body } = request;
|
|
494
|
+
await this.orchestratorRequest('POST', `/api/v1/connectors/${connector_id}/install`, body);
|
|
495
|
+
if (this.config.debug) {
|
|
496
|
+
debugLog('Connector installed', { name: request.name });
|
|
453
497
|
}
|
|
454
|
-
|
|
455
|
-
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Uninstall an MCP connector
|
|
501
|
+
*/
|
|
502
|
+
async uninstallConnector(connectorName) {
|
|
503
|
+
await this.orchestratorRequest('DELETE', `/api/v1/connectors/${connectorName}`);
|
|
504
|
+
if (this.config.debug) {
|
|
505
|
+
debugLog('Connector uninstalled', { name: connectorName });
|
|
456
506
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
});
|
|
463
|
-
if (
|
|
464
|
-
|
|
465
|
-
throw new Error(`Failed to install connector: ${response.status} ${response.statusText} - ${errorText}`);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Get details for a specific connector by ID
|
|
510
|
+
*/
|
|
511
|
+
async getConnector(connectorId) {
|
|
512
|
+
const connector = await this.orchestratorRequest('GET', `/api/v1/connectors/${connectorId}`);
|
|
513
|
+
if (this.config.debug) {
|
|
514
|
+
debugLog('Got connector', { id: connectorId });
|
|
466
515
|
}
|
|
516
|
+
return connector;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Get health status of an installed connector
|
|
520
|
+
*/
|
|
521
|
+
async getConnectorHealth(connectorId) {
|
|
522
|
+
const health = await this.orchestratorRequest('GET', `/api/v1/connectors/${connectorId}/health`);
|
|
467
523
|
if (this.config.debug) {
|
|
468
|
-
debugLog('
|
|
524
|
+
debugLog('Got connector health', { id: connectorId, healthy: health.healthy });
|
|
469
525
|
}
|
|
526
|
+
return health;
|
|
470
527
|
}
|
|
471
528
|
/**
|
|
472
529
|
* Execute a query against an installed MCP connector
|
|
@@ -1191,17 +1248,15 @@ export class AxonFlow {
|
|
|
1191
1248
|
* @example
|
|
1192
1249
|
* ```typescript
|
|
1193
1250
|
* const policies = await axonflow.listDynamicPolicies({
|
|
1194
|
-
*
|
|
1251
|
+
* type: 'cost',
|
|
1195
1252
|
* enabled: true
|
|
1196
1253
|
* });
|
|
1197
1254
|
* ```
|
|
1198
1255
|
*/
|
|
1199
1256
|
async listDynamicPolicies(options) {
|
|
1200
1257
|
const params = new URLSearchParams();
|
|
1201
|
-
if (options?.
|
|
1202
|
-
params.set('
|
|
1203
|
-
if (options?.tier)
|
|
1204
|
-
params.set('tier', options.tier);
|
|
1258
|
+
if (options?.type)
|
|
1259
|
+
params.set('type', options.type);
|
|
1205
1260
|
if (options?.enabled !== undefined)
|
|
1206
1261
|
params.set('enabled', String(options.enabled));
|
|
1207
1262
|
if (options?.limit)
|
|
@@ -1215,11 +1270,11 @@ export class AxonFlow {
|
|
|
1215
1270
|
if (options?.search)
|
|
1216
1271
|
params.set('search', options.search);
|
|
1217
1272
|
const queryString = params.toString();
|
|
1218
|
-
const path = `/api/v1/policies${queryString ? `?${queryString}` : ''}`;
|
|
1273
|
+
const path = `/api/v1/policies/dynamic${queryString ? `?${queryString}` : ''}`;
|
|
1219
1274
|
if (this.config.debug) {
|
|
1220
1275
|
debugLog('Listing dynamic policies', { options });
|
|
1221
1276
|
}
|
|
1222
|
-
return this.
|
|
1277
|
+
return this.orchestratorRequest('GET', path);
|
|
1223
1278
|
}
|
|
1224
1279
|
/**
|
|
1225
1280
|
* Get a specific dynamic policy by ID.
|
|
@@ -1231,7 +1286,7 @@ export class AxonFlow {
|
|
|
1231
1286
|
if (this.config.debug) {
|
|
1232
1287
|
debugLog('Getting dynamic policy', { id });
|
|
1233
1288
|
}
|
|
1234
|
-
return this.
|
|
1289
|
+
return this.orchestratorRequest('GET', `/api/v1/policies/dynamic/${id}`);
|
|
1235
1290
|
}
|
|
1236
1291
|
/**
|
|
1237
1292
|
* Create a new dynamic policy.
|
|
@@ -1256,7 +1311,7 @@ export class AxonFlow {
|
|
|
1256
1311
|
if (this.config.debug) {
|
|
1257
1312
|
debugLog('Creating dynamic policy', { name: policy.name });
|
|
1258
1313
|
}
|
|
1259
|
-
return this.
|
|
1314
|
+
return this.orchestratorRequest('POST', '/api/v1/policies/dynamic', policy);
|
|
1260
1315
|
}
|
|
1261
1316
|
/**
|
|
1262
1317
|
* Update an existing dynamic policy.
|
|
@@ -1269,7 +1324,7 @@ export class AxonFlow {
|
|
|
1269
1324
|
if (this.config.debug) {
|
|
1270
1325
|
debugLog('Updating dynamic policy', { id, updates: Object.keys(policy) });
|
|
1271
1326
|
}
|
|
1272
|
-
return this.
|
|
1327
|
+
return this.orchestratorRequest('PUT', `/api/v1/policies/dynamic/${id}`, policy);
|
|
1273
1328
|
}
|
|
1274
1329
|
/**
|
|
1275
1330
|
* Delete a dynamic policy.
|
|
@@ -1280,7 +1335,7 @@ export class AxonFlow {
|
|
|
1280
1335
|
if (this.config.debug) {
|
|
1281
1336
|
debugLog('Deleting dynamic policy', { id });
|
|
1282
1337
|
}
|
|
1283
|
-
await this.
|
|
1338
|
+
await this.orchestratorRequest('DELETE', `/api/v1/policies/dynamic/${id}`);
|
|
1284
1339
|
}
|
|
1285
1340
|
/**
|
|
1286
1341
|
* Toggle a dynamic policy's enabled status.
|
|
@@ -1293,7 +1348,9 @@ export class AxonFlow {
|
|
|
1293
1348
|
if (this.config.debug) {
|
|
1294
1349
|
debugLog('Toggling dynamic policy', { id, enabled });
|
|
1295
1350
|
}
|
|
1296
|
-
return this.
|
|
1351
|
+
return this.orchestratorRequest('PATCH', `/api/v1/policies/dynamic/${id}`, {
|
|
1352
|
+
enabled,
|
|
1353
|
+
});
|
|
1297
1354
|
}
|
|
1298
1355
|
/**
|
|
1299
1356
|
* Get effective dynamic policies with tier inheritance applied.
|
|
@@ -1308,11 +1365,95 @@ export class AxonFlow {
|
|
|
1308
1365
|
if (options?.includeDisabled)
|
|
1309
1366
|
params.set('include_disabled', 'true');
|
|
1310
1367
|
const queryString = params.toString();
|
|
1311
|
-
const path = `/api/v1/policies/effective${queryString ? `?${queryString}` : ''}`;
|
|
1368
|
+
const path = `/api/v1/policies/dynamic/effective${queryString ? `?${queryString}` : ''}`;
|
|
1312
1369
|
if (this.config.debug) {
|
|
1313
1370
|
debugLog('Getting effective dynamic policies', { options });
|
|
1314
1371
|
}
|
|
1315
|
-
return this.
|
|
1372
|
+
return this.orchestratorRequest('GET', path);
|
|
1373
|
+
}
|
|
1374
|
+
// ============================================================================
|
|
1375
|
+
// Portal Authentication Methods (Enterprise)
|
|
1376
|
+
// ============================================================================
|
|
1377
|
+
/**
|
|
1378
|
+
* Login to Customer Portal and store session cookie.
|
|
1379
|
+
* Required before using Code Governance methods.
|
|
1380
|
+
*
|
|
1381
|
+
* @param orgId - Organization ID
|
|
1382
|
+
* @param password - Organization password
|
|
1383
|
+
* @returns Login response with session info
|
|
1384
|
+
*
|
|
1385
|
+
* @example
|
|
1386
|
+
* ```typescript
|
|
1387
|
+
* const login = await axonflow.loginToPortal('test-org-001', 'test123');
|
|
1388
|
+
* console.log(`Logged in as ${login.name}`);
|
|
1389
|
+
*
|
|
1390
|
+
* // Now you can use Code Governance methods
|
|
1391
|
+
* const providers = await axonflow.listGitProviders();
|
|
1392
|
+
* ```
|
|
1393
|
+
*/
|
|
1394
|
+
async loginToPortal(orgId, password) {
|
|
1395
|
+
const url = `${this.getPortalUrl()}/api/v1/auth/login`;
|
|
1396
|
+
const response = await fetch(url, {
|
|
1397
|
+
method: 'POST',
|
|
1398
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1399
|
+
body: JSON.stringify({ org_id: orgId, password }),
|
|
1400
|
+
signal: AbortSignal.timeout(this.config.timeout),
|
|
1401
|
+
});
|
|
1402
|
+
if (!response.ok) {
|
|
1403
|
+
const errorText = await response.text();
|
|
1404
|
+
throw new AuthenticationError(`Login failed: ${errorText}`);
|
|
1405
|
+
}
|
|
1406
|
+
const result = (await response.json());
|
|
1407
|
+
// Extract session cookie from response
|
|
1408
|
+
const cookies = response.headers.get('set-cookie');
|
|
1409
|
+
if (cookies) {
|
|
1410
|
+
const match = cookies.match(/axonflow_session=([^;]+)/);
|
|
1411
|
+
if (match) {
|
|
1412
|
+
this.sessionCookie = match[1];
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
// Fallback to session_id in response body
|
|
1416
|
+
if (!this.sessionCookie && result.session_id) {
|
|
1417
|
+
this.sessionCookie = result.session_id;
|
|
1418
|
+
}
|
|
1419
|
+
if (this.config.debug) {
|
|
1420
|
+
debugLog('Portal login successful', { orgId });
|
|
1421
|
+
}
|
|
1422
|
+
return {
|
|
1423
|
+
sessionId: result.session_id,
|
|
1424
|
+
orgId: result.org_id,
|
|
1425
|
+
email: result.email,
|
|
1426
|
+
name: result.name,
|
|
1427
|
+
expiresAt: result.expires_at,
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Logout from Customer Portal and clear session cookie.
|
|
1432
|
+
*/
|
|
1433
|
+
async logoutFromPortal() {
|
|
1434
|
+
if (!this.sessionCookie) {
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
try {
|
|
1438
|
+
await fetch(`${this.getPortalUrl()}/api/v1/auth/logout`, {
|
|
1439
|
+
method: 'POST',
|
|
1440
|
+
headers: { Cookie: `axonflow_session=${this.sessionCookie}` },
|
|
1441
|
+
signal: AbortSignal.timeout(this.config.timeout),
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
catch {
|
|
1445
|
+
// Ignore logout errors
|
|
1446
|
+
}
|
|
1447
|
+
this.sessionCookie = null;
|
|
1448
|
+
if (this.config.debug) {
|
|
1449
|
+
debugLog('Portal logout successful');
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Check if logged in to Customer Portal.
|
|
1454
|
+
*/
|
|
1455
|
+
isLoggedIn() {
|
|
1456
|
+
return this.sessionCookie !== null;
|
|
1316
1457
|
}
|
|
1317
1458
|
// ============================================================================
|
|
1318
1459
|
// Code Governance Methods (Enterprise)
|
|
@@ -1356,7 +1497,7 @@ export class AxonFlow {
|
|
|
1356
1497
|
apiRequest.installation_id = request.installationId;
|
|
1357
1498
|
if (request.privateKey)
|
|
1358
1499
|
apiRequest.private_key = request.privateKey;
|
|
1359
|
-
return this.
|
|
1500
|
+
return this.portalRequest('POST', '/api/v1/code-governance/git-providers/validate', apiRequest);
|
|
1360
1501
|
}
|
|
1361
1502
|
/**
|
|
1362
1503
|
* Configure a Git provider for code governance.
|
|
@@ -1407,7 +1548,7 @@ export class AxonFlow {
|
|
|
1407
1548
|
apiRequest.installation_id = request.installationId;
|
|
1408
1549
|
if (request.privateKey)
|
|
1409
1550
|
apiRequest.private_key = request.privateKey;
|
|
1410
|
-
return this.
|
|
1551
|
+
return this.portalRequest('POST', '/api/v1/code-governance/git-providers', apiRequest);
|
|
1411
1552
|
}
|
|
1412
1553
|
/**
|
|
1413
1554
|
* List all configured Git providers for the tenant.
|
|
@@ -1425,7 +1566,7 @@ export class AxonFlow {
|
|
|
1425
1566
|
if (this.config.debug) {
|
|
1426
1567
|
debugLog('Listing Git providers');
|
|
1427
1568
|
}
|
|
1428
|
-
return this.
|
|
1569
|
+
return this.portalRequest('GET', '/api/v1/code-governance/git-providers');
|
|
1429
1570
|
}
|
|
1430
1571
|
/**
|
|
1431
1572
|
* Delete a configured Git provider.
|
|
@@ -1441,7 +1582,7 @@ export class AxonFlow {
|
|
|
1441
1582
|
if (this.config.debug) {
|
|
1442
1583
|
debugLog('Deleting Git provider', { type });
|
|
1443
1584
|
}
|
|
1444
|
-
await this.
|
|
1585
|
+
await this.portalRequest('DELETE', `/api/v1/code-governance/git-providers/${type}`);
|
|
1445
1586
|
}
|
|
1446
1587
|
/**
|
|
1447
1588
|
* Create a Pull Request from LLM-generated code.
|
|
@@ -1509,7 +1650,7 @@ export class AxonFlow {
|
|
|
1509
1650
|
apiRequest.secrets_detected = request.secretsDetected;
|
|
1510
1651
|
if (request.unsafePatterns !== undefined)
|
|
1511
1652
|
apiRequest.unsafe_patterns = request.unsafePatterns;
|
|
1512
|
-
const response = await this.
|
|
1653
|
+
const response = await this.portalRequest('POST', '/api/v1/code-governance/prs', apiRequest);
|
|
1513
1654
|
// Transform snake_case response to camelCase
|
|
1514
1655
|
return {
|
|
1515
1656
|
prId: response.pr_id,
|
|
@@ -1554,10 +1695,10 @@ export class AxonFlow {
|
|
|
1554
1695
|
if (this.config.debug) {
|
|
1555
1696
|
debugLog('Listing PRs', { options });
|
|
1556
1697
|
}
|
|
1557
|
-
const response = await this.
|
|
1698
|
+
const response = await this.portalRequest('GET', path);
|
|
1558
1699
|
// Transform snake_case response to camelCase
|
|
1559
1700
|
return {
|
|
1560
|
-
prs: response.prs.map(pr => ({
|
|
1701
|
+
prs: (response.prs || []).map(pr => ({
|
|
1561
1702
|
id: pr.id,
|
|
1562
1703
|
prNumber: pr.pr_number,
|
|
1563
1704
|
prUrl: pr.pr_url,
|
|
@@ -1593,7 +1734,7 @@ export class AxonFlow {
|
|
|
1593
1734
|
if (this.config.debug) {
|
|
1594
1735
|
debugLog('Getting PR', { prId });
|
|
1595
1736
|
}
|
|
1596
|
-
const response = await this.
|
|
1737
|
+
const response = await this.portalRequest('GET', `/api/v1/code-governance/prs/${prId}`);
|
|
1597
1738
|
// Transform snake_case response to camelCase
|
|
1598
1739
|
return {
|
|
1599
1740
|
id: response.id,
|
|
@@ -1630,7 +1771,7 @@ export class AxonFlow {
|
|
|
1630
1771
|
if (this.config.debug) {
|
|
1631
1772
|
debugLog('Syncing PR status', { prId });
|
|
1632
1773
|
}
|
|
1633
|
-
const response = await this.
|
|
1774
|
+
const response = await this.portalRequest('POST', `/api/v1/code-governance/prs/${prId}/sync`);
|
|
1634
1775
|
// Transform snake_case response to camelCase
|
|
1635
1776
|
return {
|
|
1636
1777
|
id: response.id,
|
|
@@ -1670,7 +1811,7 @@ export class AxonFlow {
|
|
|
1670
1811
|
if (this.config.debug) {
|
|
1671
1812
|
debugLog('Getting code governance metrics');
|
|
1672
1813
|
}
|
|
1673
|
-
const response = await this.
|
|
1814
|
+
const response = await this.portalRequest('GET', '/api/v1/code-governance/metrics');
|
|
1674
1815
|
return {
|
|
1675
1816
|
tenantId: response.tenant_id,
|
|
1676
1817
|
totalPrs: response.total_prs,
|
|
@@ -1718,9 +1859,9 @@ export class AxonFlow {
|
|
|
1718
1859
|
if (this.config.debug) {
|
|
1719
1860
|
debugLog('Exporting code governance data', { path });
|
|
1720
1861
|
}
|
|
1721
|
-
const response = await this.
|
|
1862
|
+
const response = await this.portalRequest('GET', path);
|
|
1722
1863
|
return {
|
|
1723
|
-
records: response.records.map(r => ({
|
|
1864
|
+
records: (response.records || []).map(r => ({
|
|
1724
1865
|
id: r.id,
|
|
1725
1866
|
prNumber: r.pr_number,
|
|
1726
1867
|
prUrl: r.pr_url,
|
|
@@ -1741,6 +1882,36 @@ export class AxonFlow {
|
|
|
1741
1882
|
exportedAt: response.exported_at,
|
|
1742
1883
|
};
|
|
1743
1884
|
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Export code governance data as CSV.
|
|
1887
|
+
*
|
|
1888
|
+
* Returns raw CSV data suitable for saving to file or streaming.
|
|
1889
|
+
*
|
|
1890
|
+
* @param options - Export options (date filters, state filter)
|
|
1891
|
+
* @returns Raw CSV data
|
|
1892
|
+
*
|
|
1893
|
+
* @example
|
|
1894
|
+
* ```typescript
|
|
1895
|
+
* const csvData = await axonflow.exportCodeGovernanceDataCSV();
|
|
1896
|
+
* fs.writeFileSync('pr-audit.csv', csvData);
|
|
1897
|
+
* ```
|
|
1898
|
+
*/
|
|
1899
|
+
async exportCodeGovernanceDataCSV(options) {
|
|
1900
|
+
const params = new URLSearchParams();
|
|
1901
|
+
params.set('format', 'csv');
|
|
1902
|
+
if (options?.startDate)
|
|
1903
|
+
params.set('start_date', options.startDate);
|
|
1904
|
+
if (options?.endDate)
|
|
1905
|
+
params.set('end_date', options.endDate);
|
|
1906
|
+
if (options?.state)
|
|
1907
|
+
params.set('state', options.state);
|
|
1908
|
+
const query = params.toString();
|
|
1909
|
+
const path = `/api/v1/code-governance/export${query ? '?' + query : ''}`;
|
|
1910
|
+
if (this.config.debug) {
|
|
1911
|
+
debugLog('Exporting code governance data as CSV', { path });
|
|
1912
|
+
}
|
|
1913
|
+
return this.portalRequestText('GET', path);
|
|
1914
|
+
}
|
|
1744
1915
|
// ============================================================================
|
|
1745
1916
|
// Execution Replay Methods
|
|
1746
1917
|
// ============================================================================
|
|
@@ -1793,6 +1964,65 @@ export class AxonFlow {
|
|
|
1793
1964
|
}
|
|
1794
1965
|
return response.json();
|
|
1795
1966
|
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Get the portal URL for enterprise PR workflow features.
|
|
1969
|
+
* Falls back to agent endpoint with port 8082 if not configured.
|
|
1970
|
+
*/
|
|
1971
|
+
getPortalUrl() {
|
|
1972
|
+
if (this.config.portalEndpoint) {
|
|
1973
|
+
return this.config.portalEndpoint;
|
|
1974
|
+
}
|
|
1975
|
+
// Default: assume portal is on same host as agent, port 8082
|
|
1976
|
+
try {
|
|
1977
|
+
const url = new URL(this.config.endpoint);
|
|
1978
|
+
url.port = '8082';
|
|
1979
|
+
return url.toString().replace(/\/$/, '');
|
|
1980
|
+
}
|
|
1981
|
+
catch {
|
|
1982
|
+
return 'http://localhost:8082';
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Generic HTTP request helper for Customer Portal APIs (enterprise features).
|
|
1987
|
+
* Requires prior authentication via loginToPortal().
|
|
1988
|
+
*/
|
|
1989
|
+
async portalRequest(method, path, body) {
|
|
1990
|
+
if (!this.sessionCookie) {
|
|
1991
|
+
throw new AuthenticationError('Not logged in to Customer Portal. Call loginToPortal() first.');
|
|
1992
|
+
}
|
|
1993
|
+
const url = `${this.getPortalUrl()}${path}`;
|
|
1994
|
+
const headers = {
|
|
1995
|
+
'Content-Type': 'application/json',
|
|
1996
|
+
Cookie: `axonflow_session=${this.sessionCookie}`,
|
|
1997
|
+
};
|
|
1998
|
+
const options = {
|
|
1999
|
+
method,
|
|
2000
|
+
headers,
|
|
2001
|
+
signal: AbortSignal.timeout(this.config.timeout),
|
|
2002
|
+
};
|
|
2003
|
+
if (body && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {
|
|
2004
|
+
options.body = JSON.stringify(body);
|
|
2005
|
+
}
|
|
2006
|
+
if (this.config.debug) {
|
|
2007
|
+
debugLog('Portal request', { method, path });
|
|
2008
|
+
}
|
|
2009
|
+
const response = await fetch(url, options);
|
|
2010
|
+
if (!response.ok) {
|
|
2011
|
+
const errorText = await response.text();
|
|
2012
|
+
if (response.status === 401 || response.status === 403) {
|
|
2013
|
+
throw new AuthenticationError(`Request failed: ${errorText}`);
|
|
2014
|
+
}
|
|
2015
|
+
if (response.status === 404) {
|
|
2016
|
+
throw new APIError(404, 'Not Found', errorText);
|
|
2017
|
+
}
|
|
2018
|
+
throw new APIError(response.status, response.statusText, errorText);
|
|
2019
|
+
}
|
|
2020
|
+
// Handle DELETE responses with no body
|
|
2021
|
+
if (response.status === 204 || method === 'DELETE') {
|
|
2022
|
+
return undefined;
|
|
2023
|
+
}
|
|
2024
|
+
return response.json();
|
|
2025
|
+
}
|
|
1796
2026
|
/**
|
|
1797
2027
|
* List workflow executions with optional filtering and pagination.
|
|
1798
2028
|
*
|
|
@@ -2349,5 +2579,36 @@ export class AxonFlow {
|
|
|
2349
2579
|
},
|
|
2350
2580
|
};
|
|
2351
2581
|
}
|
|
2582
|
+
/**
|
|
2583
|
+
* Generic HTTP request helper for Customer Portal APIs that returns raw text.
|
|
2584
|
+
* Used for CSV exports and other non-JSON responses.
|
|
2585
|
+
* Requires prior authentication via loginToPortal().
|
|
2586
|
+
*/
|
|
2587
|
+
async portalRequestText(method, path) {
|
|
2588
|
+
if (!this.sessionCookie) {
|
|
2589
|
+
throw new AuthenticationError('Not logged in to Customer Portal. Call loginToPortal() first.');
|
|
2590
|
+
}
|
|
2591
|
+
const url = `${this.getPortalUrl()}${path}`;
|
|
2592
|
+
const headers = {
|
|
2593
|
+
Cookie: `axonflow_session=${this.sessionCookie}`,
|
|
2594
|
+
};
|
|
2595
|
+
const options = {
|
|
2596
|
+
method,
|
|
2597
|
+
headers,
|
|
2598
|
+
signal: AbortSignal.timeout(this.config.timeout),
|
|
2599
|
+
};
|
|
2600
|
+
if (this.config.debug) {
|
|
2601
|
+
debugLog('Portal request (text)', { method, path });
|
|
2602
|
+
}
|
|
2603
|
+
const response = await fetch(url, options);
|
|
2604
|
+
if (!response.ok) {
|
|
2605
|
+
const errorText = await response.text();
|
|
2606
|
+
if (response.status === 401 || response.status === 403) {
|
|
2607
|
+
throw new AuthenticationError(`Request failed: ${errorText}`);
|
|
2608
|
+
}
|
|
2609
|
+
throw new APIError(response.status, response.statusText, errorText);
|
|
2610
|
+
}
|
|
2611
|
+
return response.text();
|
|
2612
|
+
}
|
|
2352
2613
|
}
|
|
2353
2614
|
//# sourceMappingURL=client.js.map
|