Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code documentation in jsdoc #163

Merged
merged 6 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading