diff --git a/.changeset/short-panthers-smoke.md b/.changeset/short-panthers-smoke.md
new file mode 100644
index 000000000..d35f4b549
--- /dev/null
+++ b/.changeset/short-panthers-smoke.md
@@ -0,0 +1,5 @@
+---
+"@redocly/cli": minor
+---
+
+Added the `eject` and `translate` commands for use with the new Reunite-hosted product family.
diff --git a/docs/commands/preview.md b/docs/commands/preview.md
index cde7570fd..f2cb95239 100644
--- a/docs/commands/preview.md
+++ b/docs/commands/preview.md
@@ -14,19 +14,19 @@ This command is for our pre-release products, currently open for early access to
redocly preview
redocly preview --product=revel
redocly preview --product=reef --plan=pro
-redocly preview --product=reef --plan=pro --source-dir=./my-docs-project --port=4001
+redocly preview --product=reef --plan=pro --project-dir=./my-docs-project --port=4001
```
## Options
-| Option | Type | Description |
-| ---------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| --help | boolean | Show help. |
-| --plan | string | Product plan to use in preview.
**Possible values:** `pro`, `enterprise`. The default value is `enterprise`. For more details, see [plans](https://redocly.com/pricing/). |
-| --product | string | Name of a product to preview the project with.
**Possible values:** `redoc`, `revel`, `reef`, `realm`, `redoc-revel`, `redoc-reef`, `revel-reef`.
`redoc` is the flagship product for generating API documentation from OpenAPI specifications.
`revel` is a specialized product designed for external API applications.
`reef` is a specialized product designed for internal API needs.
`realm` is a balanced product combining `redoc`, `revel`, and `reef`.
`redoc-revel` is a blended product combining `redoc` and `revel`.
`redoc-reef` is a blended product combining `redoc` and `reef`.
`revel-reef` is a blended product combining `revel` and `reef`.
The default value is autodetected from the project's `package.json` or `realm` is used. |
-| --source-dir, -d | string | Path to the project directory. The default value is `.` (current directory). |
-| --port | number | The port to run the preview server on. The default value is `4000`. |
-| --version | boolean | Show version number. |
+| Option | Type | Description |
+| ----------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| --help | boolean | Show help. |
+| --plan | string | Product plan to use in preview.
**Possible values:** `pro`, `enterprise`. The default value is `enterprise`. For more details, see [plans](https://redocly.com/pricing/). |
+| --product | string | Name of a product to preview the project with.
**Possible values:** `redoc`, `revel`, `reef`, `realm`, `redoc-revel`, `redoc-reef`, `revel-reef`.
`redoc` is the flagship product for generating API documentation from OpenAPI specifications.
`revel` is a specialized product designed for external API applications.
`reef` is a specialized product designed for internal API needs.
`realm` is a balanced product combining `redoc`, `revel`, and `reef`.
`redoc-revel` is a blended product combining `redoc` and `revel`.
`redoc-reef` is a blended product combining `redoc` and `reef`.
`revel-reef` is a blended product combining `revel` and `reef`.
The default value is autodetected from the project's `package.json` or `realm` is used. |
+| --project-dir, -d | string | Path to the project directory. The default value is `.` (current directory). |
+| --port, -p | number | The port to run the preview server on. The default value is `4000`. |
+| --version | boolean | Show version number. |
## Examples
@@ -50,10 +50,10 @@ redocly preview --plan=pro
### Specify project directory
-By default, the preview command uses the current directory. To specify another directory, provide a path relative to the current directory using the `--source-dir` option:
+By default, the preview command uses the current directory. To specify another directory, provide a path relative to the current directory using the `--project-dir` option:
```bash
-redocly preview --source-dir=./path/to/my/docs/
+redocly preview --project-dir=./path/to/my/docs/
```
### Use custom port for preview
diff --git a/packages/cli/src/cms/commands/push.ts b/packages/cli/src/cms/commands/push.ts
index a3b43ee60..c723ff917 100644
--- a/packages/cli/src/cms/commands/push.ts
+++ b/packages/cli/src/cms/commands/push.ts
@@ -13,6 +13,7 @@ import { ReuniteApiClient, getDomain, getApiKeys } from '../api';
import type { OutputFormat } from '@redocly/openapi-core';
import type { CommandArgs } from '../../wrapper';
+import type { VerifyConfigOptions } from '../../types';
export type PushOptions = {
apis?: string[];
@@ -33,13 +34,12 @@ export type PushOptions = {
'default-branch': string;
domain?: string;
- config?: string;
'wait-for-deployment'?: boolean;
'max-execution-time': number;
'continue-on-deploy-failures'?: boolean;
verbose?: boolean;
format?: Extract;
-};
+} & VerifyConfigOptions;
type FileToUpload = { name: string; path: string };
diff --git a/packages/cli/src/commands/build-docs/types.ts b/packages/cli/src/commands/build-docs/types.ts
index fce09113b..fb180c67f 100644
--- a/packages/cli/src/commands/build-docs/types.ts
+++ b/packages/cli/src/commands/build-docs/types.ts
@@ -1,3 +1,5 @@
+import type { VerifyConfigOptions } from '../../types';
+
export type BuildDocsOptions = {
watch?: boolean;
output?: string;
@@ -20,5 +22,4 @@ export type BuildDocsArgv = {
theme: {
openapi: string | Record;
};
- config?: string;
-};
+} & VerifyConfigOptions;
diff --git a/packages/cli/src/commands/bundle.ts b/packages/cli/src/commands/bundle.ts
index ee32d7289..0c2c8e8c6 100644
--- a/packages/cli/src/commands/bundle.ts
+++ b/packages/cli/src/commands/bundle.ts
@@ -14,13 +14,12 @@ import {
checkForDeprecatedOptions,
} from '../utils/miscellaneous';
-import type { OutputExtensions, Skips, Totals } from '../types';
+import type { OutputExtensions, Skips, Totals, VerifyConfigOptions } from '../types';
import type { CommandArgs } from '../wrapper';
export type BundleOptions = {
apis?: string[];
extends?: string[];
- config?: string;
output?: string;
ext: OutputExtensions;
dereferenced?: boolean;
@@ -28,7 +27,8 @@ export type BundleOptions = {
metafile?: string;
'remove-unused-components'?: boolean;
'keep-url-references'?: boolean;
-} & Skips;
+} & Skips &
+ VerifyConfigOptions;
export async function handleBundle({
argv,
diff --git a/packages/cli/src/commands/eject.ts b/packages/cli/src/commands/eject.ts
new file mode 100644
index 000000000..b02d4b879
--- /dev/null
+++ b/packages/cli/src/commands/eject.ts
@@ -0,0 +1,29 @@
+import { spawn } from 'child_process';
+
+import type { CommandArgs } from '../wrapper';
+import type { VerifyConfigOptions } from '../types';
+
+export type EjectOptions = {
+ type: 'component';
+ path: string;
+ 'project-dir'?: string;
+ force: boolean;
+} & VerifyConfigOptions;
+
+export const handleEject = async ({ argv }: CommandArgs) => {
+ process.stdout.write(`\nLaunching eject using NPX.\n\n`);
+ const npxExecutableName = process.platform === 'win32' ? 'npx.cmd' : 'npx';
+ spawn(
+ npxExecutableName,
+ [
+ '-y',
+ '@redocly/realm',
+ 'eject',
+ `${argv.type}`,
+ `${argv.path}`,
+ `-d=${argv['project-dir']}`,
+ argv.force ? `--force=${argv.force}` : '',
+ ],
+ { stdio: 'inherit' }
+ );
+};
diff --git a/packages/cli/src/commands/join.ts b/packages/cli/src/commands/join.ts
index 043091933..07d866e48 100644
--- a/packages/cli/src/commands/join.ts
+++ b/packages/cli/src/commands/join.ts
@@ -23,13 +23,7 @@ import { isObject, isString, keysOf } from '../utils/js-utils';
import { COMPONENTS, OPENAPI3_METHOD } from './split/types';
import { crawl, startsWithComponents } from './split';
-import type {
- Oas3Definition,
- Document,
- Oas3Tag,
- Referenced,
- RuleSeverity,
-} from '@redocly/openapi-core';
+import type { Oas3Definition, Document, Oas3Tag, Referenced } from '@redocly/openapi-core';
import type { BundleResult } from '@redocly/openapi-core/lib/bundle';
import type {
Oas3Parameter,
@@ -38,6 +32,7 @@ import type {
Oas3_1Definition,
} from '@redocly/openapi-core/lib/typings/openapi';
import type { CommandArgs } from '../wrapper';
+import type { VerifyConfigOptions } from '../types';
const Tags = 'tags';
const xTagGroups = 'x-tagGroups';
@@ -60,9 +55,7 @@ export type JoinOptions = {
'prefix-components-with-info-prop'?: string;
'without-x-tag-groups'?: boolean;
output?: string;
- config?: string;
- 'lint-config'?: RuleSeverity;
-};
+} & VerifyConfigOptions;
export async function handleJoin({
argv,
diff --git a/packages/cli/src/commands/lint.ts b/packages/cli/src/commands/lint.ts
index 8030b9a01..8f4a9bfc7 100644
--- a/packages/cli/src/commands/lint.ts
+++ b/packages/cli/src/commands/lint.ts
@@ -23,20 +23,19 @@ import {
import { getCommandNameFromArgs } from '../utils/getCommandNameFromArgs';
import type { Arguments } from 'yargs';
-import type { OutputFormat, ProblemSeverity, RuleSeverity } from '@redocly/openapi-core';
+import type { OutputFormat, ProblemSeverity } from '@redocly/openapi-core';
import type { RawConfigProcessor } from '@redocly/openapi-core/lib/config';
-import type { CommandOptions, Skips, Totals } from '../types';
+import type { CommandOptions, Skips, Totals, VerifyConfigOptions } from '../types';
import type { CommandArgs } from '../wrapper';
export type LintOptions = {
apis?: string[];
'max-problems': number;
extends?: string[];
- config?: string;
format: OutputFormat;
'generate-ignore-file'?: boolean;
- 'lint-config'?: RuleSeverity;
-} & Omit;
+} & Omit &
+ VerifyConfigOptions;
export async function handleLint({
argv,
diff --git a/packages/cli/src/commands/preview-docs/index.ts b/packages/cli/src/commands/preview-docs/index.ts
index c075dd88e..7b0ec99e4 100644
--- a/packages/cli/src/commands/preview-docs/index.ts
+++ b/packages/cli/src/commands/preview-docs/index.ts
@@ -8,7 +8,7 @@ import {
} from '../../utils/miscellaneous';
import startPreviewServer from './preview-server/preview-server';
-import type { Skips } from '../../types';
+import type { Skips, VerifyConfigOptions } from '../../types';
import type { CommandArgs } from '../../wrapper';
export type PreviewDocsOptions = {
@@ -18,7 +18,8 @@ export type PreviewDocsOptions = {
config?: string;
api?: string;
force?: boolean;
-} & Omit;
+} & Omit &
+ VerifyConfigOptions;
export async function previewDocs({
argv,
diff --git a/packages/cli/src/commands/preview-project/index.ts b/packages/cli/src/commands/preview-project/index.ts
index cc32bf639..cedc6e501 100644
--- a/packages/cli/src/commands/preview-project/index.ts
+++ b/packages/cli/src/commands/preview-project/index.ts
@@ -8,19 +8,19 @@ import type { CommandArgs } from '../../wrapper';
export const previewProject = async ({ argv }: CommandArgs) => {
const { plan, port } = argv;
- const projectDir = argv['source-dir'];
+ const projectDir = argv['project-dir'];
const product = argv.product || tryGetProductFromPackageJson(projectDir);
if (!isValidProduct(product)) {
- process.stderr.write(`Invalid product ${product}`);
- throw new Error(`Project preview launch failed`);
+ process.stderr.write(`Invalid product ${product}.`);
+ throw new Error(`Project preview launch failed.`);
}
const productName = PRODUCT_NAMES[product];
const packageName = PRODUCT_PACKAGES[product];
- process.stdout.write(`\nLaunching preview of ${productName} ${plan} using NPX\n\n`);
+ process.stdout.write(`\nLaunching preview of ${productName} ${plan} using NPX.\n\n`);
const npxExecutableName = process.platform === 'win32' ? 'npx.cmd' : 'npx';
diff --git a/packages/cli/src/commands/preview-project/types.ts b/packages/cli/src/commands/preview-project/types.ts
index b561b0d39..34fdc9759 100644
--- a/packages/cli/src/commands/preview-project/types.ts
+++ b/packages/cli/src/commands/preview-project/types.ts
@@ -1,3 +1,4 @@
+import type { VerifyConfigOptions } from '../../types';
import type { PRODUCT_PACKAGES, PRODUCT_PLANS } from './constants';
export type Product = keyof typeof PRODUCT_PACKAGES;
@@ -7,6 +8,5 @@ export type PreviewProjectOptions = {
product?: Product | string;
plan: ProductPlan | string;
port?: number;
- 'source-dir': string;
- config?: string;
-};
+ 'project-dir': string;
+} & VerifyConfigOptions;
diff --git a/packages/cli/src/commands/push.ts b/packages/cli/src/commands/push.ts
index ea98a257f..6b7a79425 100644
--- a/packages/cli/src/commands/push.ts
+++ b/packages/cli/src/commands/push.ts
@@ -25,6 +25,7 @@ import { handlePush as handleCMSPush } from '../cms/commands/push';
import type { Config, BundleOutputFormat, Region } from '@redocly/openapi-core';
import type { CommandArgs } from '../wrapper';
+import type { VerifyConfigOptions } from '../types';
const DEFAULT_VERSION = 'latest';
@@ -44,8 +45,7 @@ export type PushOptions = {
public?: boolean;
files?: string[];
organization?: string;
- config?: string;
-};
+} & VerifyConfigOptions;
export function commonPushHandler({
project,
diff --git a/packages/cli/src/commands/split/index.ts b/packages/cli/src/commands/split/index.ts
index 49ea5749b..0c5881610 100644
--- a/packages/cli/src/commands/split/index.ts
+++ b/packages/cli/src/commands/split/index.ts
@@ -37,13 +37,13 @@ import type {
Referenced,
} from './types';
import type { CommandArgs } from '../../wrapper';
+import type { VerifyConfigOptions } from '../../types';
export type SplitOptions = {
api: string;
outDir: string;
separator: string;
- config?: string;
-};
+} & VerifyConfigOptions;
export async function handleSplit({ argv, collectSpecData }: CommandArgs) {
const startedAt = performance.now();
diff --git a/packages/cli/src/commands/stats.ts b/packages/cli/src/commands/stats.ts
index 1ade7b74a..c31249464 100755
--- a/packages/cli/src/commands/stats.ts
+++ b/packages/cli/src/commands/stats.ts
@@ -13,7 +13,6 @@ import {
} from '@redocly/openapi-core';
import { getFallbackApisOrExit, printExecutionTime } from '../utils/miscellaneous';
-import type { CommandArgs } from '../wrapper';
import type {
StatsAccumulator,
StatsName,
@@ -21,6 +20,8 @@ import type {
OutputFormat,
StyleguideConfig,
} from '@redocly/openapi-core';
+import type { CommandArgs } from '../wrapper';
+import type { VerifyConfigOptions } from '../types';
const statsAccumulator: StatsAccumulator = {
refs: { metric: '🚗 References', total: 0, color: 'red', items: new Set() },
@@ -89,8 +90,7 @@ function printStats(
export type StatsOptions = {
api?: string;
format: OutputFormat;
- config?: string;
-};
+} & VerifyConfigOptions;
export async function handleStats({ argv, config, collectSpecData }: CommandArgs) {
const [{ path }] = await getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
diff --git a/packages/cli/src/commands/translations.ts b/packages/cli/src/commands/translations.ts
new file mode 100644
index 000000000..1c7ca8b8b
--- /dev/null
+++ b/packages/cli/src/commands/translations.ts
@@ -0,0 +1,19 @@
+import { spawn } from 'child_process';
+
+import type { CommandArgs } from '../wrapper';
+import type { VerifyConfigOptions } from '../types';
+
+export type TranslationsOptions = {
+ locale: string;
+ 'project-dir'?: string;
+} & VerifyConfigOptions;
+
+export const handleTranslations = async ({ argv }: CommandArgs) => {
+ process.stdout.write(`\nLaunching translate using NPX.\n\n`);
+ const npxExecutableName = process.platform === 'win32' ? 'npx.cmd' : 'npx';
+ spawn(
+ npxExecutableName,
+ ['-y', '@redocly/realm', 'translate', argv.locale, `-d=${argv['project-dir']}`],
+ { stdio: 'inherit' }
+ );
+};
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 0a95b428c..fa5a88270 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -21,6 +21,8 @@ import {
} from './utils/update-version-notifier';
import { commandWrapper } from './wrapper';
import { previewProject } from './commands/preview-project';
+import { handleTranslations } from './commands/translations';
+import { handleEject } from './commands/eject';
import { PRODUCT_PLANS } from './commands/preview-project/constants';
import { commonPushHandler } from './commands/push';
@@ -29,6 +31,7 @@ import type { OutputFormat, RuleSeverity } from '@redocly/openapi-core';
import type { BuildDocsArgv } from './commands/build-docs/types';
import type { PushStatusOptions } from './cms/commands/push-status';
import type { PushArguments } from './types';
+import type { EjectOptions } from './commands/eject';
if (!('replaceAll' in String.prototype)) {
require('core-js/actual/string/replace-all');
@@ -228,6 +231,11 @@ yargs
type: 'boolean',
default: false,
},
+ 'lint-config': {
+ description: 'Severity level for config file linting.',
+ choices: ['warn', 'error', 'off'] as ReadonlyArray,
+ default: 'warn' as RuleSeverity,
+ },
}),
(argv) => {
process.env.REDOCLY_CLI_COMMAND = 'push-status';
@@ -642,18 +650,32 @@ yargs
default: 'enterprise',
},
port: {
+ alias: 'p',
type: 'number',
description: 'Preview port.',
default: 4000,
},
- 'source-dir': {
- alias: 'd',
+ 'project-dir': {
+ alias: ['d', 'source-dir'],
type: 'string',
- description: 'Project directory.',
+ description:
+ 'Specifies the project content directory. The default value is the directory where the command is executed.',
default: '.',
},
+ 'lint-config': {
+ description: 'Severity level for config file linting.',
+ choices: ['warn', 'error', 'off'] as ReadonlyArray,
+ default: 'warn' as RuleSeverity,
+ },
}),
(argv) => {
+ if (process.argv.some((arg) => arg.startsWith('--source-dir'))) {
+ process.stderr.write(
+ colors.red(
+ 'Option --source-dir is deprecated and will be removed soon. Use --project-dir instead.\n'
+ )
+ );
+ }
commandWrapper(previewProject)(argv);
}
)
@@ -764,6 +786,77 @@ yargs
commandWrapper(handlerBuildCommand)(argv as Arguments);
}
)
+ .command(
+ 'translate ',
+ 'Creates or updates translations.yaml files and fills them with missing built-in translations and translations from the redocly.yaml and sidebars.yaml files.',
+ (yargs) =>
+ yargs
+ .positional('locale', {
+ description:
+ 'Locale code to generate translations for, or `all` for all current project locales.',
+ type: 'string',
+ demandOption: true,
+ })
+ .options({
+ 'project-dir': {
+ alias: 'd',
+ type: 'string',
+ description:
+ 'Specifies the project content directory. The default value is the directory where the command is executed.',
+ default: '.',
+ },
+ 'lint-config': {
+ description: 'Severity level for config file linting.',
+ choices: ['warn', 'error', 'off'] as ReadonlyArray,
+ default: 'warn' as RuleSeverity,
+ },
+ }),
+ (argv) => {
+ process.env.REDOCLY_CLI_COMMAND = 'translate';
+ commandWrapper(handleTranslations)(argv);
+ }
+ )
+ .command(
+ 'eject ',
+ 'Helper function to eject project elements for customization.',
+ (yargs) =>
+ yargs
+ .positional('type', {
+ description:
+ 'Specifies what type of project element to eject. Currently, it could be only `component`.',
+ demandOption: true,
+ choices: ['component'],
+ })
+ .positional('path', {
+ description: 'Filepath to a component or filepath with glob pattern.',
+ type: 'string',
+ demandOption: true,
+ })
+ .options({
+ 'project-dir': {
+ alias: 'd',
+ type: 'string',
+ description:
+ 'Specifies the project content directory. The default value is the directory where the command is executed.',
+ default: '.',
+ },
+ force: {
+ alias: 'f',
+ type: 'boolean',
+ description:
+ 'Skips the "overwrite existing" confirmation when ejecting a component that is already ejected in the destination.',
+ },
+ 'lint-config': {
+ description: 'Severity level for config file linting.',
+ choices: ['warn', 'error', 'off'] as ReadonlyArray,
+ default: 'warn' as RuleSeverity,
+ },
+ }),
+ (argv) => {
+ process.env.REDOCLY_CLI_COMMAND = 'eject';
+ commandWrapper(handleEject)(argv as Arguments);
+ }
+ )
.completion('completion', 'Generate autocomplete script for `redocly` command.')
.demandCommand(1)
.middleware([notifyUpdateCliVersion])
diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts
index bce718cc7..45313b7fd 100644
--- a/packages/cli/src/types.ts
+++ b/packages/cli/src/types.ts
@@ -1,4 +1,4 @@
-import type { BundleOutputFormat, Region, Config } from '@redocly/openapi-core';
+import type { BundleOutputFormat, Region, Config, RuleSeverity } from '@redocly/openapi-core';
import type { ArgumentsCamelCase } from 'yargs';
import type { LintOptions } from './commands/lint';
import type { BundleOptions } from './commands/bundle';
@@ -12,6 +12,8 @@ import type { BuildDocsArgv } from './commands/build-docs/types';
import type { PushOptions as CMSPushOptions } from './cms/commands/push';
import type { PushStatusOptions } from './cms/commands/push-status';
import type { PreviewProjectOptions } from './commands/preview-project/types';
+import type { TranslationsOptions } from './commands/translations';
+import type { EjectOptions } from './commands/eject';
export type Totals = {
errors: number;
@@ -37,12 +39,13 @@ export type CommandOptions =
| PreviewDocsOptions
| BuildDocsArgv
| PushStatusOptions
- | VerifyConfigOptions
- | PreviewProjectOptions;
+ | PreviewProjectOptions
+ | TranslationsOptions
+ | EjectOptions;
export type VerifyConfigOptions = {
config?: string;
- 'lint-config'?: 'warning' | 'error' | 'off';
+ 'lint-config'?: RuleSeverity;
};
export type Skips = {