Skip to content

Commit

Permalink
refactor: update x-sdk-operations schema and move it to a file
Browse files Browse the repository at this point in the history
  • Loading branch information
Barrett Schonefeld committed Apr 1, 2021
1 parent 6a49b38 commit 94bc958
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 126 deletions.
2 changes: 1 addition & 1 deletion docs/spectral-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ responses:

## ibm-sdk-operations

Validates the structure of the `x-sdk-operations` object.
Validates the structure of the `x-sdk-operations` object using [this JSON Schema document](/src/spectral/schemas/x-sdk-operations.json).

**Default Severity**: warn

Expand Down
8 changes: 5 additions & 3 deletions src/spectral/rulesets/.defaultsForSpectral.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extends: spectral:oas
functionsDir: './ibm-oas'
functions:
- error-response-schema
- ibm-sdk-operations
- json-schema-validation
- response-example-provided
rules:

Expand Down Expand Up @@ -124,12 +124,14 @@ rules:
# custom Spectral rule to ensure valid x-sdk-operations schema
ibm-sdk-operations:
message: "{{error}}"
given: $.paths[*][*][x-sdk-operations]
given: $.
severity: warn
formats: ["oas3"]
resolved: true
then:
function: ibm-sdk-operations
function: json-schema-validation
functionOptions:
schemaKey: 'ibm/schemas/x-sdk-operations'
# custom Spectral rule to ensure response example provided
response-example-provided:
message: "{{error}}"
Expand Down
118 changes: 0 additions & 118 deletions src/spectral/rulesets/ibm-oas/ibm-sdk-operations.js

This file was deleted.

39 changes: 39 additions & 0 deletions src/spectral/rulesets/ibm-oas/json-schema-validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const AJV = require('ajv');
const ajv = new AJV({ allErrors: true, jsonPointers: true });
const { STATIC_ASSETS } = require('@stoplight/spectral/dist/assets');

// performs JSON Schema validation on the given object
// expects `schemaKey` options with the key to retrieve the schema
module.exports = function(obj, opts, paths) {
const errors = [];
const rootPath = paths.target !== void 0 ? paths.target : paths.given;
const jsonSchema = JSON.parse(STATIC_ASSETS[opts.schemaKey]);
const validate = ajv.compile(jsonSchema);
if (!ajv.validate(jsonSchema, obj)) {
return formatAJVErrors(validate.errors, rootPath);
}
return errors;
};

function formatAJVErrors(errors, rootPath) {
const errorList = [];
errors.forEach(function(err) {
errorList.push({
message: err.message,
path: getErrPath(err, rootPath)
});
});
return errorList;
}

function getErrPath(err, rootPath) {
const relativePath = err.dataPath.split('/');
if (relativePath.length > 1) {
const strippedPath = relativePath.splice(
relativePath.indexOf('') + 1,
relativePath.length
);
return [...rootPath, ...strippedPath];
}
return rootPath;
}
116 changes: 116 additions & 0 deletions src/spectral/rulesets/schemas/x-sdk-operations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "IBM SDK Operations Extension",
"description": "sdk operations extension schema",
"type": "object",
"properties": {
"paths": {
"$ref": "#/definitions/Paths"
}
},
"definitions": {
"Paths": {
"type": "object",
"patternProperties": {
".*": {
"$ref": "#/definitions/PathItem"
}
}
},
"PathItem": {
"type": "object",
"patternProperties": {
"^(get|put|post|delete|options|head|patch|trace)$": {
"$ref": "#/definitions/Operation"
}
}
},
"Operation": {
"type": "object",
"properties": {
"x-sdk-operations": {
"$ref": "#/definitions/SdkOperations"
}
}
},
"SdkOperations": {
"type": "object",
"properties": {
"request-examples": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/x-sdk-request-examples-array"
}
}
},
"additionalProperties": false
},
"x-sdk-request-examples-array": {
"type": "array",
"items": {
"$ref": "#/definitions/x-sdk-request-example"
}
},
"x-sdk-request-example": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name or title of the example. In documentation it should appear as a header above the example."
},
"contentType": {
"type": "array",
"items": {
"type": "string",
"description": "The media type of the response in this example."
}
},
"example": {
"type": "array",
"description": "An array of code or text elements that make up the example",
"items": {
"$ref": "#/definitions/x-sdk-request-example-element"
}
},
"response": {},
"description": {
"type": "string"
}
},
"required": [
"name",
"example"
],
"additionalProperties": false
},
"x-sdk-request-example-element": {
"type": "object",
"description": "An element of the request example.",
"properties": {
"name": {
"type": "string",
"description": "The name or title of the example element. In documentation it should appear as a header above the example element."
},
"type": {
"type": "string",
"description": "The element type indicates the type of content in the element. `text` elements contain a textual description or explanation, possibly using markdown for rich text elements. `code` elements contain code appropriate for the language of the request example. `code` elements will be presented in a `<pre><code>` block in documentation and should contain no markup or escapes other than escapes for quote and backslash (required for JSON).",
"enum": [
"text",
"code"
]
},
"source": {
"type": "array",
"items": {
"type": "string"
},
"description": "Content of the example element as an array of strings. The content is formed by simple concatenation of the array elements."
}
},
"required": [
"type",
"source"
]
}
}
}
18 changes: 14 additions & 4 deletions src/spectral/utils/spectral-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,21 @@ function setupStaticAssets(staticAssets, defaultSpectralRulesetURI) {
const content = fs.readFileSync(defaultSpectralRulesetURI, 'utf8');
staticAssets['ibm:oas'] = content;

const parentDirectory = path.parse(defaultSpectralRulesetURI).dir;

// register schemas
const baseKey = 'ibm/schemas';
const schemaDirURI = path.join(parentDirectory, 'schemas');
fs.readdirSync(schemaDirURI).forEach(function(jsonSchemaFile) {
const schemaKey = path.join(baseKey, path.parse(jsonSchemaFile).name);
staticAssets[schemaKey] = fs.readFileSync(
path.join(schemaDirURI, jsonSchemaFile),
'utf8'
);
});

// register custom functions
const customFunctionsDirURI = path.join(
path.parse(defaultSpectralRulesetURI).dir,
'ibm-oas'
);
const customFunctionsDirURI = path.join(parentDirectory, 'ibm-oas');
fs.readdirSync(customFunctionsDirURI).forEach(function(customFunctionFile) {
const customFunctionURI = path.join(
customFunctionsDirURI,
Expand Down

0 comments on commit 94bc958

Please sign in to comment.