Repository: Redocly/redocly-cli
Pull request #789 (2022-07-31 16:09:00)

chore: add tests for rules utils
## What/Why/How?

Add tests to cover part of rules utils.

## Reference

Originally started with #786 which was erroneous because `type: any` doesn't exist any longer.

## Testing

This revealed we missed an `integer` case for one method: `oasTypeOf`.

I added that and covered it with tests.


## Screenshots (optional)

One open question:

```ts
export function missingRequiredField(type: string, field: string): string {
  return `${type} object should contain \`${field}\` field.`;
}
```

Is the correct word `should` (as is) or `must`? For example, 

> Tag object should contain `description` field.

> Tag object must contain `description` field.

## Check yourself

- [x] Code is linted (see #787)
- [ ] Tested with redoc/reference-docs/workflows
- [x] All new/updated code is covered with tests

## Security

- [x] Security impact of change has been considered
- [x] Code follows company security practices and guidelines


github-actions[bot]: <!-- jest coverage report action for options with hash 3339ae53a38c44382c0fb4491bdb282d -->

## Coverage report 



| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | Category   | Percentage | Covered / Total |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :--------- | :--------- | :-------------: |
|                                                                           🟡                                                                           | Statements | 67.91%     |    2833/4172    |
|                                                                           🟡                                                                           | Branches   | 61.19%     |    1567/2561    |
|                                                                           🔴                                                                           | Functions  | 59.19%     |     451/762     |
|                                                                           🟡                                                                           | Lines      | 68.18%     |    2629/3856    |


## Test suite run success
444 tests passing in 75 suites.

<p align="right">Report generated by <a href="https://github.com/ArtiomTr/jest-coverage-report-action">🧪jest coverage report action</a> from df727e3757a488dd91b22c52f5927168fb795a8d</p>


Patch:
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index dbd0a0ce..2b9cc4c3 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -15,7 +15,7 @@ Hi! We're really excited that you are interested in contributing to Redocly CLI.
 
 - The best way to get your bug fixed is to provide a (reduced) test case. This means listing and explaining the steps we should take to try and hit the same problem you're having. It helps us understand in which conditions the issue appears, and gives us a better idea of what may be causing it.
 
-- Abide by our [Code of Conduct](https://redoc.ly/code-of-conduct/) in all your interactions on this repository, and show patience and respect to other community members.
+- Abide by our [Code of Conduct](https://redocly.com/code-of-conduct/) in all your interactions on this repository, and show patience and respect to other community members.
 
 ## Pull Request Guidelines
 Before submitting a pull request, please make sure the following is done:
diff --git a/docs/commands/bundle.md b/docs/commands/bundle.md
index 6f82d3ac..8289b571 100644
--- a/docs/commands/bundle.md
+++ b/docs/commands/bundle.md
@@ -15,10 +15,10 @@ To learn more about preprocessors, rules, and decorators, refer to the [custom r
 ## Usage
 
 ```bash
-redocly bundle <entrypoints>...
-redocly bundle <entrypoints> [--max-problems=<n>]
-redocly bundle <entrypoints> [--lint] [--config=<path>]
-redocly bundle <entrypoints>... -o <outputName> --ext <ext>
+redocly bundle <apis>...
+redocly bundle <apis> [--max-problems=<n>]
+redocly bundle <apis> [--lint] [--config=<path>]
+redocly bundle <apis>... -o <outputName> --ext <ext>
 redocly bundle --version
 ```
 
@@ -26,7 +26,7 @@ redocly bundle --version
 
 Option | Type | Description
 -- | -- | --
-entrypoints | [string] | List of API root definition filenames or names assigned in the `apis` section of your Redocly configuration file. Default values are all names defined in the `apis` section within your configuration file.
+apis | [string] | List of API root definition filenames or names assigned in the `apis` section of your Redocly configuration file. Default values are all names defined in the `apis` section within your configuration file.
 --config | string | Specify path to the [config file](#custom-configuration-file).
 --dereferenced, -d | boolean | Generate fully dereferenced bundle.
 --ext | string | Specify bundled file extension. Possible values are `json`, `yaml`, or `yml`. Default value is `yaml`.
@@ -58,7 +58,7 @@ redocly bundle openapi/openapi.yaml --output dist/openapi.json
 
 ### Bundle multiple API definitions
 
-This command creates one bundled file for each of the specified entrypoints in the `dist/` folder. Bundled files are in JSON format.
+This command creates one bundled file for each of the specified apis in the `dist/` folder. Bundled files are in JSON format.
 
 ```bash Command
 redocly bundle --output dist --ext json openapi/openapi.yaml openapi/petstore.yaml
diff --git a/docs/commands/join.md b/docs/commands/join.md
index deb8bda1..8bfc5ffa 100644
--- a/docs/commands/join.md
+++ b/docs/commands/join.md
@@ -26,7 +26,7 @@ Apart from providing individual API definition files as the input, you can also
 ### Usage
 
 ```bash
-redocly join <entrypoint> <entrypoint>...
+redocly join <api> <api>...
 redocly join <path-to-folder>/<wildcard-pattern> [--lint]
 redocly join [--help] [--prefix-components-with-info-prop] [--prefix-tags-with-info-prop] [--prefix-tags-with-filename]
 
@@ -40,7 +40,7 @@ redocly join --version
 
 Option | Type | Description
 -- | -- | --
-entrypoints | array | **REQUIRED.**  1. Array of paths to API definition files that you want to join. At least two input files are required.<br />2. A wildcard pattern to match API definition files within a specific folder.
+apis | array | **REQUIRED.**  1. Array of paths to API definition files that you want to join. At least two input files are required.<br />2. A wildcard pattern to match API definition files within a specific folder.
 --help | boolean | Show help.
 --lint | boolean | Lint definition files.
 --prefix-tags-with-filename | string | Prefix tags with property value from file name. See the [prefix-tags-with-filename section](#prefix-tags-with-filename) below.
diff --git a/docs/commands/lint.md b/docs/commands/lint.md
index 56164e33..1786d13d 100644
--- a/docs/commands/lint.md
+++ b/docs/commands/lint.md
@@ -14,7 +14,7 @@ To learn more about preprocessors and rules, refer to the [custom rules](../reso
 
 ```bash
 redocly lint
-redocly lint <entrypoints>...
+redocly lint <apis>...
 redocly lint [--max-problems=<n>] [--config=<path>] [--format=<value>]
 redocly lint [--generate-ignore-file] [--help]
 redocly lint --version
@@ -24,7 +24,7 @@ redocly lint --version
 
 Option | Type | Description
 -- | -- | --
-entrypoints | array | Array of API definition filenames that need to be linted. See [the Entrypoints section](#entrypoints) for more options.
+apis | array | Array of API definition filenames that need to be linted. See [the Apis section](#apis) for more options.
 --config | string | Specify path to the [configuration file](#custom-configuration-file).
 --extends | array | [Extend a specific configuration](#extend-configuration) (defaults or config file settings).
 --format | string | Format for the output.<br />**Possible values:** `codeframe`, `stylish`, `json`, `checkstyle`, `codeclimate`.
@@ -38,11 +38,11 @@ entrypoints | array | Array of API definition filenames that need to be linted.
 
 ## Examples
 
-### Entrypoints
+### Apis
 
-The `lint` command behaves differently depending on how you pass entrypoints to it and whether the [configuration file](#custom-configuration-file) exists.
+The `lint` command behaves differently depending on how you pass apis to it and whether the [configuration file](#custom-configuration-file) exists.
 
-#### Pass entrypoints directly
+#### Pass apis directly
 
 ```bash
 redocly lint openapi/openapi.yaml
@@ -50,11 +50,11 @@ redocly lint openapi/openapi.yaml
 
 In this case, `lint` will validate the definition(s) passed to the command. The configuration file is ignored.
 
-The `entrypoints` argument can also use any glob format supported by your file system. For example, `redocly lint ./root-documents/*.yaml`.
+The `apis` argument can also use any glob format supported by your file system. For example, `redocly lint ./root-documents/*.yaml`.
 
-#### Pass entrypoints via configuration file
+#### Pass apis via configuration file
 
-Instead of full paths, you can use names listed in the `apis` section of your Redocly configuration file as entrypoints.
+Instead of full paths, you can use names listed in the `apis` section of your Redocly configuration file.
 
 ```bash Command
 redocly lint core@v1
@@ -68,9 +68,9 @@ apis:
 
 In this case, after resolving the path behind the `core@v1` name (see the `Configuration file` tab), `lint` will validate the `definition.json` file. The presence of the Redocly configuration file is mandatory.
 
-#### Empty entrypoints
+#### Empty apis
 
-You can omit entrypoints completely when executing the `lint` command.
+You can omit apis completely when executing the `lint` command.
 
 ```bash Command
 redocly lint
@@ -86,11 +86,11 @@ apis:
     root: ./openapi/sandbox.yaml
 ```
 
-In this case, if no API definitions are specified, `lint` validates all entrypoints listed under `apis` in your Redocly configuration file. The presence of the configuration file is mandatory.
+In this case, if no API definitions are specified, `lint` validates all apis listed under `apis` in your Redocly configuration file. The presence of the configuration file is mandatory.
 
 :::warning Important
 
-If you try to execute the `lint` command without entrypoints when your project doesn't have any configuration files, the `lint` command will display an error.
+If you try to execute the `lint` command without apis when your project doesn't have any configuration files, the `lint` command will display an error.
 
 :::
 
diff --git a/docs/commands/preview-docs.md b/docs/commands/preview-docs.md
index 08745b81..05a4812c 100644
--- a/docs/commands/preview-docs.md
+++ b/docs/commands/preview-docs.md
@@ -13,17 +13,17 @@ To preview docs using the premium Redocly API reference docs, you must first aut
 ## Usage
 
 ```bash
-redocly preview-docs <entrypoint> [branchName]
-redocly preview-docs <entrypoint> [--config=<path>] [--port=<value>] [--host=<host>] [branchName]
-redocly preview-docs <entrypoint> [--force] [--help] [--version] [branchName]
-redocly preview-docs <entrypoint> --version
+redocly preview-docs <api>
+redocly preview-docs <api> [--config=<path>] [--port=<value>] [--host=<host>]
+redocly preview-docs <api> [--force] [--help] [--version]
+redocly preview-docs <api> --version
 ```
 
 ## Options
 
 Option | Type | Description
 -- | -- | --
-entrypoints | array | Path to the API definition filename or alias that you want to generate the preview for. Refer to [the entrypoints section](#entrypoints) for more options.
+api | string | Path to the API definition filename or alias that you want to generate the preview for. Refer to [the api section](#api) for more options.
 --config | string | Specify path to the [configuration file](#custom-configuration-file).
 --force, -f | boolean | Generate preview output even when errors occur.
 --help | boolean | Show help.
@@ -36,11 +36,11 @@ entrypoints | array | Path to the API definition filename or alias that you want
 
 ## Examples
 
-### Entrypoints
+### Api
 
-The command behaves differently depending on how you pass the entrypoint to it, and whether the [configuration file](#custom-configuration-file) exists.
+The command behaves differently depending on how you pass the api to it, and whether the [configuration file](#custom-configuration-file) exists.
 
-#### Pass entrypoint directly
+#### Pass api directly
 
 ```bash
 redocly preview-docs openapi/openapi.yaml
@@ -48,9 +48,9 @@ redocly preview-docs openapi/openapi.yaml
 
 In this case, `preview-docs` will preview the definition that was passed to the command. The configuration file is ignored.
 
-#### Pass entrypoint alias
+#### Pass api alias
 
-Instead of a full path, you can use an API name from the `apis` section of your Redocly configuration file as the entrypoint.
+Instead of a full path, you can use an API name from the `apis` section of your Redocly configuration file.
 
 ```bash Command
 redocly preview-docs core@v1
diff --git a/docs/commands/push.md b/docs/commands/push.md
index 5eca2505..3070e39b 100644
--- a/docs/commands/push.md
+++ b/docs/commands/push.md
@@ -69,7 +69,7 @@ To authenticate to the API registry, you can use several approaches:
 ## Usage
 
 ```bash
-redocly push [entrypoint] <destination>
+redocly push [api] <destination>
 redocly push
 redocly push [-u] [--batch-id id] [--batch-size number] <path/to/definition.yaml> <@organization-id/api-name@api-version> [--branch]
 ```
@@ -78,7 +78,7 @@ redocly push [-u] [--batch-id id] [--batch-size number] <path/to/definition.yaml
 
 Option           | Type      | Description    |
 -----------------|:---------:|------------|
-entrypoint       | string    | The API definition that you want to push to the Redocly API registry. Provide it as a path to the root API definition file (or as an alias). See [Set options explicitly](#set-options-explicitly) for more information.  |
+api              | string    | The API definition that you want to push to the Redocly API registry. Provide it as a path to the root API definition file (or as an alias). See [Set options explicitly](#set-options-explicitly) for more information.  |
 destination      | string    | Conditional. The location in the API registry where you want to push or upsert your API definition. Provide it in the following format: `@organization-id/api-name@api-version` or `api-name@api-version`if organization ID is already defined in the configuration file. See [the Destination section](#destination) for more information.  |
 --branch, -b    | string  | The branch where your API definition will be pushed or upserted. Default value is `main`.  |
 --batch-id       | string  | Specifies the ID of the CI job that the current push will be associated with. See [the Batch ID section](#batch-id) for more information.  |
@@ -165,7 +165,7 @@ The version of your API should contain only supported characters (`a-z`, `A-Z`,
 
 ### Set options explicitly
 
-Provide the `entrypoint` as a path to the root API definition file, and specify the organization ID, API name and version.
+Provide the `api` as a path to the root API definition file, and specify the organization ID, API name and version.
 
 ```bash
 redocly push openapi/petstore.yaml @openapi-org/petstore-api@v1
diff --git a/docs/commands/split.md b/docs/commands/split.md
index 3b204303..a770642c 100644
--- a/docs/commands/split.md
+++ b/docs/commands/split.md
@@ -11,7 +11,7 @@ The `split` command doesn't support OpenAPI 2.0 definitions.
 ## Usage
 
 ```bash
-redocly split <entrypoint> --outDir=<path>
+redocly split <api> --outDir=<path>
 redocly split [--help] [--version]
 redocly split --version
 ```
@@ -20,7 +20,7 @@ redocly split --version
 
 Option | Type | Description
 -- | -- | --
-entrypoint | string | **REQUIRED.** Path to the API definition file that you want to split into a multi-file structure.
+api | string | **REQUIRED.** Path to the API definition file that you want to split into a multi-file structure.
 --outDir | string | **REQUIRED.** Path to the directory where you want to save split files. If the specified directory doesn't exist, it will be created automatically.
 --help | boolean | Show help.
 --separator | string | File path separator used while splitting. The default value is `_`. This controls the file names generated in the `paths` folder (e.g. `/users/create` path becomes `user_create.yaml`).
diff --git a/docs/commands/stats.md b/docs/commands/stats.md
index e31153ad..8645f75a 100644
--- a/docs/commands/stats.md
+++ b/docs/commands/stats.md
@@ -16,8 +16,8 @@ The `stats` command provides statistics about the structure of one or more API d
 ## Usage
 
 ```bash
-redocly stats <entrypoint>
-redocly stats <entrypoint> [--format] [--config=<path>]
+redocly stats <api>
+redocly stats <api> [--format] [--config=<path>]
 redocly stats --version
 ```
 
@@ -25,7 +25,7 @@ redocly stats --version
 
 Option | Type | Description
 -- | -- | --
-entrypoint | string | **REQUIRED.** Path to the API definition file that you want to split into a multi-file structure.
+api | string | **REQUIRED.** Path to the API definition file that you want to split into a multi-file structure.
 --config | string | Specify path to the [configuration file](#custom-configuration-file).
 --format | string | Format for the output.<br />**Possible values:** `stylish`, `json`.
 --help | boolean | Show help.
@@ -33,11 +33,11 @@ entrypoint | string | **REQUIRED.** Path to the API definition file that you wan
 
 ## Examples
 
-### Entrypoint
+### Api
 
-The `stats` command behaves differently depending on how you pass the entrypoint to it and whether the [configuration file](#custom-configuration-file) exists.
+The `stats` command behaves differently depending on how you pass the api to it and whether the [configuration file](#custom-configuration-file) exists.
 
-#### Pass entrypoint directly
+#### Pass api directly
 
 ```bash
 redocly stats openapi/openapi.yaml
@@ -45,9 +45,9 @@ redocly stats openapi/openapi.yaml
 
 In this case, `stats` will show statistics for the definition that was passed to the command. The configuration file is ignored.
 
-#### Pass entrypoint via configuration file
+#### Pass api via configuration file
 
-Instead of full paths, you can use API names from the `apis` section of your Redocly configuration file as entrypoints.
+Instead of full paths, you can use API names from the `apis` section of your Redocly configuration file.
 
 ```bash Command
 redocly stats core@v1
diff --git a/packages/cli/src/__mocks__/utils.ts b/packages/cli/src/__mocks__/utils.ts
index 8c8b11f5..78deab18 100644
--- a/packages/cli/src/__mocks__/utils.ts
+++ b/packages/cli/src/__mocks__/utils.ts
@@ -1,4 +1,4 @@
-export const getFallbackEntryPointsOrExit = jest.fn((entrypoints) =>
+export const getFallbackApisOrExit = jest.fn((entrypoints) =>
   entrypoints.map((path: string) => ({ path }))
 );
 export const dumpBundle = jest.fn(() => '');
diff --git a/packages/cli/src/commands/bundle.ts b/packages/cli/src/commands/bundle.ts
index 498f6958..7636d3e2 100644
--- a/packages/cli/src/commands/bundle.ts
+++ b/packages/cli/src/commands/bundle.ts
@@ -3,55 +3,46 @@ import {
   getTotals,
   loadConfig,
   getMergedConfig,
-  OutputFormat,
   lint,
   bundle,
 } from '@redocly/openapi-core';
 import {
   dumpBundle,
   getExecutionTime,
-  getFallbackEntryPointsOrExit,
+  getFallbackApisOrExit,
   getOutputFileName,
   handleError,
   printUnusedWarnings,
   saveBundle,
   printLintTotals,
 } from '../utils';
-import { OutputExtensions, Totals } from '../types';
+import type { CommonOptions, OutputExtensions, Skips, Totals } from '../types';
 import { performance } from 'perf_hooks';
 import { blue, gray, green, red, yellow } from 'colorette';
 import { writeFileSync } from 'fs';
 
-export async function handleBundle(
-  argv: {
-    entrypoints: string[];
+export type BundleOptions = CommonOptions &
+  Skips & {
     output?: string;
     ext: OutputExtensions;
-    'max-problems'?: number;
-    'skip-rule'?: string[];
-    'skip-preprocessor'?: string[];
-    'skip-decorator'?: string[];
     dereferenced?: boolean;
     force?: boolean;
-    config?: string;
     lint?: boolean;
-    format: OutputFormat;
     metafile?: string;
-    extends?: string[];
     'remove-unused-components'?: boolean;
     'keep-url-references'?: boolean;
-  },
-  version: string
-) {
+  };
+
+export async function handleBundle(argv: BundleOptions, version: string) {
   const config = await loadConfig(argv.config, argv.extends);
   const removeUnusedComponents =
     argv['remove-unused-components'] &&
     !config.rawConfig.styleguide?.decorators?.hasOwnProperty('remove-unused-components');
-  const entrypoints = await getFallbackEntryPointsOrExit(argv.entrypoints, config);
+  const apis = await getFallbackApisOrExit(argv.apis, config);
   const totals: Totals = { errors: 0, warnings: 0, ignored: 0 };
   const maxProblems = argv['max-problems'];
 
-  for (const { path, alias } of entrypoints) {
+  for (const { path, alias } of apis) {
     try {
       const startedAt = performance.now();
       const resolvedConfig = getMergedConfig(config, alias);
@@ -105,12 +96,7 @@ export async function handleBundle(
       });
 
       const fileTotals = getTotals(problems);
-      const { outputFile, ext } = getOutputFileName(
-        path,
-        entrypoints.length,
-        argv.output,
-        argv.ext
-      );
+      const { outputFile, ext } = getOutputFileName(path, apis.length, argv.output, argv.ext);
 
       if (fileTotals.errors === 0 || argv.force) {
         if (!argv.output) {
@@ -134,9 +120,9 @@ export async function handleBundle(
       });
 
       if (argv.metafile) {
-        if (entrypoints.length > 1) {
+        if (apis.length > 1) {
           process.stderr.write(
-            yellow(`[WARNING] "--metafile" cannot be used with multiple entrypoints. Skipping...`)
+            yellow(`[WARNING] "--metafile" cannot be used with multiple apis. Skipping...`)
           );
         }
         {
diff --git a/packages/cli/src/commands/join.ts b/packages/cli/src/commands/join.ts
index 8c5477d3..13d7f44c 100644
--- a/packages/cli/src/commands/join.ts
+++ b/packages/cli/src/commands/join.ts
@@ -19,7 +19,7 @@ import {
 } from '@redocly/openapi-core';
 
 import {
-  getFallbackEntryPointsOrExit,
+  getFallbackApisOrExit,
   printExecutionTime,
   handleError,
   printLintTotals,
@@ -34,8 +34,8 @@ const xTagGroups = 'x-tagGroups';
 let potentialConflictsTotal = 0;
 
 type JoinDocumentContext = {
-  entrypoint: string;
-  entrypointFilename: string;
+  api: string;
+  apiFilename: string;
   tags: Oas3Tag[];
   potentialConflicts: any;
   tagsPrefix: string;
@@ -43,7 +43,7 @@ type JoinDocumentContext = {
 };
 
 type JoinArgv = {
-  entrypoints: string[];
+  apis: string[];
   lint?: boolean;
   'prefix-tags-with-info-prop'?: string;
   'prefix-tags-with-filename'?: boolean;
@@ -53,8 +53,8 @@ type JoinArgv = {
 
 export async function handleJoin(argv: JoinArgv, packageVersion: string) {
   const startedAt = performance.now();
-  if (argv.entrypoints.length < 2) {
-    return exitWithError(`At least 2 entrypoints should be provided. \n\n`);
+  if (argv.apis.length < 2) {
+    return exitWithError(`At least 2 apis should be provided. \n\n`);
   }
 
   const {
@@ -77,10 +77,10 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
   }
 
   const config: Config = await loadConfig();
-  const entrypoints = await getFallbackEntryPointsOrExit(argv.entrypoints, config);
+  const apis = await getFallbackApisOrExit(argv.apis, config);
   const externalRefResolver = new BaseResolver(config.resolve);
   const documents = await Promise.all(
-    entrypoints.map(
+    apis.map(
       ({ path }) => externalRefResolver.resolveDocument(null, path, true) as Promise<Document>
     )
   );
@@ -127,7 +127,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
 
   if (argv.lint) {
     for (const document of documents) {
-      await validateEntrypoint(document, config.styleguide, externalRefResolver, packageVersion);
+      await validateApi(document, config.styleguide, externalRefResolver, packageVersion);
     }
   }
 
@@ -144,22 +144,20 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
   for (const document of documents) {
     const openapi = document.parsed;
     const { tags, info } = openapi;
-    const entrypoint = path.relative(process.cwd(), document.source.absoluteRef);
-    const entrypointFilename = getEntrypointFilename(entrypoint);
+    const api = path.relative(process.cwd(), document.source.absoluteRef);
+    const apiFilename = getApiFilename(api);
     const tagsPrefix = prefixTagsWithFilename
-      ? entrypointFilename
+      ? apiFilename
       : getInfoPrefix(info, prefixTagsWithInfoProp, 'tags');
     const componentsPrefix = getInfoPrefix(info, prefixComponentsWithInfoProp, COMPONENTS);
 
     if (openapi.hasOwnProperty('x-tagGroups')) {
-      process.stderr.write(
-        yellow(`warning: x-tagGroups at ${blue(entrypoint)} will be skipped \n`)
-      );
+      process.stderr.write(yellow(`warning: x-tagGroups at ${blue(api)} will be skipped \n`));
     }
 
     const context = {
-      entrypoint,
-      entrypointFilename,
+      api,
+      apiFilename,
       tags,
       potentialConflicts,
       tagsPrefix,
@@ -191,8 +189,8 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
   printExecutionTime('join', startedAt, specFilename);
 
   function populateTags({
-    entrypoint,
-    entrypointFilename,
+    api,
+    apiFilename,
     tags,
     potentialConflicts,
     tagsPrefix,
@@ -216,13 +214,13 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
       const tagDuplicate = joinedDef.tags.find((t: Oas3Tag) => t.name === entrypointTagName);
 
       if (tagDuplicate && withoutXTagGroups) {
-        // If tag already exist and `without-x-tag-groups` option;
-        // check if description are different for potential conflicts warning;
+        // If tag already exist and `without-x-tag-groups` option,
+        // check if description are different for potential conflicts warning.
         const isTagDescriptionNotEqual =
           tag.hasOwnProperty('description') && tagDuplicate.description !== tag.description;
 
         potentialConflicts.tags.description[entrypointTagName].push(
-          ...(isTagDescriptionNotEqual ? [entrypoint] : [])
+          ...(isTagDescriptionNotEqual ? [api] : [])
         );
       } else if (!tagDuplicate) {
         // Instead add tag to joinedDef if there no duplicate;
@@ -231,42 +229,42 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
         joinedDef.tags.push(tag);
 
         if (withoutXTagGroups) {
-          potentialConflicts.tags.description[entrypointTagName] = [entrypoint];
+          potentialConflicts.tags.description[entrypointTagName] = [api];
         }
       }
 
       if (!withoutXTagGroups) {
-        createXTagGroups(entrypointFilename);
+        createXTagGroups(apiFilename);
         if (!tagDuplicate) {
-          populateXTagGroups(entrypointTagName, getIndexGroup(entrypointFilename));
+          populateXTagGroups(entrypointTagName, getIndexGroup(apiFilename));
         }
       }
 
       const doesEntrypointExist =
         !potentialConflicts.tags.all[entrypointTagName] ||
         (potentialConflicts.tags.all[entrypointTagName] &&
-          !potentialConflicts.tags.all[entrypointTagName].includes(entrypoint));
+          !potentialConflicts.tags.all[entrypointTagName].includes(api));
       potentialConflicts.tags.all[entrypointTagName] = [
         ...(potentialConflicts.tags.all[entrypointTagName] || []),
-        ...(!withoutXTagGroups && doesEntrypointExist ? [entrypoint] : []),
+        ...(!withoutXTagGroups && doesEntrypointExist ? [api] : []),
       ];
     }
   }
 
-  function getIndexGroup(entrypointFilename: string): number {
-    return joinedDef[xTagGroups].findIndex((item: any) => item.name === entrypointFilename);
+  function getIndexGroup(apiFilename: string): number {
+    return joinedDef[xTagGroups].findIndex((item: any) => item.name === apiFilename);
   }
 
-  function createXTagGroups(entrypointFilename: string) {
+  function createXTagGroups(apiFilename: string) {
     if (!joinedDef.hasOwnProperty(xTagGroups)) {
       joinedDef[xTagGroups] = [];
     }
 
-    if (!joinedDef[xTagGroups].some((g: any) => g.name === entrypointFilename)) {
-      joinedDef[xTagGroups].push({ name: entrypointFilename, tags: [] });
+    if (!joinedDef[xTagGroups].some((g: any) => g.name === apiFilename)) {
+      joinedDef[xTagGroups].push({ name: apiFilename, tags: [] });
     }
 
-    const indexGroup = getIndexGroup(entrypointFilename);
+    const indexGroup = getIndexGroup(apiFilename);
 
     if (!joinedDef[xTagGroups][indexGroup].hasOwnProperty(Tags)) {
       joinedDef[xTagGroups][indexGroup][Tags] = [];
@@ -297,11 +295,11 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
 
   function collectInfoDescriptions(
     openapi: Oas3Definition,
-    { entrypointFilename, componentsPrefix }: JoinDocumentContext
+    { apiFilename, componentsPrefix }: JoinDocumentContext
   ) {
     const { info } = openapi;
     if (info?.description) {
-      const groupIndex = joinedDef[xTagGroups] ? getIndexGroup(entrypointFilename) : -1;
+      const groupIndex = joinedDef[xTagGroups] ? getIndexGroup(apiFilename) : -1;
       if (
         joinedDef.hasOwnProperty(xTagGroups) &&
         groupIndex !== -1 &&
@@ -316,12 +314,12 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
     }
   }
 
-  function collectExternalDocs(openapi: Oas3Definition, { entrypoint }: JoinDocumentContext) {
+  function collectExternalDocs(openapi: Oas3Definition, { api }: JoinDocumentContext) {
     const { externalDocs } = openapi;
     if (externalDocs) {
       if (joinedDef.hasOwnProperty('externalDocs')) {
         process.stderr.write(
-          yellow(`warning: skip externalDocs from ${blue(path.basename(entrypoint))} \n`)
+          yellow(`warning: skip externalDocs from ${blue(path.basename(api))} \n`)
         );
         return;
       }
@@ -331,13 +329,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
 
   function collectPaths(
     openapi: Oas3Definition,
-    {
-      entrypointFilename,
-      entrypoint,
-      potentialConflicts,
-      tagsPrefix,
-      componentsPrefix,
-    }: JoinDocumentContext
+    { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }: JoinDocumentContext
   ) {
     const { paths } = openapi;
     if (paths) {
@@ -357,7 +349,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
           joinedDef.paths[path][operation] = pathOperation;
           potentialConflicts.paths[path][operation] = [
             ...(potentialConflicts.paths[path][operation] || []),
-            entrypoint,
+            api,
           ];
           const { operationId } = pathOperation;
           if (operationId) {
@@ -366,7 +358,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
             }
             potentialConflicts.paths.operationIds[operationId] = [
               ...(potentialConflicts.paths.operationIds[operationId] || []),
-              entrypoint,
+              api,
             ];
           }
           let { tags, security } = joinedDef.paths[path][operation];
@@ -375,8 +367,8 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
               addPrefix(tag, tagsPrefix)
             );
             populateTags({
-              entrypoint,
-              entrypointFilename,
+              api,
+              apiFilename,
               tags: formatTags(tags),
               potentialConflicts,
               tagsPrefix,
@@ -384,14 +376,14 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
             });
           } else {
             joinedDef.paths[path][operation]['tags'] = [
-              addPrefix('other', tagsPrefix || entrypointFilename),
+              addPrefix('other', tagsPrefix || apiFilename),
             ];
             populateTags({
-              entrypoint,
-              entrypointFilename,
+              api,
+              apiFilename,
               tags: formatTags(['other']),
               potentialConflicts,
-              tagsPrefix: tagsPrefix || entrypointFilename,
+              tagsPrefix: tagsPrefix || apiFilename,
               componentsPrefix,
             });
           }
@@ -413,7 +405,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
 
   function collectComponents(
     openapi: Oas3Definition,
-    { entrypoint, potentialConflicts, componentsPrefix }: JoinDocumentContext
+    { api, potentialConflicts, componentsPrefix }: JoinDocumentContext
   ) {
     const { components } = openapi;
     if (components) {
@@ -431,7 +423,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
           const componentPrefix = addPrefix(item, componentsPrefix!);
           potentialConflicts.components[component][componentPrefix] = [
             ...(potentialConflicts.components[component][item] || []),
-            { [entrypoint]: componentObj[item] },
+            { [api]: componentObj[item] },
           ];
           joinedDef.components[component][componentPrefix] = componentObj[item];
         }
@@ -441,13 +433,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
 
   function collectXWebhooks(
     openapi: Oas3Definition,
-    {
-      entrypointFilename,
-      entrypoint,
-      potentialConflicts,
-      tagsPrefix,
-      componentsPrefix,
-    }: JoinDocumentContext
+    { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }: JoinDocumentContext
   ) {
     const xWebhooks = 'x-webhooks';
     // @ts-ignore
@@ -465,7 +451,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
         for (const operation of Object.keys(openapiXWebhooks[webhook])) {
           potentialConflicts.xWebhooks[webhook][operation] = [
             ...(potentialConflicts.xWebhooks[webhook][operation] || []),
-            entrypoint,
+            api,
           ];
         }
         for (const operationKey of Object.keys(joinedDef[xWebhooks][webhook])) {
@@ -475,8 +461,8 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
               addPrefix(tag, tagsPrefix)
             );
             populateTags({
-              entrypoint,
-              entrypointFilename,
+              api,
+              apiFilename,
               tags: formatTags(tags),
               potentialConflicts,
               tagsPrefix,
@@ -492,8 +478,8 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
     documents: any,
     prefixComponentsWithInfoProp: string | undefined
   ) {
-    const firstEntrypoint = documents[0];
-    const openapi = firstEntrypoint.parsed;
+    const firstApi = documents[0];
+    const openapi = firstApi.parsed;
     const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, COMPONENTS);
     if (!openapi.openapi) exitWithError('Version of specification is not found in. \n');
     if (!openapi.info) exitWithError('Info section is not found in specification. \n');
@@ -584,7 +570,7 @@ function filterConflicts(entities: object) {
   return Object.entries(entities).filter(([_, files]) => files.length > 1);
 }
 
-function getEntrypointFilename(filePath: string) {
+function getApiFilename(filePath: string) {
   return path.basename(filePath, path.extname(filePath));
 }
 
@@ -632,7 +618,7 @@ function getInfoPrefix(info: any, prefixArg: string | undefined, type: string) {
   return info[prefixArg];
 }
 
-async function validateEntrypoint(
+async function validateApi(
   document: Document,
   config: StyleguideConfig,
   externalRefResolver: BaseResolver,
diff --git a/packages/cli/src/commands/lint.ts b/packages/cli/src/commands/lint.ts
index 3c7cd710..fa9cd0ec 100644
--- a/packages/cli/src/commands/lint.ts
+++ b/packages/cli/src/commands/lint.ts
@@ -6,7 +6,6 @@ import {
   lintConfig,
   findConfig,
   getMergedConfig,
-  OutputFormat,
   makeDocumentFromString,
   loadConfig,
   stringifyYaml,
@@ -17,7 +16,7 @@ import {
 } from '@redocly/openapi-core';
 import {
   getExecutionTime,
-  getFallbackEntryPointsOrExit,
+  getFallbackApisOrExit,
   handleError,
   pluralize,
   printLintTotals,
@@ -25,21 +24,15 @@ import {
   printUnusedWarnings,
   exitWithError,
 } from '../utils';
-import { Totals } from '../types';
+import type { CommonOptions, Skips, Totals } from '../types';
 import { blue, gray, red } from 'colorette';
 import { performance } from 'perf_hooks';
 
-export type LintOptions = {
-  entrypoints: string[];
-  'max-problems'?: number;
-  'generate-ignore-file'?: boolean;
-  'skip-rule'?: string[];
-  'skip-preprocessor'?: string[];
-  'lint-config': RuleSeverity;
-  extends?: string[];
-  config?: string;
-  format: OutputFormat;
-};
+export type LintOptions = CommonOptions &
+  Omit<Skips, 'skip-decorator'> & {
+    'generate-ignore-file'?: boolean;
+    'lint-config': RuleSeverity;
+  };
 
 export async function handleLint(argv: LintOptions, version: string) {
   if (argv.config && !doesYamlFileExist(argv.config)) {
@@ -52,7 +45,7 @@ export async function handleLint(argv: LintOptions, version: string) {
     lintConfigCallback(argv, version)
   );
 
-  const entrypoints = await getFallbackEntryPointsOrExit(argv.entrypoints, config);
+  const apis = await getFallbackApisOrExit(argv.apis, config);
 
   if (argv['generate-ignore-file']) {
     config.styleguide.ignore = {}; // clear ignore
@@ -61,7 +54,7 @@ export async function handleLint(argv: LintOptions, version: string) {
   let totalIgnored = 0;
 
   // TODO: use shared externalRef resolver, blocked by preprocessors now as they can mutate documents
-  for (const { path, alias } of entrypoints) {
+  for (const { path, alias } of apis) {
     try {
       const startedAt = performance.now();
       const resolvedConfig = getMergedConfig(config, alias);
@@ -117,7 +110,7 @@ export async function handleLint(argv: LintOptions, version: string) {
       `Generated ignore file with ${totalIgnored} ${pluralize('problem', totalIgnored)}.\n\n`
     );
   } else {
-    printLintTotals(totals, entrypoints.length);
+    printLintTotals(totals, apis.length);
   }
 
   printUnusedWarnings(config.styleguide);
diff --git a/packages/cli/src/commands/preview-docs/index.ts b/packages/cli/src/commands/preview-docs/index.ts
index 2820a379..41d93310 100644
--- a/packages/cli/src/commands/preview-docs/index.ts
+++ b/packages/cli/src/commands/preview-docs/index.ts
@@ -9,29 +9,26 @@ import {
   getTotals,
   getMergedConfig,
 } from '@redocly/openapi-core';
-import { getFallbackEntryPointsOrExit } from '../../utils';
+import { getFallbackApisOrExit } from '../../utils';
 import startPreviewServer from './preview-server/preview-server';
-
-export async function previewDocs(argv: {
-  port: number;
-  host: string;
-  'use-community-edition'?: boolean;
-  config?: string;
-  entrypoint?: string;
-  'skip-rule'?: string[];
-  'skip-decorator'?: string[];
-  'skip-preprocessor'?: string[];
-  force?: boolean;
-}) {
+import type { Skips } from 'cli/src/types';
+
+export async function previewDocs(
+  argv: {
+    port: number;
+    host: string;
+    'use-community-edition'?: boolean;
+    config?: string;
+    api?: string;
+    force?: boolean;
+  } & Omit<Skips, 'skip-rule'>
+) {
   let isAuthorizedWithRedocly: boolean = false;
   let redocOptions: any = {};
   let config = await reloadConfig();
 
-  const entrypoints = await getFallbackEntryPointsOrExit(
-    argv.entrypoint ? [argv.entrypoint] : [],
-    config
-  );
-  const entrypoint = entrypoints[0];
+  const apis = await getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
+  const api = apis[0];
 
   let cachedBundle: any;
   const deps = new Set<string>();
@@ -48,7 +45,7 @@ export async function previewDocs(argv: {
         problems,
         fileDependencies,
       } = await bundle({
-        ref: entrypoint.path,
+        ref: api.path,
         config,
       });
       const removed = [...deps].filter((x) => !fileDependencies.has(x));
@@ -62,12 +59,12 @@ export async function previewDocs(argv: {
       if (fileTotals.errors === 0) {
         process.stdout.write(
           fileTotals.errors === 0
-            ? `Created a bundle for ${entrypoint.alias || entrypoint.path} ${
+            ? `Created a bundle for ${api.alias || api.path} ${
                 fileTotals.warnings > 0 ? 'with warnings' : 'successfully'
               }\n`
             : colorette.yellow(
                 `Created a bundle for ${
-                  entrypoint.alias || entrypoint.path
+                  api.alias || api.path
                 } with errors. Docs may be broken or not accurate\n`
               )
         );
@@ -75,7 +72,7 @@ export async function previewDocs(argv: {
 
       return openapiBundle.parsed;
     } catch (e) {
-      handleError(e, entrypoint.path);
+      handleError(e, api.path);
     }
   }
 
@@ -98,7 +95,7 @@ export async function previewDocs(argv: {
     useRedocPro: isAuthorized && !redocOptions.useCommunityEdition,
   });
 
-  const watchPaths = [entrypoint.path, config.configFile!].filter((e) => !!e);
+  const watchPaths = [api.path, config.configFile!].filter((e) => !!e);
   const watcher = chockidar.watch(watchPaths, {
     disableGlobbing: true,
     ignoreInitial: true,
@@ -127,9 +124,7 @@ export async function previewDocs(argv: {
 
   watcher.on('ready', () => {
     process.stdout.write(
-      `\n  👀  Watching ${colorette.blue(
-        entrypoint.path
-      )} and all related resources for changes\n\n`
+      `\n  👀  Watching ${colorette.blue(api.path)} and all related resources for changes\n\n`
     );
   });
 
@@ -137,10 +132,9 @@ export async function previewDocs(argv: {
     let config = await loadConfig(argv.config);
     const redoclyClient = new RedoclyClient();
     isAuthorizedWithRedocly = await redoclyClient.isAuthorizedWithRedocly();
-    const resolvedConfig = getMergedConfig(config, argv.entrypoint);
+    const resolvedConfig = getMergedConfig(config, argv.api);
     const { styleguide } = resolvedConfig;
 
-    styleguide.skipRules(argv['skip-rule']);
     styleguide.skipPreprocessors(argv['skip-preprocessor']);
     styleguide.skipDecorators(argv['skip-decorator']);
 
@@ -178,13 +172,9 @@ export function debounce(func: Function, wait: number, immediate?: boolean) {
 
 function handleError(e: Error, ref: string) {
   if (e instanceof ResolveError) {
-    process.stderr.write(
-      `Failed to resolve entrypoint definition at ${ref}:\n\n  - ${e.message}.\n\n`
-    );
+    process.stderr.write(`Failed to resolve api definition at ${ref}:\n\n  - ${e.message}.\n\n`);
   } else if (e instanceof YamlParseError) {
-    process.stderr.write(
-      `Failed to parse entrypoint definition at ${ref}:\n\n  - ${e.message}.\n\n`
-    );
+    process.stderr.write(`Failed to parse api definition at ${ref}:\n\n  - ${e.message}.\n\n`);
   } else {
     process.stderr.write(`Something went wrong when processing ${ref}:\n\n  - ${e.message}.\n\n`);
   }
diff --git a/packages/cli/src/commands/push.ts b/packages/cli/src/commands/push.ts
index 7e7468d4..d2e0eb5b 100644
--- a/packages/cli/src/commands/push.ts
+++ b/packages/cli/src/commands/push.ts
@@ -19,7 +19,7 @@ import {
 import {
   exitWithError,
   printExecutionTime,
-  getFallbackEntryPointsOrExit,
+  getFallbackApisOrExit,
   pluralize,
   dumpBundle,
 } from '../utils';
@@ -28,7 +28,7 @@ import { promptClientToken } from './login';
 const DEFAULT_VERSION = 'latest';
 
 type PushArgs = {
-  entrypoint?: string;
+  api?: string;
   destination?: string;
   branchName?: string;
   upsert?: boolean;
@@ -75,12 +75,11 @@ export async function handlePush(argv: PushArgs): Promise<void> {
       )} or specify the 'organization' field in the config file.`
     );
   }
-  const entrypoint =
-    argv.entrypoint || (name && version && getApiEntrypoint({ name, version, config }));
+  const api = argv.api || (name && version && getApiRoot({ name, version, config }));
 
-  if (name && version && !entrypoint) {
+  if (name && version && !api) {
     exitWithError(
-      `No entrypoint found that matches ${blue(
+      `No api found that matches ${blue(
         `${name}@${version}`
       )}. Please make sure you have provided the correct data in the config file.`
     );
@@ -98,9 +97,9 @@ export async function handlePush(argv: PushArgs): Promise<void> {
     );
   }
 
-  const apis = entrypoint ? { [`${name}@${version}`]: { root: entrypoint } } : config.apis;
+  const apis = api ? { [`${name}@${version}`]: { root: api } } : config.apis;
 
-  for (const [apiNameAndVersion, { root: entrypoint }] of Object.entries(apis)) {
+  for (const [apiNameAndVersion, { root: api }] of Object.entries(apis)) {
     const resolvedConfig = getMergedConfig(config, apiNameAndVersion);
     resolvedConfig.styleguide.skipDecorators(argv['skip-decorator']);
 
@@ -108,7 +107,7 @@ export async function handlePush(argv: PushArgs): Promise<void> {
     try {
       let rootFilePath = '';
       const filePaths: string[] = [];
-      const filesToUpload = await collectFilesToUpload(entrypoint, resolvedConfig);
+      const filesToUpload = await collectFilesToUpload(api, resolvedConfig);
       const filesHash = hashFiles(filesToUpload.files);
 
       process.stdout.write(
@@ -186,10 +185,10 @@ export async function handlePush(argv: PushArgs): Promise<void> {
     }
 
     process.stdout.write(
-      `Definition: ${blue(entrypoint!)} is successfully pushed to Redocly API Registry \n`
+      `Definition: ${blue(api!)} is successfully pushed to Redocly API Registry \n`
     );
   }
-  printExecutionTime('push', startedAt, entrypoint || `apis in organization ${organizationId}`);
+  printExecutionTime('push', startedAt, api || `apis in organization ${organizationId}`);
 }
 
 function getFilesList(dir: string, files?: any): string[] {
@@ -206,15 +205,15 @@ function getFilesList(dir: string, files?: any): string[] {
   return files;
 }
 
-async function collectFilesToUpload(entrypoint: string, config: Config) {
+async function collectFilesToUpload(api: string, config: Config) {
   let files: { filePath: string; keyOnS3: string; contents?: Buffer }[] = [];
-  const [{ path: entrypointPath }] = await getFallbackEntryPointsOrExit([entrypoint], config);
+  const [{ path: apiPath }] = await getFallbackApisOrExit([api], config);
 
   process.stdout.write('Bundling definition\n');
 
   const { bundle: openapiBundle, problems } = await bundle({
     config,
-    ref: entrypointPath,
+    ref: apiPath,
     skipRedoclyRegistryRefs: true,
   });
 
@@ -222,15 +221,15 @@ async function collectFilesToUpload(entrypoint: string, config: Config) {
 
   if (fileTotals.errors === 0) {
     process.stdout.write(
-      `Created a bundle for ${blue(entrypoint)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`
+      `Created a bundle for ${blue(api)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`
     );
   } else {
-    exitWithError(`Failed to create a bundle for ${blue(entrypoint)}\n`);
+    exitWithError(`Failed to create a bundle for ${blue(api)}\n`);
   }
 
-  const fileExt = path.extname(entrypointPath).split('.').pop();
+  const fileExt = path.extname(apiPath).split('.').pop();
   files.push(
-    getFileEntry(entrypointPath, dumpBundle(openapiBundle.parsed, fileExt as BundleOutputFormat))
+    getFileEntry(apiPath, dumpBundle(openapiBundle.parsed, fileExt as BundleOutputFormat))
   );
 
   if (fs.existsSync('package.json')) {
@@ -257,7 +256,7 @@ async function collectFilesToUpload(entrypoint: string, config: Config) {
   }
   return {
     files,
-    root: path.resolve(entrypointPath),
+    root: path.resolve(apiPath),
   };
 
   function filterPluginFilesByExt(files: string[]) {
@@ -309,8 +308,8 @@ export function getDestinationProps(
     : [organization];
 }
 
-type BarePushArgs = Omit<PushArgs, 'entrypoint' | 'destination' | 'branchName'> & {
-  maybeEntrypointOrAliasOrDestination?: string;
+type BarePushArgs = Omit<PushArgs, 'api' | 'destination' | 'branchName'> & {
+  maybeApiOrDestination?: string;
   maybeDestination?: string;
   maybeBranchName?: string;
   branch?: string;
@@ -318,13 +317,7 @@ type BarePushArgs = Omit<PushArgs, 'entrypoint' | 'destination' | 'branchName'>
 
 export const transformPush =
   (callback: typeof handlePush) =>
-  ({
-    maybeEntrypointOrAliasOrDestination,
-    maybeDestination,
-    maybeBranchName,
-    branch,
-    ...rest
-  }: BarePushArgs) => {
+  ({ maybeApiOrDestination, maybeDestination, maybeBranchName, branch, ...rest }: BarePushArgs) => {
     if (!!maybeBranchName) {
       process.stderr.write(
         yellow(
@@ -332,17 +325,17 @@ export const transformPush =
         )
       );
     }
-    const entrypoint = maybeDestination ? maybeEntrypointOrAliasOrDestination : undefined;
-    const destination = maybeDestination || maybeEntrypointOrAliasOrDestination;
+    const api = maybeDestination ? maybeApiOrDestination : undefined;
+    const destination = maybeDestination || maybeApiOrDestination;
     return callback({
       ...rest,
       destination,
-      entrypoint,
+      api,
       branchName: branch ?? maybeBranchName,
     });
   };
 
-export function getApiEntrypoint({
+export function getApiRoot({
   name,
   version,
   config: { apis },
diff --git a/packages/cli/src/commands/split/index.ts b/packages/cli/src/commands/split/index.ts
index 65c63051..8ba858c1 100644
--- a/packages/cli/src/commands/split/index.ts
+++ b/packages/cli/src/commands/split/index.ts
@@ -33,17 +33,17 @@ import {
   Referenced,
 } from './types';
 
-export async function handleSplit(argv: { entrypoint: string; outDir: string; separator: string }) {
+export async function handleSplit(argv: { api: string; outDir: string; separator: string }) {
   const startedAt = performance.now();
-  const { entrypoint, outDir, separator } = argv;
-  validateDefinitionFileName(entrypoint!);
-  const openapi = readYaml(entrypoint!) as Oas3Definition | Oas3_1Definition;
+  const { api, outDir, separator } = argv;
+  validateDefinitionFileName(api!);
+  const openapi = readYaml(api!) as Oas3Definition | Oas3_1Definition;
   splitDefinition(openapi, outDir, separator);
   process.stderr.write(
-    `🪓 Document: ${blue(entrypoint!)} ${green('is successfully split')}
+    `🪓 Document: ${blue(api!)} ${green('is successfully split')}
     and all related files are saved to the directory: ${blue(outDir)} \n`
   );
-  printExecutionTime('split', startedAt, entrypoint!);
+  printExecutionTime('split', startedAt, api!);
 }
 
 function splitDefinition(
diff --git a/packages/cli/src/commands/stats.ts b/packages/cli/src/commands/stats.ts
index cd1d4d19..08d34ab3 100755
--- a/packages/cli/src/commands/stats.ts
+++ b/packages/cli/src/commands/stats.ts
@@ -21,7 +21,7 @@ import {
   bundle,
 } from '@redocly/openapi-core';
 
-import { getFallbackEntryPointsOrExit } from '../utils';
+import { getFallbackApisOrExit } from '../utils';
 import { printExecutionTime } from '../utils';
 
 const statsAccumulator: StatsAccumulator = {
@@ -53,8 +53,8 @@ function printStatsJson(statsAccumulator: StatsAccumulator) {
   process.stdout.write(JSON.stringify(json, null, 2));
 }
 
-function printStats(statsAccumulator: StatsAccumulator, entrypoint: string, format: string) {
-  process.stderr.write(`Document: ${colors.magenta(entrypoint)} stats:\n\n`);
+function printStats(statsAccumulator: StatsAccumulator, api: string, format: string) {
+  process.stderr.write(`Document: ${colors.magenta(api)} stats:\n\n`);
   switch (format) {
     case 'stylish':
       printStatsStylish(statsAccumulator);
@@ -65,12 +65,9 @@ function printStats(statsAccumulator: StatsAccumulator, entrypoint: string, form
   }
 }
 
-export async function handleStats(argv: { config?: string; entrypoint?: string; format: string }) {
+export async function handleStats(argv: { config?: string; api?: string; format: string }) {
   const config: Config = await loadConfig(argv.config);
-  const [{ path }] = await getFallbackEntryPointsOrExit(
-    argv.entrypoint ? [argv.entrypoint] : [],
-    config
-  );
+  const [{ path }] = await getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
   const externalRefResolver = new BaseResolver(config.resolve);
   const { bundle: document } = await bundle({ config, ref: path });
   const lintConfig: StyleguideConfig = config.styleguide;
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 3b0666bd..ae293034 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -18,10 +18,10 @@ yargs
   .version('version', 'Show version number.', version)
   .help('help', 'Show help.')
   .command(
-    'stats [entrypoint]',
+    'stats [api]',
     'Gathering statistics for a document.',
     (yargs) =>
-      yargs.positional('entrypoint', { type: 'string' }).option({
+      yargs.positional('api', { type: 'string' }).option({
         config: { description: 'Specify path to the config file.', type: 'string' },
         format: {
           description: 'Use a specific output format.',
@@ -32,11 +32,11 @@ yargs
     handleStats
   )
   .command(
-    'split [entrypoint]',
+    'split [api]',
     'Split definition into a multi-file structure.',
     (yargs) =>
       yargs
-        .positional('entrypoint', {
+        .positional('api', {
           description: 'API definition file that you want to split',
           type: 'string',
         })
@@ -53,15 +53,15 @@ yargs
             default: '_',
           },
         })
-        .demandOption('entrypoint'),
+        .demandOption('api'),
     handleSplit
   )
   .command(
-    'join [entrypoints...]',
+    'join [apis...]',
     'Join definitions [experimental].',
     (yargs) =>
       yargs
-        .positional('entrypoints', {
+        .positional('apis', {
           array: true,
           type: 'string',
           demandOption: true,
@@ -93,11 +93,11 @@ yargs
     }
   )
   .command(
-    'push [maybeEntrypointOrAliasOrDestination] [maybeDestination] [maybeBranchName]',
+    'push [maybeApiOrDestination] [maybeDestination] [maybeBranchName]',
     'Push an API definition to the Redocly API registry.',
     (yargs) =>
       yargs
-        .positional('maybeEntrypointOrAliasOrDestination', { type: 'string' })
+        .positional('maybeApiOrDestination', { type: 'string' })
         .positional('maybeDestination', { type: 'string' })
         .positional('maybeBranchName', { type: 'string' })
         .option({
@@ -130,10 +130,10 @@ yargs
     transformPush(handlePush)
   )
   .command(
-    'lint [entrypoints...]',
+    'lint [apis...]',
     'Lint definition.',
     (yargs) =>
-      yargs.positional('entrypoints', { array: true, type: 'string', demandOption: true }).option({
+      yargs.positional('apis', { array: true, type: 'string', demandOption: true }).option({
         format: {
           description: 'Use a specific output format.',
           choices: [
@@ -187,10 +187,10 @@ yargs
     }
   )
   .command(
-    'bundle [entrypoints...]',
+    'bundle [apis...]',
     'Bundle definition.',
     (yargs) =>
-      yargs.positional('entrypoints', { array: true, type: 'string', demandOption: true }).options({
+      yargs.positional('apis', { array: true, type: 'string', demandOption: true }).options({
         output: { type: 'string', alias: 'o' },
         format: {
           description: 'Use a specific output format.',
@@ -290,10 +290,10 @@ yargs
     }
   )
   .command(
-    'preview-docs [entrypoint]',
+    'preview-docs [api]',
     'Preview API reference docs for the specified definition.',
     (yargs) =>
-      yargs.positional('entrypoint', { type: 'string' }).options({
+      yargs.positional('api', { type: 'string' }).options({
         port: {
           alias: 'p',
           type: 'number',
diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts
index 68a610a2..12a2db1b 100644
--- a/packages/cli/src/types.ts
+++ b/packages/cli/src/types.ts
@@ -1,4 +1,5 @@
-import { BundleOutputFormat, Region } from '@redocly/openapi-core';
+import type { BundleOutputFormat, OutputFormat, Region } from '@redocly/openapi-core';
+
 export type Totals = {
   errors: number;
   warnings: number;
@@ -11,3 +12,15 @@ export type Entrypoint = {
 export const outputExtensions = ['json', 'yaml', 'yml'] as ReadonlyArray<BundleOutputFormat>;
 export type OutputExtensions = 'json' | 'yaml' | 'yml' | undefined;
 export const regionChoices = ['us', 'eu'] as ReadonlyArray<Region>;
+export type CommonOptions = {
+  apis: string[];
+  'max-problems'?: number;
+  extends?: string[];
+  config?: string;
+  format: OutputFormat;
+};
+export type Skips = {
+  'skip-rule'?: string[];
+  'skip-decorator'?: string[];
+  'skip-preprocessor'?: string[];
+};
diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts
index 85702000..2698c9e8 100644
--- a/packages/cli/src/utils.ts
+++ b/packages/cli/src/utils.ts
@@ -17,21 +17,21 @@ import {
 } from '@redocly/openapi-core';
 import { Totals, outputExtensions, Entrypoint } from './types';
 
-export async function getFallbackEntryPointsOrExit(
-  argsEntrypoints: string[] | undefined,
+export async function getFallbackApisOrExit(
+  argsApis: string[] | undefined,
   config: Config
 ): Promise<Entrypoint[]> {
   const { apis } = config;
   const shouldFallbackToAllDefinitions =
-    !isNotEmptyArray(argsEntrypoints) && apis && Object.keys(apis).length > 0;
+    !isNotEmptyArray(argsApis) && apis && Object.keys(apis).length > 0;
   const res = shouldFallbackToAllDefinitions
     ? Object.entries(apis).map(([alias, { root }]) => ({
         path: resolve(getConfigDirectory(config), root),
         alias,
       }))
-    : await expandGlobsInEntrypoints(argsEntrypoints!, config);
+    : await expandGlobsInEntrypoints(argsApis!, config);
   if (!isNotEmptyArray(res)) {
-    process.stderr.write('error: missing required argument `entrypoints`.\n');
+    process.stderr.write('error: missing required argument `apis`.\n');
     process.exit(1);
   }
   return res;
@@ -69,9 +69,9 @@ export function getExecutionTime(startedAt: number) {
     : `${Math.ceil(performance.now() - startedAt)}ms`;
 }
 
-export function printExecutionTime(commandName: string, startedAt: number, entrypoint: string) {
+export function printExecutionTime(commandName: string, startedAt: number, api: string) {
   const elapsed = getExecutionTime(startedAt);
-  process.stderr.write(gray(`\n${entrypoint}: ${commandName} processed in ${elapsed}\n\n`));
+  process.stderr.write(gray(`\n${api}: ${commandName} processed in ${elapsed}\n\n`));
 }
 
 export function pathToFilename(path: string, pathSeparator: string) {
@@ -172,13 +172,9 @@ export function pluralize(label: string, num: number) {
 
 export function handleError(e: Error, ref: string) {
   if (e instanceof ResolveError) {
-    process.stderr.write(
-      `Failed to resolve entrypoint definition at ${ref}:\n\n  - ${e.message}.\n\n`
-    );
+    process.stderr.write(`Failed to resolve api definition at ${ref}:\n\n  - ${e.message}.\n\n`);
   } else if (e instanceof YamlParseError) {
-    process.stderr.write(
-      `Failed to parse entrypoint definition at ${ref}:\n\n  - ${e.message}.\n\n`
-    );
+    process.stderr.write(`Failed to parse api definition at ${ref}:\n\n  - ${e.message}.\n\n`);
     // TODO: codeframe
   } else {
     // @ts-ignore
diff --git a/packages/core/README.md b/packages/core/README.md
index 93d09cbf..fc7f3404 100644
--- a/packages/core/README.md
+++ b/packages/core/README.md
@@ -9,9 +9,9 @@ See https://github.com/Redocly/redocly-cli
 ```js
 import { formatProblems, lint, loadConfig } from '@redocly/openapi-core';
 
-const pathToEntryPoint = 'openapi.yaml';
+const pathToApi = 'openapi.yaml';
 const config = loadConfig('optional/path/to/.redocly.yaml');
-const lintResults = await lint({ ref: pathToEntryPoint, config });
+const lintResults = await lint({ ref: pathToApi, config });
 ```
 
 ### Bundle
@@ -19,7 +19,7 @@ const lintResults = await lint({ ref: pathToEntryPoint, config });
 ```js
 import { formatProblems, bundle, loadConfig } from '@redocly/openapi-core';
 
-const pathToEntryPoint = 'openapi.yaml';
+const pathToApi = 'openapi.yaml';
 const config = loadConfig('optional/path/to/.redocly.yaml');
-const { bundle, problems } = await bundle({ ref: pathToEntryPoint, config });
+const { bundle, problems } = await bundle({ ref: pathToApi, config });
 ```
diff --git a/packages/core/src/config/utils.ts b/packages/core/src/config/utils.ts
index 0fc27652..ac177feb 100644
--- a/packages/core/src/config/utils.ts
+++ b/packages/core/src/config/utils.ts
@@ -118,7 +118,7 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) {
   return result;
 }
 
-export function getMergedConfig(config: Config, entrypointAlias?: string): Config {
+export function getMergedConfig(config: Config, apiName?: string): Config {
   const extendPaths = [
     ...Object.values(config.apis).map((api) => api?.styleguide?.extendPaths),
     config.rawConfig?.styleguide?.extendPaths,
@@ -133,24 +133,24 @@ export function getMergedConfig(config: Config, entrypointAlias?: string): Confi
     .flat()
     .filter(Boolean) as string[];
 
-  return entrypointAlias
+  return apiName
     ? new Config(
         {
           ...config.rawConfig,
           styleguide: {
-            ...(config.apis[entrypointAlias]
-              ? config.apis[entrypointAlias].styleguide
+            ...(config.apis[apiName]
+              ? config.apis[apiName].styleguide
               : config.rawConfig.styleguide),
             extendPaths,
             pluginPaths,
           },
           'features.openapi': {
             ...config['features.openapi'],
-            ...config.apis[entrypointAlias]?.['features.openapi'],
+            ...config.apis[apiName]?.['features.openapi'],
           },
           'features.mockServer': {
             ...config['features.mockServer'],
-            ...config.apis[entrypointAlias]?.['features.mockServer'],
+            ...config.apis[apiName]?.['features.mockServer'],
           },
           // TODO: merge everything else here
         },
diff --git a/packages/core/src/rules/utils.ts b/packages/core/src/rules/utils.ts
index 08ccdefb..a621d429 100644
--- a/packages/core/src/rules/utils.ts
+++ b/packages/core/src/rules/utils.ts
@@ -9,6 +9,8 @@ export function oasTypeOf(value: unknown) {
     return 'array';
   } else if (value === null) {
     return 'null';
+  } else if (Number.isInteger(value)) {
+    return 'integer';
   } else {
     return typeof value;
   }
@@ -23,7 +25,7 @@ export function oasTypeOf(value: unknown) {
  */
 export function matchesJsonSchemaType(value: unknown, type: string, nullable: boolean): boolean {
   if (nullable && value === null) {
-    return value === null;
+    return true;
   }
 
   switch (type) {


Test patch:
diff --git a/__tests__/lint-config/invlid-lint-config-saverity/snapshot.js b/__tests__/lint-config/invlid-lint-config-saverity/snapshot.js
index d723cbbb..5f1109e4 100644
--- a/__tests__/lint-config/invlid-lint-config-saverity/snapshot.js
+++ b/__tests__/lint-config/invlid-lint-config-saverity/snapshot.js
@@ -2,12 +2,12 @@
 
 exports[`E2E lint-config test with option: { dirName: 'invlid-lint-config-saverity', option: 'something' } 1`] = `
 
-index.ts lint [entrypoints...]
+index.ts lint [apis...]
 
 Lint definition.
 
 Positionals:
-  entrypoints                                              [array] [default: []]
+  apis                                                     [array] [default: []]
 
 Options:
   --version               Show version number.                         [boolean]
diff --git a/__tests__/split/missing-outDir/snapshot.js b/__tests__/split/missing-outDir/snapshot.js
index 260dc99a..943676c5 100644
--- a/__tests__/split/missing-outDir/snapshot.js
+++ b/__tests__/split/missing-outDir/snapshot.js
@@ -2,12 +2,12 @@
 
 exports[`E2E split without option: outDir 1`] = `
 
-index.ts split [entrypoint]
+index.ts split [api]
 
 Split definition into a multi-file structure.
 
 Positionals:
-  entrypoint  API definition file that you want to split     [string] [required]
+  api  API definition file that you want to split            [string] [required]
 
 Options:
   --version    Show version number.                                    [boolean]
diff --git a/packages/cli/src/__tests__/commands/bundle.test.ts b/packages/cli/src/__tests__/commands/bundle.test.ts
index ab1ace3a..41b13df5 100644
--- a/packages/cli/src/__tests__/commands/bundle.test.ts
+++ b/packages/cli/src/__tests__/commands/bundle.test.ts
@@ -29,11 +29,11 @@ describe('bundle', () => {
   });
 
   it('bundles definitions w/o linting', async () => {
-    const entrypoints = ['foo.yaml', 'bar.yaml'];
+    const apis = ['foo.yaml', 'bar.yaml'];
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
       },
@@ -41,15 +41,15 @@ describe('bundle', () => {
     );
 
     expect(lint).toBeCalledTimes(0);
-    expect(bundle).toBeCalledTimes(entrypoints.length);
+    expect(bundle).toBeCalledTimes(apis.length);
   });
 
   it('exits with code 0 when bundles definitions', async () => {
-    const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
+    const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
       },
@@ -61,7 +61,7 @@ describe('bundle', () => {
   });
 
   it('bundles definitions w/ linting', async () => {
-    const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
+    const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
 
     (getTotals as jest.Mock).mockReturnValue({
       errors: 0,
@@ -71,7 +71,7 @@ describe('bundle', () => {
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
         lint: true,
@@ -79,16 +79,16 @@ describe('bundle', () => {
       '1.0.0'
     );
 
-    expect(lint).toBeCalledTimes(entrypoints.length);
-    expect(bundle).toBeCalledTimes(entrypoints.length);
+    expect(lint).toBeCalledTimes(apis.length);
+    expect(bundle).toBeCalledTimes(apis.length);
   });
 
   it('exits with code 0 when bundles definitions w/linting w/o errors', async () => {
-    const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
+    const apis = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
         lint: true,
@@ -101,7 +101,7 @@ describe('bundle', () => {
   });
 
   it('exits with code 1 when bundles definitions w/linting w/errors', async () => {
-    const entrypoints = ['foo.yaml'];
+    const apis = ['foo.yaml'];
 
     (getTotals as jest.Mock).mockReturnValue({
       errors: 1,
@@ -111,7 +111,7 @@ describe('bundle', () => {
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
         lint: true,
@@ -119,13 +119,13 @@ describe('bundle', () => {
       '1.0.0'
     );
 
-    expect(lint).toBeCalledTimes(entrypoints.length);
+    expect(lint).toBeCalledTimes(apis.length);
     exitCb?.();
     expect(processExitMock).toHaveBeenCalledWith(1);
   });
 
   it('handleError is called when bundles an invalid definition', async () => {
-    const entrypoints = ['invalid.json'];
+    const apis = ['invalid.json'];
 
     (bundle as jest.Mock).mockImplementationOnce(() => {
       throw new Error('Invalid definition');
@@ -133,7 +133,7 @@ describe('bundle', () => {
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'json',
         format: 'codeframe',
         lint: false,
@@ -146,7 +146,7 @@ describe('bundle', () => {
   });
 
   it("handleError isn't called when bundles a valid definition", async () => {
-    const entrypoints = ['foo.yaml'];
+    const apis = ['foo.yaml'];
 
     (getTotals as jest.Mock).mockReturnValue({
       errors: 0,
@@ -156,7 +156,7 @@ describe('bundle', () => {
 
     await handleBundle(
       {
-        entrypoints,
+        apis,
         ext: 'yaml',
         format: 'codeframe',
         lint: false,
diff --git a/packages/cli/src/__tests__/commands/join.test.ts b/packages/cli/src/__tests__/commands/join.test.ts
index 63aa4938..6ab9f759 100644
--- a/packages/cli/src/__tests__/commands/join.test.ts
+++ b/packages/cli/src/__tests__/commands/join.test.ts
@@ -10,14 +10,14 @@ describe('handleJoin fails', () => {
   colloreteYellowMock.mockImplementation((string: string) => string);
 
   it('should call exitWithError because only one entrypoint', async () => {
-    await handleJoin({ entrypoints: ['first.yaml'] }, 'cli-version');
-    expect(exitWithError).toHaveBeenCalledWith(`At least 2 entrypoints should be provided. \n\n`);
+    await handleJoin({ apis: ['first.yaml'] }, 'cli-version');
+    expect(exitWithError).toHaveBeenCalledWith(`At least 2 apis should be provided. \n\n`);
   });
 
   it('should call exitWithError because passed all 3 options for tags', async () => {
     await handleJoin(
       {
-        entrypoints: ['first.yaml', 'second.yaml'],
+        apis: ['first.yaml', 'second.yaml'],
         'prefix-tags-with-info-prop': 'something',
         'without-x-tag-groups': true,
         'prefix-tags-with-filename': true,
@@ -33,7 +33,7 @@ describe('handleJoin fails', () => {
   it('should call exitWithError because passed all 2 options for tags', async () => {
     await handleJoin(
       {
-        entrypoints: ['first.yaml', 'second.yaml'],
+        apis: ['first.yaml', 'second.yaml'],
         'without-x-tag-groups': true,
         'prefix-tags-with-filename': true,
       },
diff --git a/packages/cli/src/__tests__/commands/lint.test.ts b/packages/cli/src/__tests__/commands/lint.test.ts
index c741b87d..66cfa0eb 100644
--- a/packages/cli/src/__tests__/commands/lint.test.ts
+++ b/packages/cli/src/__tests__/commands/lint.test.ts
@@ -8,7 +8,7 @@ import {
   doesYamlFileExist,
 } from '@redocly/openapi-core';
 import {
-  getFallbackEntryPointsOrExit,
+  getFallbackApisOrExit,
   getExecutionTime,
   printUnusedWarnings,
   handleError,
@@ -22,7 +22,7 @@ jest.mock('../../utils');
 jest.mock('perf_hooks');
 
 const argvMock: LintOptions = {
-  entrypoints: ['openapi.yaml'],
+  apis: ['openapi.yaml'],
   'lint-config': 'off',
   format: 'codeframe',
 };
@@ -61,10 +61,10 @@ describe('handleLint', () => {
       expect(loadConfig).toHaveBeenCalledTimes(0);
     });
 
-    it('should call loadConfig and getFallbackEntryPointsOrExit', async () => {
+    it('should call loadConfig and getFallbackApisOrExit', async () => {
       await handleLint(argvMock, versionMock);
       expect(loadConfig).toHaveBeenCalledWith(undefined, undefined, undefined);
-      expect(getFallbackEntryPointsOrExit).toHaveBeenCalled();
+      expect(getFallbackApisOrExit).toHaveBeenCalled();
     });
 
     it('should call loadConfig with args if such exist', async () => {
diff --git a/packages/cli/src/__tests__/commands/push-region.test.ts b/packages/cli/src/__tests__/commands/push-region.test.ts
index e6d72987..5e7e7d1d 100644
--- a/packages/cli/src/__tests__/commands/push-region.test.ts
+++ b/packages/cli/src/__tests__/commands/push-region.test.ts
@@ -29,7 +29,7 @@ describe('push-with-region', () => {
     redoclyClient.domain = 'redoc.ly';
     await handlePush({
       upsert: true,
-      entrypoint: 'spec.json',
+      api: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
     });
@@ -41,7 +41,7 @@ describe('push-with-region', () => {
     redoclyClient.domain = 'eu.redocly.com';
     await handlePush({
       upsert: true,
-      entrypoint: 'spec.json',
+      api: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
     });
diff --git a/packages/cli/src/__tests__/commands/push.test.ts b/packages/cli/src/__tests__/commands/push.test.ts
index 5fff6387..a6c251ee 100644
--- a/packages/cli/src/__tests__/commands/push.test.ts
+++ b/packages/cli/src/__tests__/commands/push.test.ts
@@ -1,11 +1,6 @@
 import { Config, getMergedConfig } from '@redocly/openapi-core';
 import { exitWithError } from '../../utils';
-import {
-  getApiEntrypoint,
-  getDestinationProps,
-  handlePush,
-  transformPush,
-} from '../../commands/push';
+import { getApiRoot, getDestinationProps, handlePush, transformPush } from '../../commands/push';
 
 jest.mock('fs');
 jest.mock('node-fetch', () => ({
@@ -29,7 +24,7 @@ describe('push', () => {
   it('pushes definition', async () => {
     await handlePush({
       upsert: true,
-      entrypoint: 'spec.json',
+      api: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
       public: true,
@@ -56,7 +51,7 @@ describe('push', () => {
   it('fails if batchId value is an empty string', async () => {
     await handlePush({
       upsert: true,
-      entrypoint: 'spec.json',
+      api: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
       public: true,
@@ -70,7 +65,7 @@ describe('push', () => {
   it('fails if batchSize value is less than 2', async () => {
     await handlePush({
       upsert: true,
-      entrypoint: 'spec.json',
+      api: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
       public: true,
@@ -86,23 +81,23 @@ describe('transformPush', () => {
   it('should adapt the existing syntax', () => {
     const cb = jest.fn();
     transformPush(cb)({
-      maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
+      maybeApiOrDestination: 'openapi.yaml',
       maybeDestination: '@testing_org/main@v1',
     });
     expect(cb).toBeCalledWith({
-      entrypoint: 'openapi.yaml',
+      api: 'openapi.yaml',
       destination: '@testing_org/main@v1',
     });
   });
   it('should adapt the existing syntax (including branchName)', () => {
     const cb = jest.fn();
     transformPush(cb)({
-      maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
+      maybeApiOrDestination: 'openapi.yaml',
       maybeDestination: '@testing_org/main@v1',
       maybeBranchName: 'other',
     });
     expect(cb).toBeCalledWith({
-      entrypoint: 'openapi.yaml',
+      api: 'openapi.yaml',
       destination: '@testing_org/main@v1',
       branchName: 'other',
     });
@@ -110,13 +105,13 @@ describe('transformPush', () => {
   it('should use --branch option firstly', () => {
     const cb = jest.fn();
     transformPush(cb)({
-      maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
+      maybeApiOrDestination: 'openapi.yaml',
       maybeDestination: '@testing_org/main@v1',
       maybeBranchName: 'other',
       branch: 'priority-branch',
     });
     expect(cb).toBeCalledWith({
-      entrypoint: 'openapi.yaml',
+      api: 'openapi.yaml',
       destination: '@testing_org/main@v1',
       branchName: 'priority-branch',
     });
@@ -124,7 +119,7 @@ describe('transformPush', () => {
   it('should work for a destination only', () => {
     const cb = jest.fn();
     transformPush(cb)({
-      maybeEntrypointOrAliasOrDestination: '@testing_org/main@v1',
+      maybeApiOrDestination: '@testing_org/main@v1',
     });
     expect(cb).toBeCalledWith({
       destination: '@testing_org/main@v1',
@@ -133,12 +128,12 @@ describe('transformPush', () => {
   it('should accept aliases for the old syntax', () => {
     const cb = jest.fn();
     transformPush(cb)({
-      maybeEntrypointOrAliasOrDestination: 'alias',
+      maybeApiOrDestination: 'alias',
       maybeDestination: '@testing_org/main@v1',
     });
     expect(cb).toBeCalledWith({
       destination: '@testing_org/main@v1',
-      entrypoint: 'alias',
+      api: 'alias',
     });
   });
   it('should accept no arguments at all', () => {
@@ -171,7 +166,7 @@ describe('getDestinationProps', () => {
   });
 });
 
-describe('getApiEntrypoint', () => {
+describe('getApiRoot', () => {
   let config: Config = {
     apis: {
       'main@v1': {
@@ -183,9 +178,9 @@ describe('getApiEntrypoint', () => {
     },
   } as unknown as Config;
   it('should resolve the correct api for a valid name & version', () => {
-    expect(getApiEntrypoint({ name: 'main', version: 'v1', config })).toEqual('openapi.yaml');
+    expect(getApiRoot({ name: 'main', version: 'v1', config })).toEqual('openapi.yaml');
   });
   it('should resolve the latest version of api if there is no matching version', () => {
-    expect(getApiEntrypoint({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
+    expect(getApiRoot({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
   });
 });
diff --git a/packages/cli/src/commands/split/__tests__/index.test.ts b/packages/cli/src/commands/split/__tests__/index.test.ts
index e1204c9e..70096244 100644
--- a/packages/cli/src/commands/split/__tests__/index.test.ts
+++ b/packages/cli/src/commands/split/__tests__/index.test.ts
@@ -25,7 +25,7 @@ describe('#split', () => {
     jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
 
     await handleSplit({
-      entrypoint: filePath,
+      api: filePath,
       outDir: openapiDir,
       separator: '_',
     });
@@ -46,7 +46,7 @@ describe('#split', () => {
     jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath');
 
     await handleSplit({
-      entrypoint: filePath,
+      api: filePath,
       outDir: openapiDir,
       separator: '_',
     });
diff --git a/packages/core/src/rules/__tests__/utils.test.ts b/packages/core/src/rules/__tests__/utils.test.ts
new file mode 100644
index 00000000..17417ace
--- /dev/null
+++ b/packages/core/src/rules/__tests__/utils.test.ts
@@ -0,0 +1,122 @@
+import { fieldNonEmpty, matchesJsonSchemaType, missingRequiredField, oasTypeOf } from '../utils';
+
+describe('field-non-empty', () => {
+  it('should match expected message', () => {
+    const message = fieldNonEmpty('Car', 'color');
+    expect(message).toBe('Car object `color` must be non-empty string.');
+  });
+});
+
+describe('matches-json-schema-type', () => {
+  it('should report true on a null value with nullable type', () => {
+    const results = matchesJsonSchemaType(null, 'string', true);
+    expect(results).toBe(true);
+  });
+
+  it('should report true on a value and type integer', () => {
+    const results = matchesJsonSchemaType(123, 'integer', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report false when the value is not integer and type is integer', () => {
+    const results = matchesJsonSchemaType(3.14, 'integer', false);
+    expect(results).toBe(false);
+  });
+
+  it('should report true when the value is a number and type is number', () => {
+    const results = matchesJsonSchemaType(3.14, 'number', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report true when the value is an integer and type is number', () => {
+    const results = matchesJsonSchemaType(3, 'number', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report true when the value is true and type is boolean', () => {
+    const results = matchesJsonSchemaType(true, 'boolean', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report true when the value is false and type is boolean', () => {
+    const results = matchesJsonSchemaType(false, 'boolean', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report true when the value is a string and type is boolean', () => {
+    const results = matchesJsonSchemaType('test', 'boolean', false);
+    expect(results).toBe(false);
+  });
+
+  it('should report true on an array value with array type', () => {
+    const results = matchesJsonSchemaType(['foo', 'bar'], 'array', false);
+    expect(results).toBe(true);
+  });
+
+  it('should report false on an array value with object type', () => {
+    const results = matchesJsonSchemaType(['foo', 'bar'], 'object', false);
+    expect(results).toBe(false);
+  });
+
+  it('should report true on an object value with object type', () => {
+    const car = { type: 'Fiat', model: '500', color: 'white' };
+    const results = matchesJsonSchemaType(car, 'object', true);
+    expect(results).toBe(true);
+  });
+
+  it('should report false on an object value with array type', () => {
+    const car = { type: 'Fiat', model: '500', color: 'white' };
+    const results = matchesJsonSchemaType(car, 'array', true);
+    expect(results).toBe(false);
+  });
+});
+
+describe('missing-required-field', () => {
+  it('should match expected message for missing required field', () => {
+    const message = missingRequiredField('Car', 'color');
+    expect(message).toBe('Car object should contain `color` field.');
+  });
+});
+
+describe('oas-type-of', () => {
+  it('should report the correct oas type for a string', () => {
+    const results = oasTypeOf('word');
+    expect(results).toBe('string');
+  });
+
+  it('should report the correct oas type for an integer', () => {
+    const results = oasTypeOf(123);
+    expect(results).toBe('integer');
+  });
+
+  it('should report the correct oas type for a number', () => {
+    const results = oasTypeOf(3.14);
+    expect(results).toBe('number');
+  });
+
+  it('should report the correct oas type for a null value', () => {
+    const results = oasTypeOf(null);
+    expect(results).toBe('null');
+  });
+
+  it('should report the correct oas type for a true boolean', () => {
+    const results = oasTypeOf(true);
+    expect(results).toBe('boolean');
+  });
+
+  it('should report the correct oas type for a false boolean', () => {
+    const results = oasTypeOf(false);
+    expect(results).toBe('boolean');
+  });
+
+  it('should report the correct oas type for an array', () => {
+    const results = oasTypeOf(['foo', 'bar']);
+    expect(results).toBe('array');
+  });
+
+  it('should report the correct oas type for an object', () => {
+    const car = { type: 'Fiat', model: '500', color: 'white' };
+    const results = oasTypeOf(car);
+    expect(results).toBe('object');
+  });
+});
diff --git a/packages/core/src/rules/oas3/__tests__/spec/spec.test.ts b/packages/core/src/rules/oas3/__tests__/spec/spec.test.ts
index d624cf95..8f7fa403 100644
--- a/packages/core/src/rules/oas3/__tests__/spec/spec.test.ts
+++ b/packages/core/src/rules/oas3/__tests__/spec/spec.test.ts
@@ -110,7 +110,7 @@ describe('Oas3 Structural visitor basic', () => {
               "source": "foobar.yaml",
             },
           ],
-          "message": "Expected type \`string\` but got \`number\`.",
+          "message": "Expected type \`string\` but got \`integer\`.",
           "ruleId": "spec",
           "severity": "error",
           "suggest": Array [],