@redocly/cli 1.34.0 → 1.34.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @redocly/cli
2
2
 
3
+ ## 1.34.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved OpenTelemetry data serialization.
8
+ - Updated @redocly/respect-core to v1.34.1.
9
+
3
10
  ## 1.34.0
4
11
 
5
12
  ### Minor Changes
package/README.md CHANGED
@@ -16,7 +16,7 @@ Supports OpenAPI 3.1, 3.0 and OpenAPI 2.0 (legacy Swagger), AsyncAPI 3.0 and 2.6
16
16
  ### Node
17
17
 
18
18
  ```sh
19
- npx @redocly/cli lint path-to-root-file.yaml
19
+ npx @redocly/cli@latest lint path-to-root-file.yaml
20
20
  ```
21
21
 
22
22
  Alternatively, install it globally with `npm`:
@@ -441,8 +441,8 @@ describe('cleanArgs', () => {
441
441
  afterEach(() => {
442
442
  jest.clearAllMocks();
443
443
  });
444
- it('should remove potentially sensitive data from args', () => {
445
- const testArgs = {
444
+ it('should remove potentially sensitive data from parsed args', () => {
445
+ const parsedArgs = {
446
446
  config: './fixtures/redocly.yaml',
447
447
  apis: ['main@v1', 'fixtures/openapi.yaml', 'http://some.url/openapi.yaml'],
448
448
  format: 'codeframe',
@@ -451,7 +451,21 @@ describe('cleanArgs', () => {
451
451
  'client-key': 'some-client-key',
452
452
  'ca-cert': 'some-ca-cert',
453
453
  };
454
- expect((0, miscellaneous_1.cleanArgs)(testArgs)).toEqual({
454
+ const rawArgs = [
455
+ 'redocly',
456
+ 'bundle',
457
+ 'main@v1',
458
+ 'fixtures/openapi.yaml',
459
+ 'http://some.url/openapi.yaml',
460
+ '--config=fixtures/redocly.yaml',
461
+ '--format=codeframe',
462
+ '--input=some-input',
463
+ '--client-cert=some-client-cert',
464
+ '--client-key=some-client-key',
465
+ '--ca-cert=some-ca-cert',
466
+ ];
467
+ const result = (0, miscellaneous_1.cleanArgs)(parsedArgs, rawArgs);
468
+ expect(result.arguments).toEqual(JSON.stringify({
455
469
  config: 'file-yaml',
456
470
  apis: ['api-name@api-version', 'file-yaml', 'http://url'],
457
471
  format: 'codeframe',
@@ -459,30 +473,19 @@ describe('cleanArgs', () => {
459
473
  'client-cert': '***',
460
474
  'client-key': '***',
461
475
  'ca-cert': '***',
462
- });
476
+ }));
463
477
  });
464
478
  it('should remove potentially sensitive data from a push destination', () => {
465
- const testArgs = {
479
+ const parsedArgs = {
466
480
  destination: '@org/name@version',
467
481
  };
468
- expect((0, miscellaneous_1.cleanArgs)(testArgs)).toEqual({
482
+ const rawArgs = ['redocly', 'push', '--destination=@org/name@version'];
483
+ const result = (0, miscellaneous_1.cleanArgs)(parsedArgs, rawArgs);
484
+ expect(result.arguments).toEqual(JSON.stringify({
469
485
  destination: '@organization/api-name@api-version',
470
- });
471
- });
472
- });
473
- describe('cleanRawInput', () => {
474
- beforeEach(() => {
475
- // @ts-ignore
476
- openapi_core_1.isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
477
- // @ts-ignore
478
- fs_1.existsSync = (value) => jest.requireActual('fs').existsSync(path.resolve(__dirname, value));
479
- // @ts-ignore
480
- fs_1.statSync = (value) => jest.requireActual('fs').statSync(path.resolve(__dirname, value));
486
+ }));
481
487
  });
482
- afterEach(() => {
483
- jest.clearAllMocks();
484
- });
485
- it('should remove potentially sensitive data from raw CLI input', () => {
488
+ it('should remove potentially sensitive data from raw CLI input', () => {
486
489
  const rawInput = [
487
490
  'redocly',
488
491
  'bundle',
@@ -492,8 +495,41 @@ describe('cleanRawInput', () => {
492
495
  '--config=fixtures/redocly.yaml',
493
496
  '--output',
494
497
  'fixtures',
498
+ '--client-cert',
499
+ 'fixtures/client-cert.pem',
500
+ '--client-key',
501
+ 'fixtures/client-key.pem',
502
+ '--ca-cert',
503
+ 'fixtures/ca-cert.pem',
504
+ '--organization',
505
+ 'my-org',
506
+ '--input',
507
+ 'timeout=10000',
508
+ '--input',
509
+ '{"apiKey":"some=111=1111"}',
495
510
  ];
496
- expect((0, miscellaneous_1.cleanRawInput)(rawInput)).toEqual('redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder');
511
+ const parsedArgs = {
512
+ apis: ['./fixtures/openapi.yaml', 'http://some.url/openapi.yaml'],
513
+ input: ['timeout=10000', '{"apiKey":"some=111=1111"}'],
514
+ organization: 'my-org',
515
+ 'client-cert': 'fixtures/client-cert.pem',
516
+ 'client-key': 'fixtures/client-key.pem',
517
+ 'ca-cert': 'fixtures/ca-cert.pem',
518
+ config: 'fixtures/redocly.yaml',
519
+ output: 'fixtures',
520
+ };
521
+ const result = (0, miscellaneous_1.cleanArgs)(parsedArgs, rawInput);
522
+ expect(result.raw_input).toEqual('redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder --client-cert *** --client-key *** --ca-cert *** --organization *** --input *** --input ***');
523
+ expect(result.arguments).toEqual(JSON.stringify({
524
+ apis: ['file-yaml', 'http://url'],
525
+ input: '***',
526
+ organization: '***',
527
+ 'client-cert': '***',
528
+ 'client-key': '***',
529
+ 'ca-cert': '***',
530
+ config: 'file-yaml',
531
+ output: 'folder',
532
+ }));
497
533
  });
498
534
  it('should preserve safe data from raw CLI input', () => {
499
535
  const rawInput = [
@@ -506,18 +542,31 @@ describe('cleanRawInput', () => {
506
542
  '--skip-rule',
507
543
  'operation-4xx-response',
508
544
  ];
509
- expect((0, miscellaneous_1.cleanRawInput)(rawInput)).toEqual('redocly lint file-json --format stylish --extends=minimal --skip-rule operation-4xx-response');
545
+ const parsedArgs = {
546
+ apis: ['./fixtures/openapi.json'],
547
+ format: 'stylish',
548
+ extends: 'minimal',
549
+ 'skip-rule': ['operation-4xx-response'],
550
+ };
551
+ const result = (0, miscellaneous_1.cleanArgs)(parsedArgs, rawInput);
552
+ expect(result.raw_input).toEqual('redocly lint file-json --format stylish --extends=minimal --skip-rule operation-4xx-response');
553
+ expect(result.arguments).toEqual(JSON.stringify({
554
+ apis: ['file-json'],
555
+ format: 'stylish',
556
+ extends: 'minimal',
557
+ 'skip-rule': ['operation-4xx-response'],
558
+ }));
510
559
  });
511
- describe('validateFileExtension', () => {
512
- it('should return current file extension', () => {
513
- expect((0, miscellaneous_1.getAndValidateFileExtension)('test.json')).toEqual('json');
514
- });
515
- it('should return yaml and print warning if file extension does not supported', () => {
516
- const stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
517
- colorette_1.yellow.mockImplementation((text) => text);
518
- expect((0, miscellaneous_1.getAndValidateFileExtension)('test.xml')).toEqual('yaml');
519
- expect(stderrMock).toHaveBeenCalledWith(`Unsupported file extension: xml. Using yaml.\n`);
520
- });
560
+ });
561
+ describe('validateFileExtension', () => {
562
+ it('should return current file extension', () => {
563
+ expect((0, miscellaneous_1.getAndValidateFileExtension)('test.json')).toEqual('json');
564
+ });
565
+ it('should return yaml and print warning if file extension does not supported', () => {
566
+ const stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
567
+ colorette_1.yellow.mockImplementation((text) => text);
568
+ expect((0, miscellaneous_1.getAndValidateFileExtension)('test.xml')).toEqual('yaml');
569
+ expect(stderrMock).toHaveBeenCalledWith(`Unsupported file extension: xml. Using yaml.\n`);
521
570
  });
522
571
  });
523
572
  describe('writeToFileByExtension', () => {
@@ -75,8 +75,10 @@ export type Analytics = {
75
75
  spec_keyword?: string;
76
76
  spec_full_version?: string;
77
77
  };
78
- export declare function cleanArgs(args: CommandOptions): Record<string, unknown>;
79
- export declare function cleanRawInput(argv: string[]): string;
78
+ export declare function cleanArgs(parsedArgs: CommandOptions, rawArgv: string[]): {
79
+ arguments: string;
80
+ raw_input: string;
81
+ };
80
82
  export declare function checkForDeprecatedOptions<T>(argv: T, deprecatedOptions: Array<keyof T>): void;
81
83
  export declare function notifyAboutIncompatibleConfigOptions(themeOpenapiOptions: Record<string, unknown> | undefined): void;
82
84
  export declare function formatPath(path: string): string;
@@ -28,7 +28,6 @@ exports.checkIfRulesetExist = checkIfRulesetExist;
28
28
  exports.cleanColors = cleanColors;
29
29
  exports.sendTelemetry = sendTelemetry;
30
30
  exports.cleanArgs = cleanArgs;
31
- exports.cleanRawInput = cleanRawInput;
32
31
  exports.checkForDeprecatedOptions = checkForDeprecatedOptions;
33
32
  exports.notifyAboutIncompatibleConfigOptions = notifyAboutIncompatibleConfigOptions;
34
33
  exports.formatPath = formatPath;
@@ -458,7 +457,7 @@ async function sendTelemetry(argv, exit_code, has_config, spec_version, spec_key
458
457
  event_time,
459
458
  logged_in: logged_in ? 'yes' : 'no',
460
459
  command: `${command}`,
461
- arguments: JSON.stringify(cleanArgs(args)),
460
+ ...cleanArgs(args, process.argv.slice(2)),
462
461
  node_version: process.version,
463
462
  npm_version: (0, child_process_1.execSync)('npm -v').toString().replace('\n', ''),
464
463
  os_platform: os.platform(),
@@ -466,7 +465,6 @@ async function sendTelemetry(argv, exit_code, has_config, spec_version, spec_key
466
465
  exit_code,
467
466
  environment: process.env.REDOCLY_ENVIRONMENT,
468
467
  environment_ci: process.env.CI,
469
- raw_input: cleanRawInput(process.argv.slice(2)),
470
468
  has_config: has_config ? 'yes' : 'no',
471
469
  spec_version,
472
470
  spec_keyword,
@@ -504,27 +502,41 @@ function cleanString(value) {
504
502
  }
505
503
  return value;
506
504
  }
507
- function cleanArgs(args) {
508
- const keysToClean = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
509
- const result = {};
510
- for (const [key, value] of Object.entries(args)) {
511
- if (keysToClean.includes(key)) {
512
- result[key] = '***';
505
+ function replaceArgs(commandInput, targets, replacement) {
506
+ const targetValues = Array.isArray(targets) ? targets : [targets];
507
+ for (const target of targetValues) {
508
+ commandInput = commandInput.replaceAll(target, replacement);
509
+ }
510
+ return commandInput;
511
+ }
512
+ function cleanArgs(parsedArgs, rawArgv) {
513
+ const KEYS_TO_CLEAN = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
514
+ let commandInput = rawArgv.join(' ');
515
+ const commandArguments = {};
516
+ for (const [key, value] of Object.entries(parsedArgs)) {
517
+ if (KEYS_TO_CLEAN.includes(key)) {
518
+ commandArguments[key] = '***';
519
+ commandInput = replaceArgs(commandInput, value, '***');
513
520
  }
514
521
  else if (typeof value === 'string') {
515
- result[key] = cleanString(value);
522
+ const cleanedValue = cleanString(value);
523
+ commandArguments[key] = cleanedValue;
524
+ commandInput = replaceArgs(commandInput, value, cleanedValue);
516
525
  }
517
526
  else if (Array.isArray(value)) {
518
- result[key] = value.map(cleanString);
527
+ commandArguments[key] = value.map(cleanString);
528
+ for (const replacedValue of value) {
529
+ const newValue = cleanString(replacedValue);
530
+ if (commandInput.includes(replacedValue)) {
531
+ commandInput = commandInput.replaceAll(replacedValue, newValue);
532
+ }
533
+ }
519
534
  }
520
535
  else {
521
- result[key] = value;
536
+ commandArguments[key] = value;
522
537
  }
523
538
  }
524
- return result;
525
- }
526
- function cleanRawInput(argv) {
527
- return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
539
+ return { arguments: JSON.stringify(commandArguments), raw_input: commandInput };
528
540
  }
529
541
  function checkForDeprecatedOptions(argv, deprecatedOptions) {
530
542
  for (const option of deprecatedOptions) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/cli",
3
- "version": "1.34.0",
3
+ "version": "1.34.1",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -38,8 +38,8 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@redocly/config": "^0.22.0",
41
- "@redocly/openapi-core": "1.34.0",
42
- "@redocly/respect-core": "1.34.0",
41
+ "@redocly/openapi-core": "1.34.1",
42
+ "@redocly/respect-core": "1.34.1",
43
43
  "abort-controller": "^3.0.0",
44
44
  "chokidar": "^3.5.1",
45
45
  "colorette": "^1.2.0",
@@ -11,7 +11,6 @@ import {
11
11
  cleanColors,
12
12
  HandledError,
13
13
  cleanArgs,
14
- cleanRawInput,
15
14
  getAndValidateFileExtension,
16
15
  writeToFileByExtension,
17
16
  } from '../utils/miscellaneous';
@@ -28,7 +27,6 @@ import { blue, red, yellow } from 'colorette';
28
27
  import { existsSync, statSync } from 'fs';
29
28
  import * as path from 'path';
30
29
  import * as process from 'process';
31
- import { ConfigApis } from '../types';
32
30
 
33
31
  jest.mock('os');
34
32
  jest.mock('colorette');
@@ -540,8 +538,8 @@ describe('cleanArgs', () => {
540
538
  afterEach(() => {
541
539
  jest.clearAllMocks();
542
540
  });
543
- it('should remove potentially sensitive data from args', () => {
544
- const testArgs = {
541
+ it('should remove potentially sensitive data from parsed args', () => {
542
+ const parsedArgs = {
545
543
  config: './fixtures/redocly.yaml',
546
544
  apis: ['main@v1', 'fixtures/openapi.yaml', 'http://some.url/openapi.yaml'],
547
545
  format: 'codeframe',
@@ -550,39 +548,46 @@ describe('cleanArgs', () => {
550
548
  'client-key': 'some-client-key',
551
549
  'ca-cert': 'some-ca-cert',
552
550
  };
553
- expect(cleanArgs(testArgs)).toEqual({
554
- config: 'file-yaml',
555
- apis: ['api-name@api-version', 'file-yaml', 'http://url'],
556
- format: 'codeframe',
557
- input: '***',
558
- 'client-cert': '***',
559
- 'client-key': '***',
560
- 'ca-cert': '***',
561
- });
551
+ const rawArgs = [
552
+ 'redocly',
553
+ 'bundle',
554
+ 'main@v1',
555
+ 'fixtures/openapi.yaml',
556
+ 'http://some.url/openapi.yaml',
557
+ '--config=fixtures/redocly.yaml',
558
+ '--format=codeframe',
559
+ '--input=some-input',
560
+ '--client-cert=some-client-cert',
561
+ '--client-key=some-client-key',
562
+ '--ca-cert=some-ca-cert',
563
+ ];
564
+ const result = cleanArgs(parsedArgs, rawArgs);
565
+ expect(result.arguments).toEqual(
566
+ JSON.stringify({
567
+ config: 'file-yaml',
568
+ apis: ['api-name@api-version', 'file-yaml', 'http://url'],
569
+ format: 'codeframe',
570
+ input: '***',
571
+ 'client-cert': '***',
572
+ 'client-key': '***',
573
+ 'ca-cert': '***',
574
+ })
575
+ );
562
576
  });
563
577
  it('should remove potentially sensitive data from a push destination', () => {
564
- const testArgs = {
578
+ const parsedArgs = {
565
579
  destination: '@org/name@version',
566
580
  };
567
- expect(cleanArgs(testArgs)).toEqual({
568
- destination: '@organization/api-name@api-version',
569
- });
581
+ const rawArgs = ['redocly', 'push', '--destination=@org/name@version'];
582
+ const result = cleanArgs(parsedArgs, rawArgs);
583
+ expect(result.arguments).toEqual(
584
+ JSON.stringify({
585
+ destination: '@organization/api-name@api-version',
586
+ })
587
+ );
570
588
  });
571
- });
572
589
 
573
- describe('cleanRawInput', () => {
574
- beforeEach(() => {
575
- // @ts-ignore
576
- isAbsoluteUrl = jest.requireActual('@redocly/openapi-core').isAbsoluteUrl;
577
- // @ts-ignore
578
- existsSync = (value) => jest.requireActual('fs').existsSync(path.resolve(__dirname, value));
579
- // @ts-ignore
580
- statSync = (value) => jest.requireActual('fs').statSync(path.resolve(__dirname, value));
581
- });
582
- afterEach(() => {
583
- jest.clearAllMocks();
584
- });
585
- it('should remove potentially sensitive data from raw CLI input', () => {
590
+ it('should remove potentially sensitive data from raw CLI input', () => {
586
591
  const rawInput = [
587
592
  'redocly',
588
593
  'bundle',
@@ -592,11 +597,47 @@ describe('cleanRawInput', () => {
592
597
  '--config=fixtures/redocly.yaml',
593
598
  '--output',
594
599
  'fixtures',
600
+ '--client-cert',
601
+ 'fixtures/client-cert.pem',
602
+ '--client-key',
603
+ 'fixtures/client-key.pem',
604
+ '--ca-cert',
605
+ 'fixtures/ca-cert.pem',
606
+ '--organization',
607
+ 'my-org',
608
+ '--input',
609
+ 'timeout=10000',
610
+ '--input',
611
+ '{"apiKey":"some=111=1111"}',
595
612
  ];
596
- expect(cleanRawInput(rawInput)).toEqual(
597
- 'redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder'
613
+ const parsedArgs = {
614
+ apis: ['./fixtures/openapi.yaml', 'http://some.url/openapi.yaml'],
615
+ input: ['timeout=10000', '{"apiKey":"some=111=1111"}'],
616
+ organization: 'my-org',
617
+ 'client-cert': 'fixtures/client-cert.pem',
618
+ 'client-key': 'fixtures/client-key.pem',
619
+ 'ca-cert': 'fixtures/ca-cert.pem',
620
+ config: 'fixtures/redocly.yaml',
621
+ output: 'fixtures',
622
+ };
623
+ const result = cleanArgs(parsedArgs, rawInput);
624
+ expect(result.raw_input).toEqual(
625
+ 'redocly bundle api-name@api-version file-yaml http://url --config=file-yaml --output folder --client-cert *** --client-key *** --ca-cert *** --organization *** --input *** --input ***'
626
+ );
627
+ expect(result.arguments).toEqual(
628
+ JSON.stringify({
629
+ apis: ['file-yaml', 'http://url'],
630
+ input: '***',
631
+ organization: '***',
632
+ 'client-cert': '***',
633
+ 'client-key': '***',
634
+ 'ca-cert': '***',
635
+ config: 'file-yaml',
636
+ output: 'folder',
637
+ })
598
638
  );
599
639
  });
640
+
600
641
  it('should preserve safe data from raw CLI input', () => {
601
642
  const rawInput = [
602
643
  'redocly',
@@ -608,23 +649,40 @@ describe('cleanRawInput', () => {
608
649
  '--skip-rule',
609
650
  'operation-4xx-response',
610
651
  ];
611
- expect(cleanRawInput(rawInput)).toEqual(
652
+ const parsedArgs = {
653
+ apis: ['./fixtures/openapi.json'],
654
+ format: 'stylish',
655
+ extends: 'minimal',
656
+ 'skip-rule': ['operation-4xx-response'],
657
+ };
658
+ const result = cleanArgs(parsedArgs, rawInput);
659
+
660
+ expect(result.raw_input).toEqual(
612
661
  'redocly lint file-json --format stylish --extends=minimal --skip-rule operation-4xx-response'
613
662
  );
663
+
664
+ expect(result.arguments).toEqual(
665
+ JSON.stringify({
666
+ apis: ['file-json'],
667
+ format: 'stylish',
668
+ extends: 'minimal',
669
+ 'skip-rule': ['operation-4xx-response'],
670
+ })
671
+ );
614
672
  });
673
+ });
615
674
 
616
- describe('validateFileExtension', () => {
617
- it('should return current file extension', () => {
618
- expect(getAndValidateFileExtension('test.json')).toEqual('json');
619
- });
675
+ describe('validateFileExtension', () => {
676
+ it('should return current file extension', () => {
677
+ expect(getAndValidateFileExtension('test.json')).toEqual('json');
678
+ });
620
679
 
621
- it('should return yaml and print warning if file extension does not supported', () => {
622
- const stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
623
- (yellow as jest.Mock<any, any>).mockImplementation((text: string) => text);
680
+ it('should return yaml and print warning if file extension does not supported', () => {
681
+ const stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
682
+ (yellow as jest.Mock<any, any>).mockImplementation((text: string) => text);
624
683
 
625
- expect(getAndValidateFileExtension('test.xml')).toEqual('yaml');
626
- expect(stderrMock).toHaveBeenCalledWith(`Unsupported file extension: xml. Using yaml.\n`);
627
- });
684
+ expect(getAndValidateFileExtension('test.xml')).toEqual('yaml');
685
+ expect(stderrMock).toHaveBeenCalledWith(`Unsupported file extension: xml. Using yaml.\n`);
628
686
  });
629
687
  });
630
688
 
@@ -575,7 +575,7 @@ export async function sendTelemetry(
575
575
  event_time,
576
576
  logged_in: logged_in ? 'yes' : 'no',
577
577
  command: `${command}`,
578
- arguments: JSON.stringify(cleanArgs(args)),
578
+ ...cleanArgs(args, process.argv.slice(2)),
579
579
  node_version: process.version,
580
580
  npm_version: execSync('npm -v').toString().replace('\n', ''),
581
581
  os_platform: os.platform(),
@@ -583,7 +583,6 @@ export async function sendTelemetry(
583
583
  exit_code,
584
584
  environment: process.env.REDOCLY_ENVIRONMENT,
585
585
  environment_ci: process.env.CI,
586
- raw_input: cleanRawInput(process.argv.slice(2)),
587
586
  has_config: has_config ? 'yes' : 'no',
588
587
  spec_version,
589
588
  spec_keyword,
@@ -627,7 +626,7 @@ function isDirectory(value: string) {
627
626
  return fs.existsSync(value) && fs.statSync(value).isDirectory();
628
627
  }
629
628
 
630
- function cleanString(value?: string): string | undefined {
629
+ function cleanString(value: string): string {
631
630
  if (!value) {
632
631
  return value;
633
632
  }
@@ -646,27 +645,44 @@ function cleanString(value?: string): string | undefined {
646
645
  return value;
647
646
  }
648
647
 
649
- export function cleanArgs(args: CommandOptions) {
650
- const keysToClean = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
648
+ function replaceArgs(
649
+ commandInput: string,
650
+ targets: string | string[],
651
+ replacement: string
652
+ ): string {
653
+ const targetValues = Array.isArray(targets) ? targets : [targets];
654
+ for (const target of targetValues) {
655
+ commandInput = commandInput.replaceAll(target, replacement);
656
+ }
657
+ return commandInput;
658
+ }
651
659
 
652
- const result: Record<string, unknown> = {};
653
- for (const [key, value] of Object.entries(args)) {
654
- if (keysToClean.includes(key)) {
655
- result[key] = '***';
660
+ export function cleanArgs(parsedArgs: CommandOptions, rawArgv: string[]) {
661
+ const KEYS_TO_CLEAN = ['organization', 'o', 'input', 'i', 'client-cert', 'client-key', 'ca-cert'];
662
+ let commandInput = rawArgv.join(' ');
663
+ const commandArguments: Record<string, string | string[]> = {};
664
+ for (const [key, value] of Object.entries(parsedArgs)) {
665
+ if (KEYS_TO_CLEAN.includes(key)) {
666
+ commandArguments[key] = '***';
667
+ commandInput = replaceArgs(commandInput, value, '***');
656
668
  } else if (typeof value === 'string') {
657
- result[key] = cleanString(value);
669
+ const cleanedValue = cleanString(value);
670
+ commandArguments[key] = cleanedValue;
671
+ commandInput = replaceArgs(commandInput, value, cleanedValue);
658
672
  } else if (Array.isArray(value)) {
659
- result[key] = value.map(cleanString);
673
+ commandArguments[key] = value.map(cleanString);
674
+ for (const replacedValue of value) {
675
+ const newValue = cleanString(replacedValue);
676
+ if (commandInput.includes(replacedValue)) {
677
+ commandInput = commandInput.replaceAll(replacedValue, newValue);
678
+ }
679
+ }
660
680
  } else {
661
- result[key] = value;
681
+ commandArguments[key] = value;
662
682
  }
663
683
  }
664
684
 
665
- return result;
666
- }
667
-
668
- export function cleanRawInput(argv: string[]) {
669
- return argv.map((entry) => entry.split('=').map(cleanString).join('=')).join(' ');
685
+ return { arguments: JSON.stringify(commandArguments), raw_input: commandInput };
670
686
  }
671
687
 
672
688
  export function checkForDeprecatedOptions<T>(argv: T, deprecatedOptions: Array<keyof T>) {