@xcelera/cli 2.2.2 → 2.3.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/cli.js CHANGED
@@ -62,7 +62,7 @@ function isNetworkError(error) {
62
62
  return errorMessages.has(message);
63
63
  }
64
64
 
65
- async function requestAudit(url, token, context) {
65
+ async function requestAudit(url, token, context, auth) {
66
66
  const apiUrl = `${getApiBaseUrl()}/api/v1/audit`;
67
67
  try {
68
68
  const response = await fetch(apiUrl, {
@@ -73,7 +73,8 @@ async function requestAudit(url, token, context) {
73
73
  },
74
74
  body: JSON.stringify({
75
75
  url,
76
- context
76
+ context,
77
+ ...(auth && { auth })
77
78
  })
78
79
  });
79
80
  if (!response.ok) {
@@ -105,6 +106,7 @@ async function requestAudit(url, token, context) {
105
106
  throw error;
106
107
  }
107
108
  }
109
+ /* istanbul ignore next */
108
110
  function getApiBaseUrl() {
109
111
  if (process.env.NODE_ENV === 'development') {
110
112
  return 'http://localhost:3000';
@@ -9338,13 +9340,18 @@ async function inferBuildContext() {
9338
9340
  };
9339
9341
  }
9340
9342
 
9341
- async function runAuditCommand(url, token) {
9343
+ async function runAuditCommand(url, token, authOptions) {
9342
9344
  const output = [];
9343
9345
  const errors = [];
9344
9346
  try {
9345
9347
  const buildContext = await inferBuildContext();
9346
9348
  output.push(...formatBuildContext(buildContext));
9347
- const response = await requestAudit(url, token, buildContext);
9349
+ const auth = parseAuthCredentials(authOptions);
9350
+ if (auth) {
9351
+ output.push('🔐 Authentication credentials detected');
9352
+ output.push('');
9353
+ }
9354
+ const response = await requestAudit(url, token, buildContext, auth);
9348
9355
  if (!response.success) {
9349
9356
  const { message, details } = response.error;
9350
9357
  errors.push('❌ Unable to schedule audit :(');
@@ -9436,6 +9443,59 @@ function formatGitHubIntegrationStatus(context) {
9436
9443
  }
9437
9444
  return { output, errors };
9438
9445
  }
9446
+ function parseAuthCredentials(options) {
9447
+ const envAuth = process.env.XCELERA_AUTH;
9448
+ if (envAuth) {
9449
+ try {
9450
+ return JSON.parse(envAuth);
9451
+ }
9452
+ catch {
9453
+ throw new Error('XCELERA_AUTH environment variable contains invalid JSON');
9454
+ }
9455
+ }
9456
+ // Check for --auth JSON option
9457
+ if (options?.authJson) {
9458
+ try {
9459
+ return JSON.parse(options.authJson);
9460
+ }
9461
+ catch {
9462
+ throw new Error('--auth option contains invalid JSON');
9463
+ }
9464
+ }
9465
+ // Build auth from --cookie and --header options
9466
+ const hasCookies = options?.cookies && options.cookies.length > 0;
9467
+ const hasHeaders = options?.headers && options.headers.length > 0;
9468
+ if (!hasCookies && !hasHeaders) {
9469
+ return undefined;
9470
+ }
9471
+ const auth = {};
9472
+ if (hasCookies && options.cookies) {
9473
+ auth.cookies = options.cookies.map(parseCookie);
9474
+ }
9475
+ if (hasHeaders && options.headers) {
9476
+ auth.headers = {};
9477
+ for (const header of options.headers) {
9478
+ const colonIndex = header.indexOf(':');
9479
+ if (colonIndex === -1) {
9480
+ throw new Error(`Invalid header format: "${header}". Expected "Name: Value"`);
9481
+ }
9482
+ const name = header.slice(0, colonIndex).trim();
9483
+ const value = header.slice(colonIndex + 1).trim();
9484
+ auth.headers[name] = value;
9485
+ }
9486
+ }
9487
+ return auth;
9488
+ }
9489
+ function parseCookie(cookie) {
9490
+ const equalsIndex = cookie.indexOf('=');
9491
+ if (equalsIndex === -1) {
9492
+ throw new Error(`Invalid cookie format: "${cookie}". Expected "name=value"`);
9493
+ }
9494
+ return {
9495
+ name: cookie.slice(0, equalsIndex),
9496
+ value: cookie.slice(equalsIndex + 1)
9497
+ };
9498
+ }
9439
9499
 
9440
9500
  /* istanbul ignore file */
9441
9501
  const options = {
@@ -9447,6 +9507,17 @@ const options = {
9447
9507
  type: 'string',
9448
9508
  required: true,
9449
9509
  default: process.env.XCELERA_TOKEN
9510
+ },
9511
+ auth: {
9512
+ type: 'string'
9513
+ },
9514
+ cookie: {
9515
+ type: 'string',
9516
+ multiple: true
9517
+ },
9518
+ header: {
9519
+ type: 'string',
9520
+ multiple: true
9450
9521
  }
9451
9522
  };
9452
9523
  const { positionals, values } = parseArgs({
@@ -9469,7 +9540,7 @@ if (command !== 'audit') {
9469
9540
  printHelp();
9470
9541
  process.exit(1);
9471
9542
  }
9472
- const { url, token } = values;
9543
+ const { url, token, auth, cookie, header } = values;
9473
9544
  if (!url) {
9474
9545
  console.error('URL is required. Use --url <url> to specify the URL to audit.');
9475
9546
  process.exit(1);
@@ -9478,17 +9549,48 @@ if (!token) {
9478
9549
  console.error('A token is required. Use --token or set XCELERA_TOKEN environment variable.');
9479
9550
  process.exit(1);
9480
9551
  }
9481
- const result = await runAuditCommand(url, token);
9552
+ const result = await runAuditCommand(url, token, {
9553
+ authJson: auth,
9554
+ cookies: cookie,
9555
+ headers: header
9556
+ });
9482
9557
  result.output.forEach((line) => console.log(line));
9483
9558
  result.errors.forEach((line) => console.error(line));
9484
9559
  process.exit(result.exitCode);
9485
9560
  function printHelp() {
9486
- console.log('Usage: xcelera audit --url <url> [--token <token>]');
9561
+ console.log('Usage: xcelera audit --url <url> [options]');
9487
9562
  console.log('');
9488
9563
  console.log('Options:');
9489
- console.log(' --token <token> The xcelera API token to use for authentication.');
9490
- console.log('Can also be set with the XCELERA_TOKEN environment variable.');
9491
- console.log(' --url <url> The URL to audit.');
9564
+ console.log(' --token <token> The xcelera API token.');
9565
+ console.log(' Can also be set with XCELERA_TOKEN env var.');
9566
+ console.log(' --url <url> The URL to audit.');
9567
+ console.log('');
9568
+ console.log('Authentication (for pages behind login):');
9569
+ console.log(' --cookie <cookie> Cookie in "name=value" format.');
9570
+ console.log(' Can be specified multiple times.');
9571
+ console.log(' --header <header> Header in "Name: Value" format.');
9572
+ console.log(' Can be specified multiple times.');
9573
+ console.log(' --auth <json> Full auth config as JSON.');
9574
+ console.log(' Can also be set with XCELERA_AUTH env var.');
9575
+ console.log('');
9576
+ console.log('Examples:');
9577
+ console.log(' # Basic audit');
9578
+ console.log(' xcelera audit --url https://example.com');
9579
+ console.log('');
9580
+ console.log(' # With session cookie');
9581
+ console.log(' xcelera audit --url https://myapp.com/dashboard --cookie "session=abc123"');
9582
+ console.log('');
9583
+ console.log(' # With bearer token');
9584
+ console.log(' xcelera audit --url https://api.myapp.com/admin \\');
9585
+ console.log(' --header "Authorization: Bearer eyJhbG..."');
9586
+ console.log('');
9587
+ console.log(' # Multiple cookies');
9588
+ console.log(' xcelera audit --url https://myapp.com/dashboard \\');
9589
+ console.log(' --cookie "session=abc123" --cookie "csrf=xyz"');
9590
+ console.log('');
9591
+ console.log(' # Full auth JSON (multiple cookies and headers)');
9592
+ console.log(' xcelera audit --url https://myapp.com/dashboard \\');
9593
+ console.log(' --auth \'{"cookies":[{"name":"session","value":"abc123"}],"headers":{"X-Custom":"value"}}\'');
9492
9594
  console.log('');
9493
9595
  }
9494
9596
  //# sourceMappingURL=cli.js.map