@redocly/cli 1.25.14 → 1.26.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.
@@ -1,4 +1,5 @@
1
1
  import { spawn } from 'child_process';
2
+ import { getPlatformSpawnArgs, sanitizeLocale, sanitizePath } from '../utils/platform';
2
3
 
3
4
  import type { CommandArgs } from '../wrapper';
4
5
  import type { VerifyConfigOptions } from '../types';
@@ -10,10 +11,22 @@ export type TranslationsOptions = {
10
11
 
11
12
  export const handleTranslations = async ({ argv }: CommandArgs<TranslationsOptions>) => {
12
13
  process.stdout.write(`\nLaunching translate using NPX.\n\n`);
13
- const npxExecutableName = process.platform === 'win32' ? 'npx.cmd' : 'npx';
14
- spawn(
14
+ const { npxExecutableName, sanitize, shell } = getPlatformSpawnArgs();
15
+
16
+ const projectDir = sanitize(argv['project-dir'], sanitizePath);
17
+ const locale = sanitize(argv.locale, sanitizeLocale);
18
+
19
+ const child = spawn(
15
20
  npxExecutableName,
16
- ['-y', '@redocly/realm', 'translate', argv.locale, `-d=${argv['project-dir']}`],
17
- { stdio: 'inherit' }
21
+ ['-y', '@redocly/realm', 'translate', locale, `-d=${projectDir}`],
22
+ {
23
+ stdio: 'inherit',
24
+ shell,
25
+ }
18
26
  );
27
+
28
+ child.on('error', (error) => {
29
+ process.stderr.write(`Translate launch failed: ${error.message}`);
30
+ throw new Error(`Translate launch failed.`);
31
+ });
19
32
  };
package/src/index.ts CHANGED
@@ -473,86 +473,94 @@ yargs
473
473
  'bundle [apis...]',
474
474
  'Bundle a multi-file API description to a single file.',
475
475
  (yargs) =>
476
- yargs.positional('apis', { array: true, type: 'string', demandOption: true }).options({
477
- output: {
478
- type: 'string',
479
- description: 'Output file.',
480
- alias: 'o',
481
- },
482
- ext: {
483
- description: 'Bundle file extension.',
484
- requiresArg: true,
485
- choices: outputExtensions,
486
- },
487
- 'skip-preprocessor': {
488
- description: 'Ignore certain preprocessors.',
489
- array: true,
490
- type: 'string',
491
- },
492
- 'skip-decorator': {
493
- description: 'Ignore certain decorators.',
494
- array: true,
495
- type: 'string',
496
- },
497
- dereferenced: {
498
- alias: 'd',
499
- type: 'boolean',
500
- description: 'Produce a fully dereferenced bundle.',
501
- },
502
- force: {
503
- alias: 'f',
504
- type: 'boolean',
505
- description: 'Produce bundle output even when errors occur.',
506
- },
507
- config: {
508
- description: 'Path to the config file.',
509
- type: 'string',
510
- },
511
- metafile: {
512
- description: 'Produce metadata about the bundle',
513
- type: 'string',
514
- },
515
- extends: {
516
- description: 'Override extends configurations (defaults or config file settings).',
517
- requiresArg: true,
518
- array: true,
519
- type: 'string',
520
- hidden: true,
521
- },
522
- 'remove-unused-components': {
523
- description: 'Remove unused components.',
524
- type: 'boolean',
525
- default: false,
526
- },
527
- 'keep-url-references': {
528
- description: 'Keep absolute url references.',
529
- type: 'boolean',
530
- alias: 'k',
531
- },
532
- 'lint-config': {
533
- description: 'Severity level for config file linting.',
534
- choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
535
- default: 'warn' as RuleSeverity,
536
- },
537
- format: {
538
- hidden: true,
539
- deprecated: true,
540
- },
541
- lint: {
542
- hidden: true,
543
- deprecated: true,
544
- },
545
- 'skip-rule': {
546
- hidden: true,
547
- deprecated: true,
548
- array: true,
549
- type: 'string',
550
- },
551
- 'max-problems': {
552
- hidden: true,
553
- deprecated: true,
554
- },
555
- }),
476
+ yargs
477
+ .positional('apis', { array: true, type: 'string', demandOption: true })
478
+ .options({
479
+ output: {
480
+ type: 'string',
481
+ description: 'Output file or folder for inline APIs.',
482
+ alias: 'o',
483
+ },
484
+ ext: {
485
+ description: 'Bundle file extension.',
486
+ requiresArg: true,
487
+ choices: outputExtensions,
488
+ },
489
+ 'skip-preprocessor': {
490
+ description: 'Ignore certain preprocessors.',
491
+ array: true,
492
+ type: 'string',
493
+ },
494
+ 'skip-decorator': {
495
+ description: 'Ignore certain decorators.',
496
+ array: true,
497
+ type: 'string',
498
+ },
499
+ dereferenced: {
500
+ alias: 'd',
501
+ type: 'boolean',
502
+ description: 'Produce a fully dereferenced bundle.',
503
+ },
504
+ force: {
505
+ alias: 'f',
506
+ type: 'boolean',
507
+ description: 'Produce bundle output even when errors occur.',
508
+ },
509
+ config: {
510
+ description: 'Path to the config file.',
511
+ type: 'string',
512
+ },
513
+ metafile: {
514
+ description: 'Produce metadata about the bundle',
515
+ type: 'string',
516
+ },
517
+ extends: {
518
+ description: 'Override extends configurations (defaults or config file settings).',
519
+ requiresArg: true,
520
+ array: true,
521
+ type: 'string',
522
+ hidden: true,
523
+ },
524
+ 'remove-unused-components': {
525
+ description: 'Remove unused components.',
526
+ type: 'boolean',
527
+ default: false,
528
+ },
529
+ 'keep-url-references': {
530
+ description: 'Keep absolute url references.',
531
+ type: 'boolean',
532
+ alias: 'k',
533
+ },
534
+ 'lint-config': {
535
+ description: 'Severity level for config file linting.',
536
+ choices: ['warn', 'error', 'off'] as ReadonlyArray<RuleSeverity>,
537
+ default: 'warn' as RuleSeverity,
538
+ },
539
+ format: {
540
+ hidden: true,
541
+ deprecated: true,
542
+ },
543
+ lint: {
544
+ hidden: true,
545
+ deprecated: true,
546
+ },
547
+ 'skip-rule': {
548
+ hidden: true,
549
+ deprecated: true,
550
+ array: true,
551
+ type: 'string',
552
+ },
553
+ 'max-problems': {
554
+ hidden: true,
555
+ deprecated: true,
556
+ },
557
+ })
558
+ .check((argv) => {
559
+ if (argv.output && (!argv.apis || argv.apis.length === 0)) {
560
+ throw new Error('At least one inline API must be specified when using --output.');
561
+ }
562
+ return true;
563
+ }),
556
564
  (argv) => {
557
565
  const DEPRECATED_OPTIONS = ['lint', 'format', 'skip-rule', 'max-problems'];
558
566
  const LINT_AND_BUNDLE_DOCUMENTATION_LINK =
@@ -778,7 +786,7 @@ yargs
778
786
  })
779
787
  .check((argv: any) => {
780
788
  if (argv.theme && !argv.theme?.openapi)
781
- throw Error('Invalid option: theme.openapi not set');
789
+ throw Error('Invalid option: theme.openapi not set.');
782
790
  return true;
783
791
  }),
784
792
  async (argv) => {
@@ -529,7 +529,7 @@ export function checkIfRulesetExist(rules: typeof StyleguideConfig.prototype.rul
529
529
  ...rules.oas3_1,
530
530
  ...rules.async2,
531
531
  ...rules.async3,
532
- ...rules.arazzo,
532
+ ...rules.arazzo1,
533
533
  };
534
534
 
535
535
  if (isEmptyObject(ruleset)) {
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Sanitizes the input path by removing invalid characters.
3
+ */
4
+ export const sanitizePath = (input: string): string => {
5
+ return input.replace(/[^a-zA-Z0-9 ._\-:\\/@]/g, '');
6
+ };
7
+
8
+ /**
9
+ * Sanitizes the input locale (ex. en-US) by removing invalid characters.
10
+ */
11
+ export const sanitizeLocale = (input: string): string => {
12
+ return input.replace(/[^a-zA-Z0-9@._-]/g, '');
13
+ };
14
+
15
+ /**
16
+ * Retrieves platform-specific arguments and utilities.
17
+ */
18
+ export function getPlatformSpawnArgs() {
19
+ const isWindowsPlatform = process.platform === 'win32';
20
+ const npxExecutableName = isWindowsPlatform ? 'npx.cmd' : 'npx';
21
+
22
+ const sanitizeIfWindows = (input: string | undefined, sanitizer: (input: string) => string) => {
23
+ if (isWindowsPlatform && input) {
24
+ return sanitizer(input);
25
+ } else {
26
+ return input || '';
27
+ }
28
+ };
29
+
30
+ return { npxExecutableName, sanitize: sanitizeIfWindows, shell: isWindowsPlatform };
31
+ }