Skip to content

Commit

Permalink
Code documentation in jsdoc (#163)
Browse files Browse the repository at this point in the history
* Documention of standalone functions

* Documentation of class methods

* Documentation of the CLI

* Formatting to CLI documentation

* Documentation of validate.js

* Documentation of check-systems
  • Loading branch information
richfab authored Dec 20, 2023
1 parent d81912f commit 1987efe
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 0 deletions.
6 changes: 6 additions & 0 deletions check-systems/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ if (!process.argv[2]) {
process.exit(1)
}

/**
* This function reads the local version of the file systems.csv (must be downloaded manually first),
* validates every system in the file and writes the validation report locally.
* @param {*} line - A row in the file systems.csv.
* @returns
*/
function checkGBFS(line) {
const gbfs = new gbfsValidator(line[5])

Expand Down
34 changes: 34 additions & 0 deletions gbfs-validator/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,43 @@ const fsPath = require('path')
const GBFS = require('./gbfs')
const pjson = require('./package.json')

/**
* This async function returns an Object that contains the FileValidationResult of all the files from a GBFS feed.
* @returns {Object}
*/
getFeedValidationReport = async (url) => {
const gbfs = new GBFS(url)
return gbfs.validation()
}

/**
* This function returns true if exit override param is set to 'true' to allow program to exit simplifying unit testing.
* @returns {boolean}
*/
const isExitOverrided = () => (process.env.EXIT_OVERRIDE === 'true')

/**
* This function returns true if print report option is set to 'true'.
* @param {Object} options - The CLI commander options.
* @returns {boolean}
*/
const printingReport = (options) => (options.printReport === 'yes')

/**
* This function exits the process
* @param {number} code - The exit process code.
*/
const exitProcess = (code) => {
if (!isExitOverrided && code === 1) {
process.exit(code)
}
process.exit(0)
}

/**
* This function defines the options that can be passed by the user to the CLI,
* its version and the usage description in the first line of the help.
*/
parseOptions = () => {
commander
.version(pjson.version, '-v, --version')
Expand All @@ -40,6 +61,11 @@ parseOptions = () => {
return commander.parse(process.argv).opts()
}

/**
* This function writes the validation report to a local file.
* @param {*} report - The validation report.
* @param {*} filePath - The path to the local file to write.
*/
const saveReport = (report, filePath) => {
const dirname = fsPath.dirname(filePath);
if (!fs.existsSync(dirname)) {
Expand All @@ -48,6 +74,10 @@ const saveReport = (report, filePath) => {
fs.writeFileSync(filePath, JSON.stringify(report))
}

/**
* This asyn function validates the feed and saves the report if requested in the options
* @param {*} options - The options passed by the user to the CLI.
*/
const processFeedValidation = async (options) => {
if (options.verbose) {
console.log("Started GBFS validation with options: \n " + inspect(options, { depth: null, colors: true }))
Expand All @@ -66,6 +96,10 @@ const processFeedValidation = async (options) => {
}
}

/**
* This function checks that the options passed by the user are valid and
* calls the processFeedValidation() function.
*/
const validate = () => {
const options = parseOptions()
if (!options.saveReport && !printingReport(options)) {
Expand Down
128 changes: 128 additions & 0 deletions gbfs-validator/gbfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@ const validatorVersion = process.env.COMMIT_REF
? process.env.COMMIT_REF.substring(0, 7)
: require('./package.json').version

/**
* @typedef {{
* languages: Object,
* file: string,
* url: string,
* required: boolean,
* recommended: boolean,
* exists: boolean,
* hasErrors: boolean,
* errors: Object,
* schema: Object,
* version: string
* }} FileValidationResult
*/

/**
* @typedef {{
* vehicle_type_id: string,
* form_factor: string,
* propulsion_type: string
* }} VehicleType
*/

/**
* This function returns true if the file from a GBFS feed has errors or if the file is required and missing.
* @param {Object} data - The body of a file from a GBFS feed.
* @param {boolean} required - True if the file is required.
* @returns {boolean}
*/
function hasErrors(data, required) {
let hasError = false

Expand All @@ -22,6 +51,11 @@ function hasErrors(data, required) {
return hasError
}

/**
* This function returns the number of errors in a file of a GBFS feed.
* @param {FileValidationResult} file - The validation result of a file from a GBFS feed.
* @returns {number}
*/
function countErrors(file) {
let count = 0

Expand All @@ -46,6 +80,13 @@ function countErrors(file) {
return count
}

/**
* This function returns a JSON Patch to modify a GBFS JSON schema.
* @param {string} version - The version of the GBFS feed.
* @param {string} partial - The path to the JSON Patch file.
* @param {Object} data - The params for generating the JSON Patch.
* @returns {Object} - A JSON Patch.
*/
function getPartialSchema(version, partial, data = {}) {
let partialSchema

Expand All @@ -60,6 +101,11 @@ function getPartialSchema(version, partial, data = {}) {
return partialSchema
}

/**
* This function returns an array of vehicle types defined in vehicle_types.json.
* @param {Object} param0 - The vehicle_types.json file.
* @returns {VehicleType[]}
*/
function getVehicleTypes({ body }) {
if (Array.isArray(body)) {
return body.reduce((acc, lang) => {
Expand All @@ -84,6 +130,11 @@ function getVehicleTypes({ body }) {
}
}

/**
* This function returns an array of pricing plans defined in system_pricing_plans.json.
* @param {*} param0 - The system_pricing_plans.json file.
* @returns {Object[]} - An array of pricing plans.
*/
function getPricingPlans({ body }) {
if (Array.isArray(body)) {
return body.reduce((acc, lang) => {
Expand All @@ -100,6 +151,11 @@ function getPricingPlans({ body }) {
}
}

/**
* This function returns true if free_bike_status.json contains a vehicle with a vehicle_type_id.
* @param {*} param0 - The free_bike_status.json file.
* @returns {boolean}
*/
function hadVehicleTypeId({ body }) {
if (Array.isArray(body)) {
return body.some((lang) =>
Expand All @@ -110,6 +166,11 @@ function hadVehicleTypeId({ body }) {
}
}

/**
* This function returns true if free_bike_status.json contains a vehicle with a pricing_plan_id.
* @param {*} param0 - The free_bike_status.json file.
* @returns {boolean}
*/
function hasPricingPlanId({ body }) {
if (Array.isArray(body)) {
return body.some((lang) =>
Expand All @@ -120,6 +181,13 @@ function hasPricingPlanId({ body }) {
}
}

/**
* This function returns true if a file from a GBFS feed contains a specific rental_uri (ios or android).
* @param {Object} param0 - A file from a GBFS feed.
* @param {string} key - The type of the objects that may contain a rental_uri (bikes or stations).
* @param {string} store - The type of store (ios or android).
* @returns {boolean}
*/
function hasRentalUris({ body }, key, store) {
if (Array.isArray(body)) {
return body.some((lang) =>
Expand All @@ -130,6 +198,11 @@ function hasRentalUris({ body }, key, store) {
}
}

/**
* This function returns true if a file from a GBFS feed exists in any language.
* @param {Object} file - A file from a GBFS feed.
* @returns {boolean}
*/
function fileExist(file) {
if (!file) {
return false
Expand All @@ -144,6 +217,11 @@ function fileExist(file) {
return false
}

/**
* This function returns true if the gbfs.json file is required.
* @param {string} version - The version of the GBFS feed.
* @returns {boolean}
*/
function isGBFSFileRequire(version) {
if (!version) {
return false
Expand All @@ -152,7 +230,13 @@ function isGBFSFileRequire(version) {
}
}

/** Class representing a GBFS feed. */
class GBFS {
/**
* Creates a GBFS feed.
* @param {string} url - The URL of the gbfs.json file.
* @param {Object} param1 - The parameters of the validation.
*/
constructor(
url,
{ docked = false, freefloating = false, version = null, auth = {} } = {}
Expand Down Expand Up @@ -198,6 +282,11 @@ class GBFS {
}
}

/**
* This function returns the FileValidationResult of the gbfs.json file from a generated URL.
* @param {string} url - The URL of the gbfs.json file.
* @returns FileValidationResult
*/
alternativeAutoDiscovery(url) {
return got
.get(url, this.gotOptions)
Expand Down Expand Up @@ -249,6 +338,10 @@ class GBFS {
})
}

/**
* This function returns the FileValidationResult of the gbfs.json file.
* @returns FileValidationResult
*/
checkAutodiscovery() {
return got
.get(this.url, this.gotOptions)
Expand Down Expand Up @@ -301,6 +394,14 @@ class GBFS {
})
}

/**
* This function retrieves the JSON schema and returns the result of the validate function.
* @param {string} version - The version of the GBFS feed.
* @param {string} file - The type of file from a GBFS feed.
* @param {Object} data - The body of a file from a GBFS feed.
* @param {Object} options - An Object that contains an array of JSON Patches.
* @returns {Object}
*/
validateFile(version, file, data, options) {
let schema

Expand All @@ -314,6 +415,12 @@ class GBFS {
return validate(schema, data, options)
}

/**
* This function returns on Object which contains the body of a file from a GBFS feed.
* @param {string} type - The type of file from a GBFS feed.
* @param {boolean} required - True if the file is required.
* @returns {Object}
*/
getFile(type, required) {
if (this.autoDiscovery) {
let urls
Expand Down Expand Up @@ -390,6 +497,15 @@ class GBFS {
}
}

/**
* This function returns the FileValidationResult of a file from a GBFS feed.
* @param {Object} body - The body of a file from a GBFS feed.
* @param {string} version - The version of the GBFS feed.
* @param {string} type - The type of file from a GBFS feed.
* @param {boolean} required - True if the file is required.
* @param {Object} options - An Object that contains an array of JSON Patches.
* @returns FileValidationResult
*/
validationFile(body, version, type, required, options) {
if (Array.isArray(body)) {
body = body
Expand Down Expand Up @@ -419,6 +535,10 @@ class GBFS {
}
}

/**
* This function returns a token to access a GBFS feed.
* @returns {Object}
*/
getToken() {
return got
.post(this.auth.oauthClientCredentialsGrant.tokenUrl, {
Expand All @@ -435,6 +555,10 @@ class GBFS {
})
}

/**
* This function returns an Object that contains all the files from a GBFS feed and the FileValidationResult of the gbfs.json file.
* @returns {Object}
*/
async getFiles() {
if (this.auth && this.auth.type === 'oauth_client_credentials_grant') {
await this.getToken()
Expand Down Expand Up @@ -469,6 +593,10 @@ class GBFS {
}
}

/**
* This function returns an Object that contains the FileValidationResult of all the files from a GBFS feed.
* @returns {Object}
*/
async validation() {
const { gbfsResult, gbfsVersion, files, summary } = await this.getFiles()

Expand Down
7 changes: 7 additions & 0 deletions gbfs-validator/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ const ajvErrors = require('ajv-errors')
const jsonpatch = require('fast-json-patch')
const jsonmerge = require('json-merge-patch')

/**
* This function validates a file from a GBFS feed using Ajv.
* @param {*} schema - The JSON schema for the file to validate.
* @param {*} object - The body of a file to validate from a GBFS feed.
* @param {*} options - An Object that contains an array of JSON Patches.
* @returns {Object} - An Object tthat contains the schema and the errors detected.
*/
module.exports = function validate(schema, object, options = {}) {
const ajv = new Ajv({ allErrors: true, strict: false })
ajvErrors(ajv)
Expand Down

0 comments on commit 1987efe

Please sign in to comment.