Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feat/core/json-rul…
Browse files Browse the repository at this point in the history
…eset-validation
  • Loading branch information
P0lip committed Mar 7, 2022
2 parents 885fa2c + dda11ef commit e08ba8b
Show file tree
Hide file tree
Showing 63 changed files with 1,902 additions and 1,890 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1,3 +1,4 @@
**/__fixtures__/**
/test-harness/**/*.yaml
/packages/*/dist
/packages/*/CHANGELOG.md
6 changes: 4 additions & 2 deletions .eslintrc
Expand Up @@ -84,10 +84,12 @@

{
"files": [
"src/**/__tests__/**/*.jest.test.{ts,js}"
"src/**/__tests__/**/*.jest.test.{ts,js}",
"__mocks__/**/*.{ts,js}"
],
"env": {
"jest": true
"jest": true,
"node": true
}
},

Expand Down
18 changes: 13 additions & 5 deletions README.md
Expand Up @@ -34,20 +34,28 @@ Find more [installation methods](https://meta.stoplight.io/docs/spectral/docs/ge

**Create a Ruleset**

Spectral, being a generic YAML/JSON linter, needs a ruleset in order to be able to lint files.
You can learn more about the rulesets [here](./docs/getting-started/3-rulesets.md).
Spectral, being a generic YAML/JSON linter, needs a ruleset to lint files. There are two ways to get a ruleset:

If you intend to lint an OpenAPI or AsyncAPI document, we have a few predefined rulesets you can extend to get Spectral up and running.
To reference them, you can run the following command:
1. Run this command to get our predefined rulesets based on OpenAPI or AsyncAPI:

```bash
printf '{\n "extends": ["spectral:oas", "spectral:asyncapi"]\n}\n' > .spectral.json
```

2. Create your [own ruleset](./docs/getting-started/3-rulesets.md).

**Lint**

Use this command to lint with the predefined ruleset or a ruleset stored in the same directory as your API document:

```bash
spectral lint myapifile.yaml
```

Use this command to lint with a custom ruleset or one that is located in a different directory than your API document:

```bash
spectral lint petstore.yaml
spectral lint myapifile.yaml --ruleset myruleset.json
```

## 📖 Documentation
Expand Down
Empty file added __karma__/perf_hooks.js
Empty file.
1 change: 0 additions & 1 deletion __karma__/process.js

This file was deleted.

7 changes: 0 additions & 7 deletions __mocks__/nanoid/non-secure.ts

This file was deleted.

15 changes: 15 additions & 0 deletions __mocks__/process.js
@@ -0,0 +1,15 @@
module.exports.exit = jest.fn();
module.exports.cwd = jest.fn();
module.exports.on = jest.fn();

module.exports.stdin = {
fd: 0,
isTTY: true,
};
module.exports.stdout = {
write: jest.fn(),
};

module.exports.stderr = {
write: jest.fn(),
};
2 changes: 1 addition & 1 deletion docs/getting-started/3-rulesets.md
Expand Up @@ -66,7 +66,7 @@ Extends can reference any [distributed ruleset](../guides/7-sharing-rulesets.md)
extends:
- ./config/spectral.json
- https://example.org/api/style.yaml
- some-npm-module
- some-npm-module # note that this would be treated as any other npm package, therefore it has to be placed under node_modules and have a valid package.json.
```

The `extends` keyword can be combined with extra rules in order to extend and override rulesets. Learn more about that in [custom rulesets](../guides/4-custom-rulesets.md).
Expand Down
8 changes: 7 additions & 1 deletion docs/guides/2-cli.md
@@ -1,11 +1,17 @@
# Spectral CLI

[Once installed](../getting-started/2-installation.md), Spectral can be run via the command-line:
[Once Spectral is installed](../getting-started/2-installation.md) and [you have a ruleset](../../README.md#installation-and-usage), run Spectral via the command-line:

```bash
spectral lint petstore.yaml
```

Use this command to lint with a custom ruleset or one that is located in a different directory than your API document:

```bash
spectral lint petstore.yaml --ruleset myruleset.json
```

You can lint multiple files at the same time by passing on multiple arguments:

```bash
Expand Down
60 changes: 50 additions & 10 deletions docs/guides/3-javascript.md
Expand Up @@ -53,22 +53,62 @@ Find out how to add formats, rules and functions below.

## Loading Rulesets

Spectral comes with some rulesets that are very specific to OpenAPI v2/v3, and they can be loaded using `Spectral.loadRuleset()`.
Spectral comes with some rulesets that are very specific to OpenAPI v2/v3, and they can be set using `Spectral.setRuleset()`.

```js
const { Spectral } = require("@stoplight/spectral-core");
const ruleset = require("./my-ruleset"); // if you use a YAML/JSON ruleset, make sure to use @stoplight/spectral-ruleset-migrator first.

const myOpenApiDocument = `
openapi: 3.0.0
# here goes the rest of document
`;
const ruleset = require("./my-ruleset"); // this works only for JS ruleset, look at the section below to learn how to load a YAML/JSON ruleset

const spectral = new Spectral();
spectral.setRuleset(ruleset);
spectral.run(myOpenApiDocument).then(results => {
console.log("here are the results", results);
});
// lint
```

### Loading YAML/JSON rulesets

#### Node.js

```js
const path = require("path");
const fs = require("fs");

const { Spectral } = require("@stoplight/spectral-core");
const { fetch } = require("@stoplight/spectral-runtime"); // can also use isomorphic-fetch, etc.. If you ruleset does not reference any external assets, you can provide some stub instead.
const { bundleAndLoadRuleset } = require("@stoplight/spectral-ruleset-bundler/with-loader");
// const { commonjs } = require("@stoplight/spectral-ruleset-bundler/plugins/commonjs"); needed if you want to use CommonJS

const rulesetFilepath = path.join(__dirname, ".spectral.yaml");

const spectral = new Spectral();
s.setRuleset(await bundleAndLoadRuleset(rulesetFilepath, { fs, fetch }));
// or, if you use module.exports (CommonJS) s.setRuleset(await bundleAndLoadRuleset(rulesetFilepath, { fs, fetch }), [commonjs()]);
```

#### Browser

```js
const { Spectral } = require("@stoplight/spectral-core");
const { bundleAndLoadRuleset } = require("@stoplight/spectral-ruleset-bundler/with-loader");
// const { commonjs } = require("@stoplight/spectral-ruleset-bundler/plugins/commonjs"); needed if you want to use CommonJS

const myRuleset = `extends: spectral:oas
rules: {}`;

const fs = {
promises: {
async readFile(filepath) {
if (filepath === "/.spectral.yaml") {
return myRuleset;
}

throw new Error(`Could not read ${filepath}`);
},
},
};

const spectral = new Spectral();
s.setRuleset(await bundleAndLoadRuleset("/.spectral.yaml", { fs, fetch }));
// or, if you use module.exports (CommonJS) s.setRuleset(await bundleAndLoadRuleset(rulesetFilepath, { fs, fetch }), [commonjs()]);
```

## Advanced
Expand Down
49 changes: 32 additions & 17 deletions docs/guides/4-custom-rulesets.md
Expand Up @@ -402,38 +402,53 @@ Rulesets can then reference aliases in the [given](#given) keyword, either in fu

Previously Spectral supported exceptions, which were limited in their ability to target particular rules on specific files or parts of files, or changing parts of a rule. Overrides is the much more powerful version of exceptions, with the ability to customize ruleset usage for different files and projects without having to duplicate any rules.

Overrides can be used to:
Overrides can be used to apply rulesets on:

- Override rulesets to apply on particular files/folders `files: ['schemas/**/*.draft7.json']`
- Override rulesets to apply on particular JSONPath's `files: ['**#/components/schemas/Item']`
- Override rulesets to apply on particular formats `formats: [jsonSchemaDraft7]`
- Particular formats `formats: [jsonSchemaDraft7]`
- Particular files/folders `files: ['schemas/**/*.draft7.json']`
- Particular elements of files `files: ['**#/components/schemas/Item']`
- Override particular rules

**Example**

```yaml
overrides:
formats:
- json-schema-draft7
files:
- schemas/**/*.draft7.json
rules:
valid-number-validation:
given:
- $..exclusiveMinimum
- $..exclusiveMaximum
then:
function: schema
functionOptions:
type: number
```

To apply an override to particular elements of files, combine a glob for a filepath
with a [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) after the anchor, i.e.:

```yaml
overrides:
- files:
- schemas/**/*.draft7.json
formats:
- json-schema-draft7
- "legacy/**/*.oas.json#/paths"
rules:
valid-number-validation:
given:
- $..exclusiveMinimum
- $..exclusiveMaximum
then:
function: schema
functionOptions:
type: number
some-inherited-rule: "off"
```

One can also combine a glob for a filepath with a JSONPath after the anchor, i.e.:
JSON Pointers have a different syntax than JSON Paths used in the `given` component of a rule.
In JSON Pointers, path components are prefixed with a "/" and then concatenated to form the pointer.
Since "/" has a special meaning in JSON pointer, it must be encoded as "~1" when it appears in a component, and "~" must be encoded as "~0".

You can test JSON Pointer expressions in the [JSON Query online evaluator](https://www.jsonquerytool.com/) by choosing "JSONPointer" as the Transform.

```yaml
overrides:
- files:
- "legacy/**/*.oas.json#/paths"
- "legacy/**/*.oas.json#/paths/~1Pets~1{petId}/get/parameters/0"
rules:
some-inherited-rule: "off"
```
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/7-sharing-rulesets.md
Expand Up @@ -14,7 +14,7 @@ Or mix and match!
extends:
- ./config/spectral.json
- https://example.org/api/style.yaml
- some-npm-module
- some-npm-module # note that this would be treated as any other npm package, therefore it has to live under node_modules, and have a valid package.json.
```

There are various pros and cons to each approach, so see what is right for you.
Expand Down Expand Up @@ -109,7 +109,7 @@ module.exports = function (targetVal, { min }) {
};
```

Developers wanting to pull in your ruleset can just reference the module name in `extends`:
Developers wanting to pull in your ruleset can just install the package using yarn or npm and reference the module name in `extends`:

```yaml
extends:
Expand All @@ -126,7 +126,7 @@ Pegging a ruleset on given version is possible through a `package.json`:
}
```

Or through the use of CDNs for NPM repository, such as [unpkg.com](https://unpkg.com/):
If you Spectral in a browser or don't want to install the package, you can also reference that package through the use of CDNs for NPM repository, such as [unpkg.com](https://unpkg.com/):

```yaml
extends:
Expand Down
5 changes: 3 additions & 2 deletions karma.conf.ts
Expand Up @@ -17,7 +17,7 @@ module.exports = (config: Config): void => {
files: ['./__karma__/jest.ts', 'packages/*/src/**/*.ts'],

// list of files / patterns to exclude
exclude: ['packages/cli/**', '**/*.jest.test.ts'],
exclude: ['packages/cli/**', 'packages/ruleset-bundler/src/plugins/commonjs.ts', '**/*.jest.test.ts'],

// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
Expand All @@ -40,7 +40,8 @@ module.exports = (config: Config): void => {
'nimma/legacy': require.resolve('./node_modules/nimma/dist/legacy/cjs/index.js'),
'node-fetch': require.resolve('./__karma__/fetch'),
fs: require.resolve('./__karma__/fs'),
process: require.resolve('./__karma__/process'),
process: require.resolve('./__mocks__/process'),
perf_hooks: require.resolve('./__karma__/perf_hooks'),
fsevents: require.resolve('./__karma__/fsevents'),
},
},
Expand Down
9 changes: 3 additions & 6 deletions package.json
Expand Up @@ -30,15 +30,15 @@
"lint": "yarn lint.prettier && yarn lint.eslint",
"lint.fix": "yarn lint.prettier --write && yarn lint.eslint --fix",
"lint.eslint": "eslint --cache --cache-location .cache/.eslintcache --ext=.js,.mjs,.ts packages test-harness",
"lint.prettier": "prettier --ignore-path .eslintignore --ignore-unknown --check packages/core/src/ruleset/meta/*.json packages/rulesets/src/{asyncapi,oas}/schemas/*.json packages/*/CHANGELOG.md docs/**/*.md README.md",
"lint.prettier": "prettier --ignore-path .eslintignore --ignore-unknown --check packages/core/src/ruleset/meta/*.json packages/rulesets/src/{asyncapi,oas}/schemas/*.json docs/**/*.md README.md",
"pretest": "yarn workspace @stoplight/spectral-ruleset-migrator pretest",
"test": "yarn pretest && yarn test.karma && yarn test.jest",
"test.harness": "jest -c ./test-harness/jest.config.js",
"test.jest": "jest --silent --cacheDirectory=.cache/.jest",
"test.karma": "karma start",
"prepare": "husky install",
"prerelease": "patch-package",
"release": "yarn prerelease && HUSKY=0 yarn workspaces foreach run release"
"release": "yarn prerelease && yarn workspaces foreach run release"
},
"workspaces": {
"packages": [
Expand Down Expand Up @@ -100,7 +100,7 @@
"node-powershell": "^4.0.0",
"patch-package": "^6.4.7",
"prettier": "^2.4.1",
"semantic-release": "^19.0.2",
"semantic-release": "^18.0.1",
"semantic-release-monorepo": "^7.0.5",
"ts-jest": "^27.0.7",
"ts-node": "^10.4.0",
Expand All @@ -110,9 +110,6 @@
"*.{ts,js}": [
"eslint --fix --cache --cache-location .cache/.eslintcache"
],
"packages/*/CHANGELOG.md": [
"prettier --write"
],
"docs/**/*.md": [
"prettier --ignore-path .eslintignore --write"
],
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/CHANGELOG.md
@@ -1,3 +1,10 @@
# [@stoplight/spectral-cli-v6.3.0](https://github.com/stoplightio/spectral/compare/@stoplight/spectral-cli-v6.2.1...@stoplight/spectral-cli-v6.3.0) (2022-03-03)


### Features

* **cli:** improve error logging ([#2071](https://github.com/stoplightio/spectral/issues/2071)) ([b194368](https://github.com/stoplightio/spectral/commit/b194368164d92dce31b7ceba84ccc94fbe51f979))

# [@stoplight/spectral-cli-v6.2.1](https://github.com/stoplightio/spectral/compare/@stoplight/spectral-cli-v6.2.0...@stoplight/spectral-cli-v6.2.1) (2022-02-08)

### Bug Fixes
Expand Down
9 changes: 7 additions & 2 deletions packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@stoplight/spectral-cli",
"version": "6.2.1",
"version": "6.3.0",
"homepage": "https://github.com/stoplightio/spectral",
"bugs": "https://github.com/stoplightio/spectral/issues",
"author": "Stoplight <support@stoplight.io>",
Expand Down Expand Up @@ -51,15 +51,18 @@
"lodash": "~4.17.21",
"pony-cause": "^1.0.0",
"proxy-agent": "5.0.0",
"stacktracey": "^2.1.7",
"strip-ansi": "6.0",
"text-table": "0.2",
"tslib": "^2.3.0",
"yargs": "17.3.1"
},
"devDependencies": {
"@types/es-aggregate-error": "^1.0.2",
"@types/xml2js": "^0.4.9",
"@types/yargs": "^17.0.8",
"copyfiles": "^2.4.1",
"es-aggregate-error": "^1.0.7",
"jest-when": "^3.4.2",
"nock": "^13.1.3",
"node-html-parser": "^4.1.5",
Expand All @@ -73,7 +76,9 @@
],
"assets": [
"./dist/**/*.json",
"./dist/**/*.html"
"./dist/**/*.html",
"../*/dist/**/*.js.map",
"../*/src/**/*.ts"
]
}
}

0 comments on commit e08ba8b

Please sign in to comment.