mirror of
https://github.com/LukeHagar/redocly-cli.git
synced 2025-12-06 04:21:09 +00:00
refactor: split in two packages: core and cli (#223)
This commit is contained in:
16
.github/workflows/deploy.yaml
vendored
16
.github/workflows/deploy.yaml
vendored
@@ -2,9 +2,9 @@ name: CD to NPM & AWS S3
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
tags:
|
||||
- v[0-9]*.[0-9]*.[0-9]*
|
||||
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -18,7 +18,8 @@ jobs:
|
||||
restore-keys: |
|
||||
npm-${{ hashFiles('package-lock.json') }}
|
||||
npm-
|
||||
- run: npm ci
|
||||
- run: npm i -g npm@7
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
deploy:
|
||||
needs: test
|
||||
@@ -34,8 +35,10 @@ jobs:
|
||||
npm-${{ hashFiles('package-lock.json') }}
|
||||
npm-
|
||||
|
||||
- name: Install npm@7
|
||||
run: npm i -g npm@7
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm install
|
||||
|
||||
- name: Build package
|
||||
run: npm run build
|
||||
@@ -68,8 +71,11 @@ jobs:
|
||||
npm-${{ hashFiles('package-lock.json') }}
|
||||
npm-
|
||||
|
||||
- name: Install npm@7
|
||||
run: npm i -g npm@7
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
run: npm install
|
||||
|
||||
- name: Build package
|
||||
run: npm run build
|
||||
|
||||
17
.github/workflows/unit-tests.yaml
vendored
17
.github/workflows/unit-tests.yaml
vendored
@@ -5,8 +5,16 @@ on: [push]
|
||||
jobs:
|
||||
build-and-unit:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: cache node modules
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
@@ -15,5 +23,8 @@ jobs:
|
||||
restore-keys: |
|
||||
npm-${{ hashFiles('package-lock.json') }}
|
||||
npm-
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
- run: npm i -g npm@7
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
env:
|
||||
CI: true
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,12 +2,10 @@
|
||||
.idea
|
||||
node_modules/
|
||||
nodejs/
|
||||
|
||||
coverage/
|
||||
.vscode/
|
||||
|
||||
yarn.lock
|
||||
dist/
|
||||
lib/
|
||||
|
||||
*.tar.gz
|
||||
*.tsbuildinfo
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { readdirSync, statSync, existsSync } from 'fs';
|
||||
import { spawnSync } from 'child_process';
|
||||
import { join } from 'path';
|
||||
//@ts-ignore
|
||||
import { toMatchSpecificSnapshot, addSerializer } from './specific-snapshot';
|
||||
|
||||
expect.extend({
|
||||
@@ -10,19 +11,18 @@ expect.extend({
|
||||
});
|
||||
|
||||
addSerializer({
|
||||
test: (val) => typeof val === 'string',
|
||||
print: (v) => v as string,
|
||||
test: (val: any) => typeof val === 'string',
|
||||
print: (v: any) => v as string,
|
||||
});
|
||||
|
||||
describe('E2E', () => {
|
||||
const contents = readdirSync(__dirname);
|
||||
|
||||
for (const file of contents) {
|
||||
const testPath = join(__dirname, file);
|
||||
if (statSync(testPath).isFile()) continue;
|
||||
if (!existsSync(join(testPath, '.redocly.yaml'))) continue;
|
||||
|
||||
const r = spawnSync('npx', ['ts-node', '--transpile-only', '../../src/cli.ts', 'lint'], {
|
||||
const r = spawnSync('npx', ['ts-node', '--transpile-only', '../../packages/cli/src/index.ts', 'lint'], {
|
||||
cwd: testPath,
|
||||
env: {
|
||||
...process.env,
|
||||
|
||||
@@ -6,7 +6,6 @@ let commonSnapshotState;
|
||||
|
||||
function toMatchSpecificSnapshot(received, snapshotFile, ...rest) {
|
||||
const absoluteSnapshotFile = getAbsolutePathToSnapshot(this.testPath, snapshotFile);
|
||||
|
||||
// store the common state to re-use it in "afterAll" hook.
|
||||
commonSnapshotState = this.snapshotState;
|
||||
let snapshotState = snapshotsStateMap.get(absoluteSnapshotFile);
|
||||
|
||||
13838
package-lock.json
generated
13838
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
100
package.json
100
package.json
@@ -1,28 +1,34 @@
|
||||
{
|
||||
"name": "@redocly/openapi-cli",
|
||||
"name": "@redocly/openapi",
|
||||
"version": "1.0.0-beta.18",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
"node": ">=15.0.0"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"scripts": {
|
||||
"test": "npm run typecheck && npm run unit",
|
||||
"unit": "jest ./src --coverage --coverageReporters lcov text-summary",
|
||||
"e2e": "jest ./__tests__",
|
||||
"cli": "ts-node src/cli.ts",
|
||||
"build": "tsc -p tsconfig.build.json && cp ./src/cli/preview-server/default.hbs ./lib/cli/preview-server",
|
||||
"benchmark": "node --expose-gc --noconcurrent_sweeping --predictable ./benchmark/benchmark.js",
|
||||
"prettier": "npx prettier --write \"**/*.{ts,js}\"",
|
||||
"unit": "jest ./packages --coverage --coverageReporters lcov text-summary",
|
||||
"typecheck": "tsc --noEmit --skipLibCheck",
|
||||
"prepublishOnly": "npm run build",
|
||||
"bundle": "webpack --config webpack.config.ts",
|
||||
"e2e": "jest ./__tests__",
|
||||
"prettier": "npx prettier --write \"**/*.{ts,js}\"",
|
||||
"clean": "rm -rf packages/**/lib packages/**/node_modules packages/**/*.tsbuildinfo package-lock.json node_modules",
|
||||
"compile": "tsc -b tsconfig.build.json",
|
||||
"prepare": "npm run compile",
|
||||
"cli": "ts-node packages/cli/src/index.ts",
|
||||
"lint": "npm run cli lint nodejs/resources/pets.yaml -- --format stylish",
|
||||
"bundle": "npm run cli bundle nodejs/resources/pets.yaml nodejs/resources/p.yaml",
|
||||
"stats": "npm run cli stats nodejs/resources/pets.yaml",
|
||||
"split": "npm run cli split nodejs/resources/pets.yaml -- --outDir output",
|
||||
"preview": "npm run cli preview-docs nodejs/resources/pets.yaml",
|
||||
"benchmark": "node --expose-gc --noconcurrent_sweeping --predictable packages/core/src/benchmark/benchmark.js",
|
||||
"webpack-bundle": "webpack --config webpack.config.ts",
|
||||
"upload": "node scripts/archive-and-upload-bundle.js"
|
||||
},
|
||||
"bin": {
|
||||
"openapi": "lib/cli.js"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Redocly/openapi-cli.git"
|
||||
@@ -37,61 +43,37 @@
|
||||
],
|
||||
"contributors": [
|
||||
"Sergey Dubovyk <serhii@redoc.ly> (https://redoc.ly/)",
|
||||
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)"
|
||||
"Roman Hotsiy <roman@redoc.ly> (https://redoc.ly/)",
|
||||
"Andriy Leliv <andriy@redoc.ly> (https://redoc.ly/)"
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.0",
|
||||
"@types/js-levenshtein": "^1.1.0",
|
||||
"@types/js-yaml": "^3.12.4",
|
||||
"@types/lodash.isequal": "^4.5.5",
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/yargs": "^15.0.5",
|
||||
"jest": "^26.0.1",
|
||||
"null-loader": "^4.0.0",
|
||||
"outdent": "^0.7.1",
|
||||
"prettier": "^2.0.5",
|
||||
"shebang-loader": "0.0.1",
|
||||
"ts-jest": "^26.1.0",
|
||||
"ts-loader": "^8.0.2",
|
||||
"ts-node": "^8.10.2",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redocly/ajv": "^6.12.3",
|
||||
"@types/node": "^14.0.13",
|
||||
"chokidar": "^3.4.0",
|
||||
"colorette": "^1.2.0",
|
||||
"glob": "^7.1.6",
|
||||
"glob-promise": "^3.4.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
"js-yaml": "^3.14.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"portfinder": "^1.0.26",
|
||||
"readline": "^1.3.0",
|
||||
"simple-websocket": "^9.0.0",
|
||||
"typescript": "^3.9.5",
|
||||
"yaml-ast-parser": "0.0.43",
|
||||
"yargs": "^15.3.1"
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.15",
|
||||
"jest": "^26.6.3",
|
||||
"null-loader": "^4.0.0",
|
||||
"outdent": "^0.7.1",
|
||||
"prettier": "^2.1.2",
|
||||
"shebang-loader": "0.0.1",
|
||||
"ts-jest": "^26.4.4",
|
||||
"ts-loader": "^8.0.2",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "4.0.5",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.ts",
|
||||
"!src/**/__tests__/**/*",
|
||||
"!src/cli.ts",
|
||||
"!src/cli/**/*.ts",
|
||||
"!src/format/format.ts"
|
||||
"packages/**/*.ts",
|
||||
"!packages/**/__tests__/**/*",
|
||||
"!packages/cli/src/index.ts",
|
||||
"!packages/cli/**/*.ts",
|
||||
"!packages/cli/src/format/format.ts"
|
||||
],
|
||||
"testMatch": [
|
||||
"**/__tests__/**/*.test.ts",
|
||||
|
||||
3
packages/cli/bin/cli.js
Executable file
3
packages/cli/bin/cli.js
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require("../lib/index");
|
||||
29
packages/cli/package.json
Normal file
29
packages/cli/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@redocly/openapi-cli",
|
||||
"version": "1.0.0-beta.18",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"openapi-cli": "bin/cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redocly/openapi-core": "^1.0.0-beta.18",
|
||||
"@types/node": "^14.11.8",
|
||||
"yargs": "^15.3.1",
|
||||
"colorette": "^1.2.0",
|
||||
"chokidar": "^3.4.0",
|
||||
"handlebars": "^4.7.6",
|
||||
"portfinder": "^1.0.26",
|
||||
"readline": "^1.3.0",
|
||||
"simple-websocket": "^9.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"glob-promise": "^3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/yargs": "^15.0.5",
|
||||
"typescript": "^4.0.3"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
import * as colorette from 'colorette';
|
||||
import * as chockidar from 'chokidar';
|
||||
|
||||
import { loadConfig } from '../config/config';
|
||||
import { bundle } from '../bundle';
|
||||
import { getFallbackEntryPointsOrExit, getTotals } from '../cli';
|
||||
import { bundle, loadConfig, ResolveError, YamlParseError, RedoclyClient } from "@redocly/openapi-core";
|
||||
import { getFallbackEntryPointsOrExit, getTotals } from '../../utils';
|
||||
import startPreviewServer from './preview-server/preview-server';
|
||||
import { RedoclyClient } from '../redocly';
|
||||
import { ResolveError, YamlParseError } from '../resolve';
|
||||
|
||||
export async function previewDocs(argv: {
|
||||
port: number;
|
||||
@@ -39,7 +35,6 @@ export async function previewDocs(argv: {
|
||||
ref: entrypoint,
|
||||
config,
|
||||
});
|
||||
|
||||
const removed = [...deps].filter((x) => !fileDependencies.has(x));
|
||||
watcher.unwatch(removed);
|
||||
watcher.add([...fileDependencies]);
|
||||
@@ -52,11 +47,11 @@ export async function previewDocs(argv: {
|
||||
process.stdout.write(
|
||||
fileTotals.errors === 0
|
||||
? `Created a bundle for ${entrypoint} ${
|
||||
fileTotals.warnings > 0 ? 'with warnings' : 'successfully'
|
||||
}\n`
|
||||
fileTotals.warnings > 0 ? 'with warnings' : 'successfully'
|
||||
}\n`
|
||||
: colorette.yellow(
|
||||
`Created a bundle for ${entrypoint} with errors. Docs may be broken or not accurate\n`,
|
||||
),
|
||||
`Created a bundle for ${entrypoint} with errors. Docs may be broken or not accurate\n`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// import { watch } from 'chokidar';
|
||||
import { compile } from 'handlebars';
|
||||
import * as colorette from 'colorette';
|
||||
import * as portfinder from 'portfinder';
|
||||
|
||||
import { readFileSync, promises as fsPromises } from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { printExecutionTime, readYaml, writeYaml } from '../../utils';
|
||||
import { red, blue, yellow, green } from 'colorette';
|
||||
import * as fs from 'fs';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as path from 'path';
|
||||
import { performance } from 'perf_hooks';
|
||||
const isEqual = require('lodash.isequal');
|
||||
import { pathToFilename } from '../../ref-utils';
|
||||
import { printExecutionTime, pathToFilename, readYaml, writeYaml } from '../../utils';
|
||||
import { isString, isObject, isEmptyObject } from '../../js-utils';
|
||||
import {
|
||||
Definition,
|
||||
Oas2Definition,
|
||||
Oas3Schema,
|
||||
Oas3Definition,
|
||||
Oas3Components,
|
||||
Oas3ComponentName,
|
||||
@@ -22,8 +23,6 @@ import {
|
||||
OPENAPI3_METHOD_NAMES,
|
||||
OPENAPI3_COMPONENT_NAMES
|
||||
} from './types'
|
||||
import { performance } from 'perf_hooks';
|
||||
import { Oas3Schema } from '../../typings/openapi';
|
||||
|
||||
export async function handleSplit (argv: {
|
||||
entrypoint?: string;
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
Oas3Schema,
|
||||
Oas3Definition,
|
||||
Oas3Components,
|
||||
Oas3PathItem,
|
||||
Oas3Paths,
|
||||
Oas3ComponentName,
|
||||
} from '../../typings/openapi';
|
||||
import { Oas2Definition } from '../../typings/swagger';
|
||||
export { Oas3Definition, Oas2Definition, Oas3Components, Oas3Paths, Oas3PathItem, Oas3ComponentName }
|
||||
Oas2Definition
|
||||
} from "@redocly/openapi-core";
|
||||
export { Oas3Definition, Oas2Definition, Oas3Components, Oas3Paths, Oas3PathItem, Oas3ComponentName, Oas3Schema }
|
||||
export type Definition = Oas3Definition | Oas2Definition;
|
||||
export interface ComponentsFiles {
|
||||
[schemas: string]: any;
|
||||
@@ -1,17 +1,28 @@
|
||||
import { performance } from 'perf_hooks';
|
||||
import * as colors from 'colorette';
|
||||
import { Config, LintConfig, loadConfig } from '..';
|
||||
import { normalizeTypes } from '../types';
|
||||
import { Oas3Types } from '../types/oas3';
|
||||
import { Oas2Types } from '../types/oas2';
|
||||
import { StatsAccumulator, StatsName } from '../typings/common';
|
||||
import { BaseResolver, Document, resolveDocument } from '../resolve';
|
||||
import { detectOpenAPI, OasMajorVersion, openAPIMajor } from '../validate';
|
||||
import { normalizeVisitors } from '../visitors';
|
||||
import { WalkContext, walkDocument } from '../walk';
|
||||
import { getFallbackEntryPointsOrExit } from '../cli';
|
||||
import {
|
||||
Config,
|
||||
LintConfig,
|
||||
loadConfig,
|
||||
normalizeTypes,
|
||||
Oas3Types,
|
||||
Oas2Types,
|
||||
StatsAccumulator,
|
||||
StatsName,
|
||||
BaseResolver,
|
||||
Document,
|
||||
resolveDocument,
|
||||
detectOpenAPI,
|
||||
OasMajorVersion,
|
||||
openAPIMajor,
|
||||
normalizeVisitors,
|
||||
WalkContext,
|
||||
walkDocument,
|
||||
Stats
|
||||
} from "@redocly/openapi-core";
|
||||
|
||||
import { getFallbackEntryPointsOrExit } from '../utils'
|
||||
import { printExecutionTime } from '../utils';
|
||||
import { Stats } from '../rules/other/stats';
|
||||
|
||||
const statsAccumulator: StatsAccumulator = {
|
||||
refs: { metric: '🚗 References', total: 0, color: 'red', items: new Set() },
|
||||
@@ -1,32 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import * as yargs from 'yargs';
|
||||
import { extname, basename, dirname, join, resolve } from 'path';
|
||||
import { extname, basename, dirname, join } from 'path';
|
||||
import { red, green, yellow, blue, gray } from 'colorette';
|
||||
import { performance } from 'perf_hooks';
|
||||
import * as glob from 'glob-promise';
|
||||
import { validate } from './validate';
|
||||
import { bundle } from './bundle';
|
||||
|
||||
import { Totals } from './types';
|
||||
|
||||
import {
|
||||
BundleOutputFormat,
|
||||
validate,
|
||||
bundle,
|
||||
loadConfig,
|
||||
LintConfig,
|
||||
ResolveError,
|
||||
YamlParseError,
|
||||
RedoclyClient,
|
||||
formatProblems,
|
||||
OutputFormat,
|
||||
} from "@redocly/openapi-core";
|
||||
|
||||
import {
|
||||
CircularJSONNotSupportedError,
|
||||
getFallbackEntryPointsOrExit,
|
||||
getExecutionTime,
|
||||
getTotals,
|
||||
dumpBundle,
|
||||
saveBundle,
|
||||
BundleOutputFormat,
|
||||
promptUser,
|
||||
CircularJSONNotSupportedError,
|
||||
getExecutionTime,
|
||||
} from './utils';
|
||||
import { formatProblems, OutputFormat } from './format/format';
|
||||
import { ResolveError, YamlParseError } from './resolve';
|
||||
import { loadConfig, Config, LintConfig } from './config/config';
|
||||
import { NormalizedProblem } from './walk';
|
||||
import { previewDocs } from './cli/preview-docs';
|
||||
import { handleStats } from './cli/stats';
|
||||
import { handleSplit } from './cli/split';
|
||||
import { RedoclyClient } from './redocly';
|
||||
import { previewDocs } from './commands/preview-docs';
|
||||
import { handleStats } from './commands/stats';
|
||||
import { handleSplit } from './commands/split';
|
||||
const version = require('../package.json').version;
|
||||
const outputExtensions = ['json', 'yaml', 'yml'] as ReadonlyArray<BundleOutputFormat>;
|
||||
const ERROR_MESSAGE = {
|
||||
MISSING_ARGUMENT: 'error: missing required argument `entrypoints`.\n'
|
||||
}
|
||||
|
||||
yargs
|
||||
.version('version', 'Show version number.', version)
|
||||
@@ -35,24 +42,24 @@ yargs
|
||||
(yargs) => yargs
|
||||
.positional('entrypoint', { type: 'string' })
|
||||
.option({
|
||||
config: { description: 'Specify path to the config file.', type: 'string' },
|
||||
format: {
|
||||
description: 'Use a specific output format.',
|
||||
choices: ['stylish', 'json'] as ReadonlyArray<OutputFormat>,
|
||||
default: 'stylish' as OutputFormat,
|
||||
config: { description: 'Specify path to the config file.', type: 'string' },
|
||||
format: {
|
||||
description: 'Use a specific output format.',
|
||||
choices: ['stylish', 'json'] as ReadonlyArray<OutputFormat>,
|
||||
default: 'stylish' as OutputFormat,
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
),
|
||||
async (argv) => { handleStats(argv) }
|
||||
)
|
||||
.command('split [entrypoint]', 'Split definition into a multi-file structure',
|
||||
(yargs) => yargs
|
||||
.positional('entrypoint', { type: 'string' })
|
||||
.option({ outDir: {
|
||||
description: 'Output directory where files will be saved',
|
||||
required: true,
|
||||
type: 'string'
|
||||
}}),
|
||||
description: 'Output directory where files will be saved',
|
||||
required: true,
|
||||
type: 'string'
|
||||
}}),
|
||||
(argv) => { handleSplit(argv) }
|
||||
)
|
||||
.command(
|
||||
@@ -410,14 +417,16 @@ function handleError(e: Error, ref: string) {
|
||||
`Failed to parse entrypoint definition at ${ref}:\n\n - ${e.message}.\n\n`,
|
||||
);
|
||||
// TODO: codeframe
|
||||
} else if (e instanceof CircularJSONNotSupportedError) {
|
||||
process.stderr.write(
|
||||
red(`Detected circular reference which can't be converted to JSON.\n`) +
|
||||
`Try to use ${blue('yaml')} output or remove ${blue('--dereferenced')}.\n\n`,
|
||||
);
|
||||
} else {
|
||||
process.stderr.write(`Something went wrong when processing ${ref}:\n\n - ${e.message}.\n\n`);
|
||||
throw e;
|
||||
} else { // @ts-ignore
|
||||
if (e instanceof CircularJSONNotSupportedError) {
|
||||
process.stderr.write(
|
||||
red(`Detected circular reference which can't be converted to JSON.\n`) +
|
||||
`Try to use ${blue('yaml')} output or remove ${blue('--dereferenced')}.\n\n`,
|
||||
);
|
||||
} else {
|
||||
process.stderr.write(`Something went wrong when processing ${ref}:\n\n - ${e.message}.\n\n`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,33 +472,6 @@ function printLintTotals(totals: Totals, definitionsCount: number) {
|
||||
process.stderr.write('\n');
|
||||
}
|
||||
|
||||
export type Totals = {
|
||||
errors: number;
|
||||
warnings: number;
|
||||
ignored: number;
|
||||
};
|
||||
|
||||
export function getTotals(problems: (NormalizedProblem & { ignored?: boolean })[]): Totals {
|
||||
let errors = 0;
|
||||
let warnings = 0;
|
||||
let ignored = 0;
|
||||
|
||||
for (const m of problems) {
|
||||
if (m.ignored) {
|
||||
ignored++;
|
||||
continue;
|
||||
}
|
||||
if (m.severity === 'error') errors++;
|
||||
if (m.severity === 'warn') warnings++;
|
||||
}
|
||||
|
||||
return {
|
||||
errors,
|
||||
warnings,
|
||||
ignored,
|
||||
};
|
||||
}
|
||||
|
||||
function pluralize(label: string, num: number) {
|
||||
if (label.endsWith('is')) {
|
||||
[label] = label.split(' ');
|
||||
@@ -498,40 +480,6 @@ function pluralize(label: string, num: number) {
|
||||
return num === 1 ? `${label}` : `${label}s`;
|
||||
}
|
||||
|
||||
function getConfigDirectory(config: Config) {
|
||||
return config.configFile ? dirname(config.configFile) : process.cwd();
|
||||
}
|
||||
|
||||
function getAliasOrPath(config: Config, aliasOrPath: string) {
|
||||
return config.apiDefinitions[aliasOrPath] || aliasOrPath;
|
||||
}
|
||||
|
||||
function isNotEmptyArray(args?: string[]): boolean {
|
||||
return Array.isArray(args) && !!args.length;
|
||||
}
|
||||
|
||||
async function expandGlobsInEntrypoints(args: string[], config: Config) {
|
||||
return (await Promise.all((args as string[]).map(async aliasOrPath => {
|
||||
return glob.hasMagic(aliasOrPath)
|
||||
? (await glob(aliasOrPath)).map((g: string) => getAliasOrPath(config, g))
|
||||
: getAliasOrPath(config, aliasOrPath);
|
||||
}))).flat();
|
||||
}
|
||||
|
||||
export async function getFallbackEntryPointsOrExit(argsEntrypoints: string[] | undefined, config: Config) {
|
||||
const { apiDefinitions } = config;
|
||||
const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsEntrypoints) && apiDefinitions && Object.keys(apiDefinitions).length > 0;
|
||||
const res = shouldFallbackToAllDefinitions
|
||||
? Object.values(apiDefinitions).map((fileName) => resolve(getConfigDirectory(config), fileName))
|
||||
: await expandGlobsInEntrypoints(argsEntrypoints!, config);
|
||||
|
||||
if (!isNotEmptyArray(res)) {
|
||||
process.stderr.write(ERROR_MESSAGE.MISSING_ARGUMENT);
|
||||
process.exit(1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function printUnusedWarnings(config: LintConfig) {
|
||||
const { preprocessors, rules, decorators } = config.getUnusedRules();
|
||||
if (rules.length) {
|
||||
5
packages/cli/src/types.ts
Normal file
5
packages/cli/src/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type Totals = {
|
||||
errors: number;
|
||||
warnings: number;
|
||||
ignored: number;
|
||||
}
|
||||
135
packages/cli/src/utils.ts
Normal file
135
packages/cli/src/utils.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { performance } from "perf_hooks";
|
||||
import * as colors from 'colorette';
|
||||
import * as glob from 'glob-promise';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as readline from 'readline';
|
||||
import { BundleOutputFormat, Config, NormalizedProblem } from "@redocly/openapi-core";
|
||||
import { dirname, resolve } from 'path';
|
||||
import { Totals } from './types';
|
||||
|
||||
export async function getFallbackEntryPointsOrExit(argsEntrypoints: string[] | undefined, config: Config) {
|
||||
const { apiDefinitions } = config;
|
||||
const shouldFallbackToAllDefinitions = !isNotEmptyArray(argsEntrypoints) && apiDefinitions && Object.keys(apiDefinitions).length > 0;
|
||||
const res = shouldFallbackToAllDefinitions
|
||||
? Object.values(apiDefinitions).map((fileName) => resolve(getConfigDirectory(config), fileName))
|
||||
: await expandGlobsInEntrypoints(argsEntrypoints!, config);
|
||||
|
||||
if (!isNotEmptyArray(res)) {
|
||||
process.stderr.write('error: missing required argument `entrypoints`.\n');
|
||||
process.exit(1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function getConfigDirectory(config: Config) {
|
||||
return config.configFile ? dirname(config.configFile) : process.cwd();
|
||||
}
|
||||
|
||||
function isNotEmptyArray(args?: string[]): boolean {
|
||||
return Array.isArray(args) && !!args.length;
|
||||
}
|
||||
function getAliasOrPath(config: Config, aliasOrPath: string) {
|
||||
return config.apiDefinitions[aliasOrPath] || aliasOrPath;
|
||||
}
|
||||
|
||||
async function expandGlobsInEntrypoints(args: string[], config: Config) {
|
||||
return (await Promise.all((args as string[]).map(async aliasOrPath => {
|
||||
return glob.hasMagic(aliasOrPath)
|
||||
? (await glob(aliasOrPath)).map((g: string) => getAliasOrPath(config, g))
|
||||
: getAliasOrPath(config, aliasOrPath);
|
||||
}))).flat();
|
||||
}
|
||||
|
||||
export function getTotals(problems: (NormalizedProblem & { ignored?: boolean })[]): Totals {
|
||||
let errors = 0;
|
||||
let warnings = 0;
|
||||
let ignored = 0;
|
||||
|
||||
for (const m of problems) {
|
||||
if (m.ignored) {
|
||||
ignored++;
|
||||
continue;
|
||||
}
|
||||
if (m.severity === 'error') errors++;
|
||||
if (m.severity === 'warn') warnings++;
|
||||
}
|
||||
|
||||
return {
|
||||
errors,
|
||||
warnings,
|
||||
ignored,
|
||||
};
|
||||
}
|
||||
|
||||
export function getExecutionTime(startedAt: number) {
|
||||
return process.env.NODE_ENV === 'test'
|
||||
? '<test>ms'
|
||||
: `${Math.ceil(performance.now() - startedAt)}ms`;
|
||||
}
|
||||
|
||||
export function printExecutionTime(commandName: string, startedAt: number, entrypoint: string) {
|
||||
const elapsed = getExecutionTime(startedAt);
|
||||
process.stderr.write(colors.gray(`\n${entrypoint}: ${commandName} processed in ${elapsed}\n\n`));
|
||||
}
|
||||
|
||||
export function pathToFilename(path: string) {
|
||||
return path
|
||||
.replace(/~1/g, '/')
|
||||
.replace(/~0/g, '~')
|
||||
.substring(1)
|
||||
.replace(/\//g, '@');
|
||||
}
|
||||
|
||||
export class CircularJSONNotSupportedError extends Error {
|
||||
constructor(public originalError: Error) {
|
||||
super(originalError.message);
|
||||
// Set the prototype explicitly.
|
||||
Object.setPrototypeOf(this, CircularJSONNotSupportedError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
export function dumpBundle(obj: any, format: BundleOutputFormat, dereference?: boolean) {
|
||||
if (format === 'json') {
|
||||
try {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
} catch (e) {
|
||||
if (e.message.indexOf('circular') > -1) {
|
||||
throw new CircularJSONNotSupportedError(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
return yaml.safeDump(obj, {
|
||||
noRefs: !dereference,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function saveBundle(filename: string, output: string) {
|
||||
fs.mkdirSync(path.dirname(filename), { recursive: true });
|
||||
fs.writeFileSync(filename, output);
|
||||
}
|
||||
|
||||
export async function promptUser(query: string): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
rl.question(`${query}:\n\n `, (answer) => {
|
||||
rl.close();
|
||||
resolve(answer);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function readYaml(filename: string) {
|
||||
return yaml.safeLoad(fs.readFileSync(filename, 'utf-8'), { filename });
|
||||
}
|
||||
|
||||
export function writeYaml(data: any, filename: string) {
|
||||
return fs.writeFileSync(filename, yaml.safeDump(data));
|
||||
}
|
||||
9
packages/cli/tsconfig.json
Normal file
9
packages/cli/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "lib"
|
||||
},
|
||||
"references": [{ "path": "../core" }],
|
||||
"exclude": ["lib"]
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import outdent from 'outdent';
|
||||
import * as path from 'path';
|
||||
|
||||
import { bundleDocument, bundle } from '../bundle';
|
||||
import { bundleDocument, bundle } from '../src/bundle';
|
||||
|
||||
import { parseYamlToDocument, yamlSerializer } from './utils';
|
||||
import { LintConfig, Config } from '../config/config';
|
||||
import { BaseResolver } from '../resolve';
|
||||
import { LintConfig, Config } from '../src/config/config';
|
||||
import { BaseResolver } from '../src/resolve';
|
||||
|
||||
describe('bundle', () => {
|
||||
expect.addSnapshotSerializer(yamlSerializer);
|
||||
@@ -1,8 +1,8 @@
|
||||
import { outdent } from 'outdent';
|
||||
|
||||
import { getLineColLocation, getCodeframe } from '../format/codeframes';
|
||||
import { LocationObject } from '../walk';
|
||||
import { Source } from '../resolve';
|
||||
import { getLineColLocation, getCodeframe } from '../src/format/codeframes';
|
||||
import { LocationObject } from '../src/walk';
|
||||
import { Source } from '../src/resolve';
|
||||
|
||||
describe('Location', () => {
|
||||
it('should correctly calculate location for key', () => {
|
||||
@@ -20,7 +20,6 @@ describe('Location', () => {
|
||||
`,
|
||||
),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 3, col: 3 });
|
||||
expect(preciseLocation.end).toEqual({ line: 3, col: 10 });
|
||||
@@ -41,7 +40,6 @@ describe('Location', () => {
|
||||
`,
|
||||
),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 2, col: 1 });
|
||||
expect(preciseLocation.end).toEqual({ line: 2, col: 5 });
|
||||
@@ -62,7 +60,6 @@ describe('Location', () => {
|
||||
`,
|
||||
),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 4, col: 11 });
|
||||
expect(preciseLocation.end).toEqual({ line: 4, col: 14 });
|
||||
@@ -83,7 +80,6 @@ describe('Location', () => {
|
||||
`,
|
||||
),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 3, col: 3 });
|
||||
expect(preciseLocation.end).toEqual({ line: 5, col: 28 });
|
||||
@@ -95,7 +91,6 @@ describe('Location', () => {
|
||||
pointer: '#/info/missing',
|
||||
source: new Source('foobar.yaml', ''),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 1, col: 1 });
|
||||
expect(preciseLocation.end).toEqual({ line: 1, col: 1 });
|
||||
@@ -107,7 +102,6 @@ describe('Location', () => {
|
||||
pointer: '#/info/missing',
|
||||
source: new Source('foobar.yaml', '\n\n\n'),
|
||||
};
|
||||
|
||||
const preciseLocation = getLineColLocation(loc);
|
||||
expect(preciseLocation.start).toEqual({ line: 1, col: 1 });
|
||||
expect(preciseLocation.end).toEqual({ line: 1, col: 1 });
|
||||
@@ -1,7 +1,7 @@
|
||||
import { normalizeVisitors, VisitorLevelContext } from '../visitors';
|
||||
import { Oas3RuleSet } from '../validate';
|
||||
import { Oas3Types } from '../types/oas3';
|
||||
import { normalizeTypes } from '../types';
|
||||
import { normalizeVisitors, VisitorLevelContext } from '../src/visitors';
|
||||
import { Oas3RuleSet } from '../src/validate';
|
||||
import { Oas3Types } from '../src/types/oas3';
|
||||
import { normalizeTypes } from '../src/types';
|
||||
|
||||
describe('Normalize visitors', () => {
|
||||
it('should work correctly for single rule', () => {
|
||||
@@ -1,10 +1,10 @@
|
||||
import outdent from 'outdent';
|
||||
|
||||
import { parseYamlToDocument } from './utils';
|
||||
import { parseRef } from '../ref-utils';
|
||||
import { validateDocument } from '../validate';
|
||||
import { LintConfig } from '../config/config';
|
||||
import { BaseResolver } from '../resolve';
|
||||
import { parseRef } from '../src/ref-utils';
|
||||
import { validateDocument } from '../src/validate';
|
||||
import { LintConfig } from '../src/config/config';
|
||||
import { BaseResolver } from '../src/resolve';
|
||||
|
||||
describe('ref-utils', () => {
|
||||
it(`should unescape refs with '/'`, () => {
|
||||
@@ -1,9 +1,9 @@
|
||||
import { outdent } from 'outdent';
|
||||
|
||||
import { resolveDocument, BaseResolver } from '../resolve';
|
||||
import { resolveDocument, BaseResolver } from '../src/resolve';
|
||||
import { parseYamlToDocument } from './utils';
|
||||
import { Oas3Types } from '../types/oas3';
|
||||
import { normalizeTypes } from '../types';
|
||||
import { Oas3Types } from '../src/types/oas3';
|
||||
import { normalizeTypes } from '../src/types';
|
||||
|
||||
describe('Resolve http-headers', () => {
|
||||
it('should use matching http-headers', async () => {
|
||||
@@ -1,10 +1,10 @@
|
||||
import { outdent } from 'outdent';
|
||||
import * as path from 'path';
|
||||
|
||||
import { resolveDocument, BaseResolver, Document } from '../resolve';
|
||||
import { resolveDocument, BaseResolver, Document } from '../src/resolve';
|
||||
import { parseYamlToDocument } from './utils';
|
||||
import { Oas3Types } from '../types/oas3';
|
||||
import { normalizeTypes } from '../types';
|
||||
import { Oas3Types } from '../src/types/oas3';
|
||||
import { normalizeTypes } from '../src/types';
|
||||
|
||||
describe('collect refs', () => {
|
||||
it('should resolve local refs', async () => {
|
||||
@@ -32,9 +32,9 @@ describe('collect refs', () => {
|
||||
expect(Array.from(resolvedRefs.keys())).toMatchInlineSnapshot(
|
||||
[`foobar.yaml::#/defs/info`],
|
||||
`
|
||||
Object {
|
||||
"0": "foobar.yaml::#/defs/info",
|
||||
}
|
||||
Array [
|
||||
"foobar.yaml::#/defs/info",
|
||||
]
|
||||
`,
|
||||
);
|
||||
expect(Array.from(resolvedRefs.values()).map((info) => info.node)).toEqual([
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as path from 'path';
|
||||
|
||||
import { Document, Source } from '../resolve';
|
||||
import { NormalizedProblem } from '../walk';
|
||||
import { RuleConfig, LintConfig, Plugin } from '../config/config';
|
||||
import { Oas3RuleSet } from '../validate';
|
||||
import { Document, Source } from '../src/resolve';
|
||||
import { NormalizedProblem } from '../src/walk';
|
||||
import { RuleConfig, LintConfig, Plugin } from '../src/config/config';
|
||||
import { Oas3RuleSet } from '../src/validate';
|
||||
|
||||
export function parseYamlToDocument(body: string, absoluteRef: string = ''): Document {
|
||||
return {
|
||||
@@ -1,11 +1,11 @@
|
||||
import outdent from 'outdent';
|
||||
import * as path from 'path';
|
||||
|
||||
import { validateDocument, Oas3RuleSet } from '../validate';
|
||||
import { validateDocument, Oas3RuleSet } from '../src/validate';
|
||||
|
||||
import { parseYamlToDocument, replaceSourceWithRef, makeConfigForRuleset } from './utils';
|
||||
import { BaseResolver, Document } from '../resolve';
|
||||
import { listOf } from '../types';
|
||||
import { BaseResolver, Document } from '../src/resolve';
|
||||
import { listOf } from '../src/types';
|
||||
|
||||
describe('walk order', () => {
|
||||
it('should run visitors', async () => {
|
||||
26
packages/core/package.json
Normal file
26
packages/core/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@redocly/openapi-core",
|
||||
"version": "1.0.0-beta.18",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^14.11.8",
|
||||
"colorette": "^1.2.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
"yaml-ast-parser": "0.0.43",
|
||||
"minimatch": "^3.0.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
"@redocly/ajv": "^6.12.3",
|
||||
"lodash.isequal": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^3.12.4",
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/js-levenshtein": "^1.1.0",
|
||||
"@types/lodash.isequal": "^4.5.5",
|
||||
"typescript": "^4.0.5"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument } from '../../src/__tests__/utils';
|
||||
|
||||
import { LintConfig } from '../../src/config/config';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
import { validateDocument } from '../../validate';
|
||||
import { LintConfig } from '../../config/config';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument } from '../utils';
|
||||
|
||||
export const name = 'Validate with recommended rules';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
@@ -1,14 +1,12 @@
|
||||
import * as path from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
import { resolveDocument, BaseResolver } from '../../src/resolve';
|
||||
import { parseYamlToDocument } from '../../src/__tests__/utils';
|
||||
import { Oas3Types } from '../../src/types/oas3';
|
||||
import { normalizeTypes } from '../../src/types';
|
||||
import { resolveDocument, BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument } from '../utils';
|
||||
import { Oas3Types } from '../../types/oas3';
|
||||
import { normalizeTypes } from '../../types';
|
||||
|
||||
export const name = 'Resolve with no external refs';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = path.resolve(path.join(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
@@ -1,13 +1,11 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../../src/__tests__/utils';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
import { validateDocument } from '../../validate';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../utils';
|
||||
|
||||
export const name = 'Validate with 50 top-level rules';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
@@ -28,7 +26,6 @@ for (let i = 0; i < 50; i++) {
|
||||
}
|
||||
|
||||
const config = makeConfigForRuleset(ruleset);
|
||||
|
||||
export function measureAsync() {
|
||||
return validateDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
@@ -1,19 +1,16 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../../src/__tests__/utils';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
import { validateDocument } from '../../validate';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../utils';
|
||||
|
||||
export const name = 'Validate with single nested rule';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
rebillyDefinitionRef,
|
||||
);
|
||||
|
||||
const visitor = {
|
||||
test: () => {
|
||||
let count = 0;
|
||||
@@ -32,9 +29,7 @@ const visitor = {
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const config = makeConfigForRuleset(visitor);
|
||||
|
||||
export function measureAsync() {
|
||||
return validateDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
@@ -1,21 +1,16 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../../src/__tests__/utils';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
|
||||
import { validateDocument } from '../../validate';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../utils';
|
||||
export const name = 'Validate with no rules';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
rebillyDefinitionRef,
|
||||
);
|
||||
|
||||
const config = makeConfigForRuleset({});
|
||||
|
||||
export function measureAsync() {
|
||||
return validateDocument({
|
||||
externalRefResolver: new BaseResolver(),
|
||||
@@ -1,13 +1,11 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../../src/__tests__/utils';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
import { validateDocument } from '../../validate';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../utils';
|
||||
|
||||
export const name = 'Validate with single top-level rule and report';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
@@ -17,6 +15,7 @@ const rebillyDocument = parseYamlToDocument(
|
||||
const config = makeConfigForRuleset({
|
||||
test: () => {
|
||||
return {
|
||||
// @ts-ignore
|
||||
Schema(schema, ctx) {
|
||||
if (schema.type === 'number') {
|
||||
ctx.report({
|
||||
@@ -1,13 +1,10 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join as pathJoin, resolve as pathResolve } from 'path';
|
||||
|
||||
import { validateDocument } from '../../src/validate';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../../src/__tests__/utils';
|
||||
import { BaseResolver } from '../../src/resolve';
|
||||
|
||||
import { validateDocument } from '../../validate';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
import { parseYamlToDocument, makeConfigForRuleset } from '../utils';
|
||||
export const name = 'Validate with single top-level rule';
|
||||
export const count = 10;
|
||||
|
||||
const rebillyDefinitionRef = pathResolve(pathJoin(__dirname, 'rebilly.yaml'));
|
||||
const rebillyDocument = parseYamlToDocument(
|
||||
readFileSync(rebillyDefinitionRef, 'utf-8'),
|
||||
@@ -1,14 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const assert = require('assert');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const { red, green, yellow, cyan, grey } = require('./colors');
|
||||
const { sampleModule } = require('./fork');
|
||||
|
||||
const NS_PER_SEC = 1e9;
|
||||
const LOCAL = 'local';
|
||||
|
||||
@@ -27,37 +24,32 @@ function prepareRevision(revision) {
|
||||
console.log(`🍳 Preparing ${revision}...`);
|
||||
|
||||
if (revision === LOCAL) {
|
||||
return tscBuild(LOCAL_DIR());
|
||||
return tscBuild(path.join(LOCAL_DIR(), '../../..'));
|
||||
}
|
||||
|
||||
// Returns the complete git hash for a given git revision reference.
|
||||
const hash = exec(`git rev-parse "${revision}"`);
|
||||
|
||||
const dir = path.join(os.tmpdir(), 'openapi-cli-benchmark', hash);
|
||||
fs.rmdirSync(dir, { recursive: true });
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
|
||||
exec(`git archive "${hash}" | tar -xC "${dir}"`);
|
||||
exec('npm ci', { cwd: dir });
|
||||
|
||||
const to = path.join(dir, 'benchmark/benches');
|
||||
const to = path.join(dir, 'packages/core/src/benchmark/benches');
|
||||
exec(`rm -rf ${to}`);
|
||||
exec(`cp -R ${LOCAL_DIR('benchmark/benches')} ${to}`);
|
||||
|
||||
return tscBuild(dir);
|
||||
}
|
||||
|
||||
function tscBuild(dir) {
|
||||
const oldCwd = process.cwd();
|
||||
process.chdir(dir);
|
||||
|
||||
execSync('rm -rf dist && npx tsc', { stdio: 'inherit' });
|
||||
execSync('npm run compile', { stdio: 'inherit' });
|
||||
exec(
|
||||
`cp ${path.join(dir, 'benchmark/benches/*.yaml')} ${path.join(dir, 'lib/benchmark/benches/')}`,
|
||||
`cp ${path.join(dir, 'packages/core/src/benchmark/benches/*.yaml')} ${path.join(dir, 'packages/core/lib/benchmark/benches/')}`,
|
||||
);
|
||||
|
||||
process.chdir(oldCwd);
|
||||
return path.join(dir, 'lib/benchmark/benches');
|
||||
return path.join(dir, 'packages/core/lib/benchmark/benches');
|
||||
}
|
||||
|
||||
async function collectSamples(modulePath) {
|
||||
@@ -258,10 +250,10 @@ function exec(command, options) {
|
||||
|
||||
// Find all benchmark tests to be run.
|
||||
function matchBenchmarks(patterns) {
|
||||
let benchmarks = findFiles(LOCAL_DIR('lib/benchmark/benches'), '*.bench.js');
|
||||
let benchmarks = findFiles(LOCAL_DIR('../lib/benchmark/benches'), '*.bench.js');
|
||||
if (patterns.length > 0) {
|
||||
benchmarks = benchmarks.filter((benchmark) =>
|
||||
patterns.some((pattern) => path.join('benchmark/benches', benchmark).includes(pattern)),
|
||||
patterns.some((pattern) => path.join('../lib/benchmark/benches', benchmark).includes(pattern)),
|
||||
);
|
||||
}
|
||||
|
||||
31
packages/core/src/benchmark/utils.ts
Normal file
31
packages/core/src/benchmark/utils.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as yaml from 'js-yaml';
|
||||
import { Document, Source } from '../resolve';
|
||||
import { Oas3RuleSet } from '../validate';
|
||||
import { RuleConfig, LintConfig, Plugin } from '../config/config';
|
||||
|
||||
export function parseYamlToDocument(body: string, absoluteRef: string = ''): Document {
|
||||
return {
|
||||
source: new Source(absoluteRef, body),
|
||||
parsed: yaml.safeLoad(body, { filename: absoluteRef }),
|
||||
};
|
||||
}
|
||||
|
||||
export function makeConfigForRuleset(rules: Oas3RuleSet, plugin?: Partial<Plugin>) {
|
||||
const rulesConf: Record<string, RuleConfig> = {};
|
||||
const ruleId = 'test';
|
||||
Object.keys(rules).forEach((name) => {
|
||||
rulesConf[`${ruleId}/${name}`] = 'error';
|
||||
});
|
||||
|
||||
return new LintConfig({
|
||||
plugins: [
|
||||
{
|
||||
...plugin,
|
||||
id: ruleId,
|
||||
rules: { oas3: rules },
|
||||
},
|
||||
],
|
||||
extends: [],
|
||||
rules: rulesConf,
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import isEqual = require('lodash.isequal');
|
||||
|
||||
import { BaseResolver, resolveDocument, Document } from './resolve';
|
||||
|
||||
import { Oas3Rule, normalizeVisitors, Oas3Visitor, Oas2Visitor } from './visitors';
|
||||
import { Oas3Types } from './types/oas3';
|
||||
import { Oas2Types } from './types/oas2';
|
||||
@@ -6,10 +6,8 @@ export default {
|
||||
'info-contact': 'error',
|
||||
'info-license': 'error',
|
||||
'info-license-url': 'error',
|
||||
|
||||
'tag-description': 'error',
|
||||
'tags-alphabetical': 'error',
|
||||
|
||||
'parameter-description': 'error',
|
||||
'no-identical-paths': 'error',
|
||||
'no-ambiguous-paths': 'error',
|
||||
@@ -27,17 +25,14 @@ export default {
|
||||
'operation-tag-defined': 'error',
|
||||
'operation-security-defined': 'error',
|
||||
'operation-singular-tag': 'error',
|
||||
|
||||
'no-unresolved-refs': 'error',
|
||||
'no-enum-type-mismatch': 'error',
|
||||
|
||||
'boolean-parameter-prefixes': 'error',
|
||||
'paths-kebab-case': 'error',
|
||||
spec: 'error',
|
||||
},
|
||||
oas3_0Rules: {
|
||||
'no-invalid-media-type-examples': 'error',
|
||||
|
||||
'no-server-example.com': 'error',
|
||||
'no-server-trailing-slash': 'error',
|
||||
'no-empty-servers': 'error',
|
||||
@@ -3,7 +3,6 @@ import * as path from 'path';
|
||||
import * as yaml from 'js-yaml';
|
||||
import { dirname } from 'path';
|
||||
import { red, blue } from 'colorette';
|
||||
|
||||
import { builtInConfigs } from './builtIn';
|
||||
import * as builtinRules from '../rules/builtin';
|
||||
import { loadYaml, notUndefined } from '../utils';
|
||||
@@ -6,10 +6,8 @@ export default {
|
||||
'info-contact': 'off',
|
||||
'info-license': 'off',
|
||||
'info-license-url': 'off',
|
||||
|
||||
'tag-description': 'warn',
|
||||
'tags-alphabetical': 'off',
|
||||
|
||||
'parameter-description': 'off',
|
||||
'no-path-trailing-slash': 'warn',
|
||||
'no-identical-paths': 'warn',
|
||||
@@ -27,10 +25,8 @@ export default {
|
||||
'operation-security-defined': 'warn',
|
||||
'operation-operationId-url-safe': 'warn',
|
||||
'operation-singular-tag': 'off',
|
||||
|
||||
'no-unresolved-refs': 'error',
|
||||
'no-enum-type-mismatch': 'warn',
|
||||
|
||||
'boolean-parameter-prefixes': 'off',
|
||||
'paths-kebab-case': 'off',
|
||||
spec: 'error',
|
||||
@@ -40,7 +36,6 @@ export default {
|
||||
severity: 'warn',
|
||||
disallowAdditionalProperties: true,
|
||||
},
|
||||
|
||||
'no-server-example.com': 'warn',
|
||||
'no-server-trailing-slash': 'error',
|
||||
'no-empty-servers': 'warn',
|
||||
@@ -6,10 +6,8 @@ export default {
|
||||
'info-contact': 'off',
|
||||
'info-license': 'warn',
|
||||
'info-license-url': 'warn',
|
||||
|
||||
'tag-description': 'warn',
|
||||
'tags-alphabetical': 'off',
|
||||
|
||||
'parameter-description': 'off',
|
||||
'no-path-trailing-slash': 'error',
|
||||
'no-identical-paths': 'error',
|
||||
@@ -27,10 +25,8 @@ export default {
|
||||
'operation-tag-defined': 'off',
|
||||
'operation-security-defined': 'error',
|
||||
'operation-singular-tag': 'off',
|
||||
|
||||
'no-unresolved-refs': 'error',
|
||||
'no-enum-type-mismatch': 'error',
|
||||
|
||||
'boolean-parameter-prefixes': 'off',
|
||||
'paths-kebab-case': 'off',
|
||||
spec: 'error',
|
||||
@@ -40,7 +36,6 @@ export default {
|
||||
severity: 'warn',
|
||||
disallowAdditionalProperties: true,
|
||||
},
|
||||
|
||||
'no-server-example.com': 'warn',
|
||||
'no-server-trailing-slash': 'error',
|
||||
'no-empty-servers': 'error',
|
||||
@@ -1,8 +1,6 @@
|
||||
import { gray, red, options as colorOptions } from 'colorette';
|
||||
|
||||
import * as yamlAst from 'yaml-ast-parser';
|
||||
|
||||
import { parsePointer } from '../ref-utils';
|
||||
import { unescapePointer } from '../ref-utils';
|
||||
import { LineColLocationObject, Loc, LocationObject } from '../walk';
|
||||
|
||||
type YAMLMapping = yamlAst.YAMLMapping & { kind: yamlAst.Kind.MAPPING };
|
||||
@@ -10,22 +8,22 @@ type YAMLMap = yamlAst.YamlMap & { kind: yamlAst.Kind.MAP };
|
||||
type YAMLAnchorReference = yamlAst.YAMLAnchorReference & { kind: yamlAst.Kind.ANCHOR_REF };
|
||||
type YAMLSequence = yamlAst.YAMLSequence & { kind: yamlAst.Kind.SEQ };
|
||||
type YAMLScalar = yamlAst.YAMLScalar & { kind: yamlAst.Kind.SCALAR };
|
||||
|
||||
type YAMLNode = YAMLMapping | YAMLMap | YAMLAnchorReference | YAMLSequence | YAMLScalar;
|
||||
|
||||
const MAX_LINE_LENGTH = 150;
|
||||
const MAX_CODEFRAME_LINES = 3;
|
||||
|
||||
// TODO: temporary
|
||||
function parsePointer(pointer: string) {
|
||||
return pointer.substr(2).split('/').map(unescapePointer);
|
||||
}
|
||||
|
||||
export function getCodeframe(location: LineColLocationObject, color: boolean) {
|
||||
colorOptions.enabled = color;
|
||||
|
||||
const { start, end = { line: start.line, col: start.col + 1 }, source } = location;
|
||||
|
||||
const lines = source.getLines();
|
||||
|
||||
const startLineNum = start.line;
|
||||
const endLineNum = Math.max(Math.min(end.line, lines.length), start.line);
|
||||
|
||||
let skipLines = Math.max(endLineNum - startLineNum - MAX_CODEFRAME_LINES + 1, 0);
|
||||
if (skipLines < 2) skipLines = 0; // do not skip one line
|
||||
|
||||
@@ -12,7 +12,13 @@ import {
|
||||
|
||||
import { NormalizedProblem, ProblemSeverity, LineColLocationObject, LocationObject } from '../walk';
|
||||
import { getCodeframe, getLineColLocation } from './codeframes';
|
||||
import { Totals } from '../cli';
|
||||
|
||||
type Totals = {
|
||||
errors: number;
|
||||
warnings: number;
|
||||
ignored: number;
|
||||
}
|
||||
|
||||
|
||||
const ERROR_MESSAGE = {
|
||||
INVALID_SEVERITY_LEVEL: 'Invalid severity level; accepted values: error or warn',
|
||||
@@ -115,7 +121,7 @@ export function formatProblems(
|
||||
problems: problems.map((p) => {
|
||||
let problem = {
|
||||
...p,
|
||||
location: p.location.map((location) => ({
|
||||
location: p.location.map((location: any) => ({
|
||||
...location,
|
||||
source: {
|
||||
ref: path.relative(cwd, location.source.absoluteRef),
|
||||
21
packages/core/src/index.ts
Normal file
21
packages/core/src/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export type { BundleOutputFormat } from './utils';
|
||||
export { Oas3Types } from './types/oas3';
|
||||
export { Oas2Types } from './types/oas2';
|
||||
export { Oas3Definition, Oas3Components, Oas3PathItem, Oas3Paths, Oas3ComponentName, Oas3Schema } from './typings/openapi';
|
||||
export { Oas2Definition } from './typings/swagger';
|
||||
export { StatsAccumulator, StatsName } from './typings/common';
|
||||
export { normalizeTypes } from './types';
|
||||
export { Stats } from './rules/other/stats';
|
||||
|
||||
export { loadConfig, Config, LintConfig } from './config/config';
|
||||
export { RedoclyClient } from './redocly';
|
||||
export { BaseResolver, Document, resolveDocument, ResolveError, YamlParseError } from './resolve';
|
||||
export { unescapePointer } from './ref-utils';
|
||||
export { detectOpenAPI, OasMajorVersion, openAPIMajor } from './validate';
|
||||
export { normalizeVisitors } from './visitors';
|
||||
export { WalkContext, walkDocument, NormalizedProblem, ProblemSeverity, LineColLocationObject, LocationObject, Loc } from './walk';
|
||||
|
||||
export { formatProblems, OutputFormat } from './format/format';
|
||||
|
||||
export { validate } from './validate';
|
||||
export { bundle } from './bundle';
|
||||
@@ -2,7 +2,6 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { yellow, red, green, gray } from 'colorette';
|
||||
|
||||
import { query } from './query';
|
||||
|
||||
const TOKEN_FILENAME = '.redocly-config.json';
|
||||
@@ -79,11 +79,3 @@ export function isMappingRef(mapping: string) {
|
||||
mapping.indexOf('/') > -1
|
||||
);
|
||||
}
|
||||
|
||||
export function pathToFilename(path: string) {
|
||||
return path
|
||||
.replace(/~1/g, '/')
|
||||
.replace(/~0/g, '~')
|
||||
.substring(1)
|
||||
.replace(/\//g, '@');
|
||||
}
|
||||
@@ -3,7 +3,6 @@ import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
import * as yaml from 'js-yaml';
|
||||
const { readFile } = fs.promises;
|
||||
|
||||
import { OasRef } from './typings/openapi';
|
||||
import { isRef, joinPointer, escapePointer, parseRef, isAbsoluteUrl } from './ref-utils';
|
||||
import { safeLoad as safeLoadToAst, YAMLNode, Kind } from 'yaml-ast-parser';
|
||||
@@ -5,7 +5,7 @@ import { validateDocument } from '../../validate';
|
||||
import { LintConfig } from '../..';
|
||||
import { BaseResolver } from '../../resolve';
|
||||
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
|
||||
describe('oas3 boolean-parameter-prefixes', () => {
|
||||
it('should report on unresolved $ref', async () => {
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-ignore
|
||||
import * as Ajv from '@redocly/ajv';
|
||||
// import * as jsonSpecV4 from 'ajv/lib/refs/json-schema-draft-04.json';
|
||||
// import { OasVersion } from '../validate';
|
||||
@@ -71,7 +72,7 @@ export function validateJsonSchema(
|
||||
let suggest =
|
||||
error.keyword === 'enum' ? (error.params as Ajv.EnumParams).allowedValues : undefined;
|
||||
if (suggest) {
|
||||
message += ` ${suggest.map((e) => `"${e}"`).join(', ')}`;
|
||||
message += ` ${suggest.map((e: any) => `"${e}"`).join(', ')}`;
|
||||
}
|
||||
|
||||
if (error.keyword === 'type') {
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as oas3 from './oas3/index';
|
||||
import * as oas2 from './oas2/index';
|
||||
import { CustomRulesConfig } from '../index';
|
||||
import { CustomRulesConfig } from '../config/config';
|
||||
|
||||
export const rules: CustomRulesConfig = {
|
||||
oas3: oas3.rules,
|
||||
@@ -1,7 +1,7 @@
|
||||
import { outdent } from 'outdent';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 info-license', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 license-url', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('no-ambiguous-paths', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 typed enum', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('no-identical-paths', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('no-path-trailing-slash', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-2xx-response', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-operationId-unique', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-operationId-url-safe', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-parameters-unique', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-security-defined', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 operation-singular-tag', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Common path-http-verbs-order', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 path-not-include-query', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 path-params-defined', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 paths-kebab-case', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 tag-description', () => {
|
||||
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
|
||||
import { LintConfig } from '../../../config/config';
|
||||
|
||||
import { validateDocument } from '../../../validate';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../__tests__/utils';
|
||||
import { parseYamlToDocument, replaceSourceWithRef } from '../../../../__tests__/utils';
|
||||
import { BaseResolver } from '../../../resolve';
|
||||
|
||||
describe('Oas3 tags-alphabetical', () => {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user