diff --git a/cli.js b/cli.js new file mode 100644 index 0000000000000000000000000000000000000000..5ca576ddfb8e0ffad5fb4cabaf3093554d98859d --- /dev/null +++ b/cli.js @@ -0,0 +1,120 @@ +#! /usr/bin/env node +/** + * Copyright 2017 Adobe Systems Incorporated. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + */ + +var logger = require('winston'); +var Promise = require('bluebird'); +var path = require('path'); +var _ = require('lodash'); +var fs = Promise.promisifyAll(require('fs')); +var readdirp = require('readdirp'); +var Ajv = require('ajv'); + +var processFile = require('./lib/main'); +var Schema = require('./lib/schema'); +var readSchemaFile = require('./lib/readSchemaFile'); + +// parse/process command line arguments +var argv = require('optimist') +.usage('Generate Markdown documentation from JSON Schema.\n\nUsage: $0') +.demand('d') +.alias('d', 'input') +// TODO: is baseURL still a valid parameter? +.describe('d', 'path to directory containing all JSON Schemas or a single JSON Schema file. This will be considered as the baseURL. Note that only files ending in .schema.json will be processed.') +.alias('o', 'out') +.describe('o', 'path to output directory') +.default('o', path.resolve(path.join('.', 'out'))) +.alias('m', 'meta') +.describe('m','add metadata elements to .md files Eg -m template=reference. Multiple values can be added by repeating the flag Eg: -m template=reference -m hide-nav=true') +.alias('s','metaSchema') +.describe('s', 'Custom meta schema path to validate schemas') +.alias('x', 'schema-out') +.describe('x', 'output JSON Schema files including description and validated examples in the _new folder at output directory') +.check(function (args) { + if (!fs.existsSync(args.input)) { + throw 'Input file "' + args.input + '" does not exist!'; + } + if (args.s && !fs.existsSync(args.s)) { + throw 'Meta schema file "' + args.s + '" does not exist!'; + } +}) +.argv; + +var ajv = new Ajv({ allErrors: true , messages:true }); +ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')); +var schemaPathMap = {}; +var metaElements = {}; +var schemaPath = path.resolve(argv.d); +var outDir = path.resolve(argv.o); +var target = fs.statSync(schemaPath); + +if(argv.s){ + ajv.addMetaSchema(require(path.resolve(argv.s))); +} + +if (argv.m) { + if(_.isArray(argv.m)){ + _.each(argv.m,function(item){ + var meta=item.split('='); + if (meta.length === 2) { + metaElements[meta[0]] = meta[1]; + } + }); + } else { + var meta=(argv.m).split('='); + if (meta.length === 2) { + metaElements[meta[0]] = meta[1]; + } + } +} + +logger.info('output directory: %s', outDir); +if (target.isDirectory()) { + // the ajv json validator will be passed into the main module to help with processing + var files=[]; + readdirp({ root: schemaPath, fileFilter: '*.schema.json' }) + .on('data',(entry) => { + files.push(entry.fullPath); + ajv.addSchema(require(entry.fullPath), entry.fullPath); + }) + .on('end',() => { + Schema.setAjv(ajv); + Schema.setSchemaPathMap(schemaPathMap); + return Promise.reduce(files, readSchemaFile, schemaPathMap) + .then((schemaMap)=>{ + logger.info('finished reading all *.schema.json files in %s, beginning processing....', schemaPath); + return Schema.load(schemaMap, schemaPath, outDir, metaElements); + }) + .then(() => { + logger.info('Processing complete.'); + }) + .catch((err) => { + logger.error(err); + process.exit(1); + }); + }) + .on('error',(err)=>{ + logger.error(err); + process.exit(1); + }); +} else { + readSchemaFile(schemaPathMap, schemaPath) + .then((schemaMap) => { + ajv.addSchema(require(schemaPath), schemaPath); + Schema.setAjv(ajv); + Schema.setSchemaPathMap(schemaPathMap); + logger.info('finished reading %s, beginning processing....', schemaPath); + return Schema.load(schemaMap , schemaPath, outDir, metaElements); + }) + .then(() => { + logger.info('Processing complete.'); + }) + .catch((err) => { + logger.error(err); + process.exit(1); + }); +} diff --git a/lib/main.js b/lib/main.js old mode 100755 new mode 100644 index 73cc043b99972454353e3600002d375605d624a3..9ce1b84660146314a874c846ab63cdc250c955df --- a/lib/main.js +++ b/lib/main.js @@ -5,138 +5,8 @@ * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ -'use strict'; -var Promise=require('bluebird'); -var fs = Promise.promisifyAll(require('fs')); -var path = require('path'); -var _ = require('lodash'); -var async = require('async'); -var logger = require('winston'); -var readdirp = require('readdirp'); -var Schema = require('./schema'); -var Ajv = require('ajv'); -var ajv = new Ajv({ allErrors: true , messages:true}); -ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')); - - -// parse/process command line arguments - -var argv = require('optimist') -.usage('Generate Markdown documentation from JSON Schema.\n\nUsage: $0') -.demand('d') -.alias('d', 'input') -.describe('d', 'path to directory containing all JSON Schemas or a single JSON Schema file. This will be considered as the baseURL') -.alias('f','isFile') -.describe('f','pass if input is a file path') -.alias('o', 'out') -.describe('o', 'path to output directory (default: ./out)') -.alias('m', 'meta') -.describe('m','add metadata elements to .md files Eg -m template=reference. Multiple values can be added by repeating the flag Eg: -m template=reference -m hide-nav=true') -.alias('s','metaSchema') -.describe('s', 'Custom meta schema path to validate schemas') -.alias('x', 'schema-out') -.describe('x', 'pass to output JSON Schema files including description and validated examples in the _new folder at output directory') -.argv; - -if (!argv.d) { - process.exit(1); -} -var schemaPathMap={}; -var schemaPath = path.resolve(argv.d); -var fileDir=schemaPath; -var baseName = path.basename(schemaPath).replace(/\.[^/.]+$/, ''); -var outDir = path.resolve(argv.o || './out'); -var metaElements={}; -if(argv.f){ - fileDir=path.dirname(schemaPath); -} -if (argv.m) { - if(_.isArray(argv.m)){ - _.each(argv.m,function(item){ - var meta=item.split("="); - if(meta.length == 2) - metaElements[meta[0]]=meta[1]; - }); - } - else { - var meta=(argv.m).split("="); - if(meta.length == 2) - metaElements[meta[0]]=meta[1]; - } - -} -if(argv.s){ - ajv.addMetaSchema(require(path.resolve(argv.s))); -} - -var baseURL = path.resolve(fileDir); -logger.info('output directory: %s', outDir); -logger.info('processing %s...', schemaPath); - -var readSchemaFiles=function(fullpath){ - return fs.readFileAsync(fullpath).then((data)=>{ - let schema = JSON.parse(data); - let obj = {}; - obj.filePath = fullpath; - obj.jsonSchema = schema; - if(schema["$id"] && schema["$id"].length > 0){ - if(! schemaPathMap[schema["$id"]]) - schemaPathMap[schema["$id"]] = obj; - // TODO err - //TODO check Missing Specific properties to throw warning // function for warning - } - else { - schemaPathMap[fullpath] = obj; - } - }) -} - -//Function to generate Markdown for all files in a folder -var GenerateForAllFiles = function (dirname) { - var files=[]; - return new Promise((resolve,reject) => { - readdirp({ root: dirname, fileFilter: '*.schema.json' }) - .on('data',(entry) => { - files.push( entry.fullPath ); - ajv.addSchema(require(entry.fullPath),entry.fullPath); - }) - .on('end',()=>resolve(files)) - .on('error',(err)=>{ - reject(err); - }) - }).then((schemaFiles) => { - Schema.setAjv(ajv); - Schema.setSchemaPathMap(schemaPathMap); - return Promise.map(schemaFiles,readSchemaFiles) - .then(() => { - logger.info("Read Schema files!!!") - return Schema.load(schemaPathMap,schemaPath,outDir,metaElements) - - }) - - }) -} - - -if(argv.f){ - //generating markdown for a single file - readSchemaFiles(schemaPath).then(()=>{ - ajv.addSchema(require(schemaPath),schemaPath); - Schema.setAjv(ajv); - Schema.setSchemaPathMap(schemaPathMap); - logger.info("Read Schema files!!!"); - Schema.load( schemaPathMap , schemaPath, outDir, metaElements) - .then(()=>{logger.info("Done!!!")}) - .catch((err) => { - logger.error("Error Occurred. Processing Incomplete!!!") - logger.error(err)}) - }) - } - else { - GenerateForAllFiles(schemaPath) - .then(()=>{logger.info("Done!!!")}) - .catch((err) => { - logger.error("Error Occurred. Processing Incomplete!!!") - logger.error(err) - }) - } +module.exports = { + writer:require('./writeFiles'), + reader:require('./readSchemaFile'), + schema:require('./schema') +}; diff --git a/lib/readSchemaFile.js b/lib/readSchemaFile.js new file mode 100644 index 0000000000000000000000000000000000000000..5ef273b8b60ce637e5ce1061502398d1019c9f3f --- /dev/null +++ b/lib/readSchemaFile.js @@ -0,0 +1,34 @@ +/** + * Copyright 2017 Adobe Systems Incorporated. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + */ + +var Promise=require('bluebird'); +var fs = Promise.promisifyAll(require('fs')); + +// Reads a schema file and modifies a schema path map object based on the schema file. +// Returns the schema path map object. +module.exports = function readSchemaFile(schemaPathMap, fullPath) { + if (!schemaPathMap) { + schemaPathMap = {}; + } + return fs.readFileAsync(fullPath) + .then((data)=>{ + let schema = JSON.parse(data); + let obj = {}; + obj.filePath = fullPath; + obj.jsonSchema = schema; + if(schema["$id"] && schema["$id"].length > 0) { + if(! schemaPathMap[schema["$id"]]) { + schemaPathMap[schema["$id"]] = obj; + } + // TODO err + //TODO check Missing Specific properties to throw warning // function for warning + } else { + schemaPathMap[fullPath] = obj; + } + return schemaPathMap; + }); +}; diff --git a/package.json b/package.json index d41464391a7a2cb59d9cc2d3dce500ff14411f6a..e084bd0bf816f55cc0004aca6217844f658bdd96 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "version": "0.2.0", "main": "lib/main.js", "bin": { - "jsonschema2md": "./index.js" + "jsonschema2md": "./cli.js" }, "scripts": { - "start": "node ./index.js", + "start": "node cli.js", "test": "jasmine" }, "dependencies": {