azure-api-style-guide/functions/lro-response-schema.js

105 строки
3.6 KiB
JavaScript

// Check conformance to Azure guidelines for 202 responses:
// - A 202 response should have a response body schema
// - The response body schema should contain `id`, `status`, and `error` properties.
// - The `id`, `status`, and `error` properties should be required.
// - The `id` property should be type: string.
// - The `status` property should be type: string and enum with values:
// - "Running", "Succeeded", "Failed", "Cancelled".
// - The `error` property should be type: object and not required.
// Rule target is a 202 response
module.exports = (lroResponse, _opts, context) => {
// defensive programming - make sure we have an object
if (lroResponse === null || typeof lroResponse !== 'object') {
return [];
}
const lroResponseSchema = lroResponse.schema;
// A 202 response should include a schema for the operation status monitor.
if (!lroResponseSchema) {
return [{
message: 'A 202 response should include a schema for the operation status monitor.',
path: context.path || [],
}];
}
const path = [...(context.path || []), 'schema'];
const errors = [];
// - The `id`, `status`, and `error` properties should be required.
const requiredProperties = new Set(lroResponseSchema.required || []);
const checkRequiredProperty = (prop) => {
if (!requiredProperties.has(prop)) {
errors.push({
message: `\`${prop}\` property in LRO response should be required`,
path: [...path, 'required'],
});
}
};
// Check id property
if (lroResponseSchema.properties && 'id' in lroResponseSchema.properties) {
if (lroResponseSchema.properties.id.type !== 'string') {
errors.push({
message: '\'id\' property in LRO response should be type: string',
path: [...path, 'properties', 'id', 'type'],
});
}
checkRequiredProperty('id');
} else {
errors.push({
message: 'LRO response should contain top-level property `id`',
path: [...path, 'properties'],
});
}
// Check status property
if (lroResponseSchema.properties && 'status' in lroResponseSchema.properties) {
if (lroResponseSchema.properties.status.type !== 'string') {
errors.push({
message: '`status` property in LRO response should be type: string',
path: [...path, 'properties', 'status', 'type'],
});
}
checkRequiredProperty('status');
const statusValues = new Set(lroResponseSchema.properties.status.enum || []);
const requiredStatusValues = ['Running', 'Succeeded', 'Failed', 'Canceled'];
if (!requiredStatusValues.every((value) => statusValues.has(value))) {
errors.push({
message: `'status' property enum in LRO response should contain values: ${requiredStatusValues.join(', ')}`,
path: [...path, 'properties', 'status', 'enum'],
});
}
} else {
errors.push({
message: 'LRO response should contain top-level property `status`',
path: [...path, 'properties'],
});
}
// Check error property
if (lroResponseSchema.properties && 'error' in lroResponseSchema.properties) {
if (lroResponseSchema.properties.error.type !== 'object') {
errors.push({
message: '`error` property in LRO response should be type: object',
path: [...path, 'properties', 'error', 'type'],
});
}
if (requiredProperties.has('error')) {
errors.push({
message: '`error` property in LRO response should not be required',
path: [...path, 'required'],
});
}
} else {
errors.push({
message: 'LRO response should contain top-level property `error`',
path: [...path, 'properties'],
});
}
return errors;
};