UNPKG

@openactive/rpde-validator

Version:

A library to walk and validate an RPDE feed

206 lines (198 loc) • 6.63 kB
const _ = require('lodash'); const { ValidationErrorCategory, ValidationErrorSeverity, } = require('@openactive/data-model-validator'); const RpdeRule = require('../../rpde-rule'); const RpdeErrorType = require('../../errors/rpde-error-type'); const RequiredPropertyValuesRule = class extends RpdeRule { constructor() { super(); this.meta = { name: 'RequiredPropertyValuesRule', description: 'Validates that the feed properties conform to the correct format', tests: { state: { description: 'Raises a failure if the `state` property isn\'t one of "updated" or "deleted"', message: 'The [`state` property](https://www.openactive.io/realtime-paged-data-exchange/#-state-) must be of value "updated" or "deleted", but was found to be different in {{count}} items in the feed.', sampleValues: { count: 23, }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, id: { description: 'Raises a failure if the `id` property isn\'t a string or an integer in any item', message: 'The [`id` property](https://www.openactive.io/realtime-paged-data-exchange/#-id-) must be a string, but was found to be different in {{count}} items in the feed.', sampleValues: { count: 23, }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, kind: { description: 'Raises a failure if the `kind` property isn\'t a string in any item', message: 'The [`kind` property](https://www.openactive.io/realtime-paged-data-exchange/#-kind-) must be a string, but was found to be different in {{count}} items in the feed.', sampleValues: { count: 23, }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, data: { description: 'Raises a failure if the `data` property isn\'t an object in any item', message: 'The [`data` property](https://www.openactive.io/realtime-paged-data-exchange/#-data-) must be an object, but was found to be different in {{count}} items in the feed.', sampleValues: { count: 23, }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, item: { description: 'Raises a failure if an item is found that isn\'t an object', message: 'Items must be objects, but were found to be different in {{count}} items in the feed.', sampleValues: { count: 23, }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, items: { description: 'Raises a failure if the items property isn\'t an array', message: 'Required property [`items`](https://www.openactive.io/realtime-paged-data-exchange/#-response-) must be an array, but was found to be "{{type}}".', sampleValues: { type: 'string', }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, license: { description: 'Raises a failure if the license property isn\'t a string', message: 'Required property [`license`](https://www.openactive.io/realtime-paged-data-exchange/#-response-) must be a string, but was found to be "{{type}}".', sampleValues: { type: 'object', }, category: ValidationErrorCategory.CONFORMANCE, severity: ValidationErrorSeverity.FAILURE, type: RpdeErrorType.INVALID_FORMAT, }, }, }; } validate(node) { if ( typeof node.data.items !== 'undefined' && ( typeof node.data.items !== 'object' || !(node.data.items instanceof Array) ) ) { // Items must be an array node.log.addPageError( node.url, this.createError( 'items', { value: node.data, url: node.url, }, { type: typeof node.data.items, }, ), ); } if ( typeof node.data.license !== 'undefined' && typeof node.data.license !== 'string' ) { // License must be a string node.log.addPageError( node.url, this.createError( 'license', { value: node.data, url: node.url, }, { type: typeof node.data.license, }, ), ); } const invalidProps = { state: 0, kind: 0, item: 0, id: 0, data: 0, }; if (node.data.items instanceof Array) { for (const item of node.data.items) { if ( !_.isPlainObject(item) ) { invalidProps.item += 1; } if ( typeof item.state !== 'undefined' && ( typeof item.state !== 'string' || ( item.state !== 'deleted' && item.state !== 'updated' ) ) ) { invalidProps.state += 1; } if ( typeof item.kind !== 'undefined' && typeof item.kind !== 'string' ) { invalidProps.kind += 1; } if ( typeof item.id !== 'undefined' && typeof item.id !== 'string' && typeof item.id !== 'number' ) { invalidProps.id += 1; } if ( typeof item.data !== 'undefined' && !_.isPlainObject(item.data) ) { invalidProps.data += 1; } } } for (const prop in invalidProps) { if ( Object.prototype.hasOwnProperty.call(invalidProps, prop) && invalidProps[prop] > 0 ) { node.log.addPageError( node.url, this.createError( prop, { value: node.data, url: node.url, }, { count: invalidProps[prop], }, ), ); } } } }; module.exports = RequiredPropertyValuesRule;