Skip to main content
Sign in
Snippets Groups Projects
Commit 81bc953d authored by Anjan Kaur's avatar Anjan Kaur
Browse files

Issues #17 #18 #20, resolving in same schema, displaying schema dependencies

parent 01ac4faf
No related branches found
No related tags found
No related merge requests found
......@@ -77,7 +77,6 @@ if (argv.m) {
}
if(argv.s){
console.log("here");
ajv.addMetaSchema(require(path.resolve(argv.s)));
}
......
......
......@@ -27,11 +27,336 @@ var url = require("url");
var Promise=require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var Writer=require('./writeFiles');
var jsonSchemaRefParser = require("json-schema-ref-parser");
var deff='#/definitions/';
var absUrlRegex = new RegExp('^(?:[a-z]+:)?//', 'i');
var refParser = require('json-schema-ref-parser');
var pointer = require('json-pointer');
var smap; //TODO remove
var sPath; //TODO remove
var wmap={};
var async = require('async');
function get$refType(refValue){
var startpart = "", endpart = "", refType = "";
var arr = refValue.split("#");
if(arr.length > 1)
endpart=arr[1]
startpart=arr[0]
//TODO yRelNoDef
//relative-- yRelWithDef, yRelNoDef,
//absolute-- yAbsWithDef, yAbsFSchema, yAbsWithFragment
var refType="",currStartId;
var traversedRefMap;
var deff='/definitions/';
//if( absUrlRegex.test(refVal) ){
if(startpart.length > 1){
if(startpart in smap){
if(endpart.startsWith(deff)){
refType = "yAbsWithDef"
}
else{
if(endpart.length == 0)
refType = "yAbsFSchema"
else
refType = "yAbsWithFragment"
}
}
}
else {
if(endpart.startsWith(deff)){
refType = "yRelWithDef"
}
}
// }
return {startpart,endpart,refType}
}
function normaliseLinks(obj,refArr){
let basepath = refArr.startpart ;
let $linkVal = "", $linkPath = "";
if(basepath in smap){
let newpath = path.relative(path.dirname(sPath),smap[basepath].filePath).replace(/\\/g, '/'); //to cater windows paths
let temp = newpath.slice(0, -5).split("/");
$linkVal = obj["title"] ? obj["title"] : path.basename(newpath).slice(0, -5);
$linkPath = temp.join("/")+".md";
return { $linkVal , $linkPath };
}
}
function processSchema(schema){
var propertyMap={};
return new Promise((resolve,reject)=>{
if(!schema.properties)
schema.properties={}
var $id = schema["$id"] || schema["id"];
var base$id = $id;
if(! (base$id in wmap))
wmap[base$id] = {};
var required = schema["required"] || [];
if(schema["allOf"]){
_.each(schema["allOf"],function(value) {
if(value["$ref"]){
let obj,link;
var refArr = get$refType(value["$ref"]);
if(refArr.refType === "yRelWithDef"){
refArr.startpart = base$id
}
if(smap[refArr.startpart]){
obj=smap[refArr.startpart].jsonSchema;
if(refArr.refType != "yRelWithDef"){
link=normaliseLinks(obj,refArr);
if(!wmap[base$id][refArr.startpart]){
wmap[base$id][refArr.startpart]=link;
}
}
if(pointer.has(obj,refArr.endpart)){
var ischema = _.cloneDeep(pointer.get(obj, refArr.endpart));
if(refArr.refType === "yAbsFSchema"){
processSchema(ischema).then((psSchema) => {
if( psSchema["properties"] ){
_.forOwn(psSchema["properties"],(val,key,object) => {
processFurther(val,key,refArr.startpart).then((pfSchema)=>{
if(pfSchema){
schema.properties[key] = pfSchema;
schema.properties[key].$oSchema={}
schema.properties[key].$oSchema.$linkVal=link.$linkVal
schema.properties[key].$oSchema.$linkPath=link.$linkPath
if(pfSchema["required"]){
if(key in pfSchema["required"]){
schema.required.push(key);
}
}
}
});
})
}
})
}
else{
if( ischema["properties"] ){
_.forOwn(ischema["properties"],(val,key,object) => {
processFurther(val,key,refArr.startpart).then((pfSchema)=>{
schema.properties[key] = pfSchema;
if(refArr.refType === "yAbsWithDef"){
schema.properties[key].$oSchema={}
schema.properties[key].$oSchema.$linkVal=link.$linkVal
schema.properties[key].$oSchema.$linkPath=link.$linkPath
}
if(ischema["required"]){
if(key in ischema["required"])
schema.required.push(key);
}
});
})
}
// //decide what to do for if only type is given
// // Additional properties
// //Array
// //Additional Items
}
}
}
}else{
_.forOwn(value,function(val,key){
schema[key]=val;
//
})
// TODO add properties if there // behaviour to be decided
}
});
resolve(schema);
}
else {
//TODO check if something missing left here
resolve(schema);
}
})
}
// function processIDeff(def){
//
// }
var processISchema = Promise.method(function(schema,base$id){
let refArr;
if(! (base$id in wmap) )
wmap[base$id] = {};
if(schema["anyOf"] || schema["oneOf"]){
// var $definitions=[]
schema["type"] = schema["anyOf"] ? "anyOf" : "oneOf";
var arr = schema["anyOf"]? schema["anyOf"] : schema["oneOf"];
_.each(arr,function(value,index) {
if(value["$ref"]){
let obj,link;
refArr = get$refType(value["$ref"]);
if(refArr.refType === "yRelWithDef"){
refArr.startpart = base$id
}
if(smap[refArr.startpart]){
obj=smap[refArr.startpart].jsonSchema;
// if(refArr.refType === "yAbsFSchema" || refArr.refType === "yAbsWithDef")
if(refArr.refType != "yRelWithDef"){
link = normaliseLinks(obj,refArr);
if(!wmap[base$id][refArr.startpart]){
if(!refArr.startpart === base$id){
}
wmap[base$id][refArr.startpart]=link;
}
}
if(refArr.refType === "yAbsFSchema"){
value.$linkVal = link.$linkVal;
value.$linkPath = link.$linkPath;
}
else if (refArr.refType === "yRelWithDef" || refArr.refType === "yAbsWithDef"){
let ischema = _.cloneDeep(pointer.get(obj, refArr.endpart));
processISchema(ischema,refArr.startpart).then((piSchema)=>{
delete arr[index];
arr[index]=piSchema;
})
// processIDeff(obj);
// $definitions.push(a);
}
else {
// nothing
}
}
}
else{
processISchema(value,base$id).then((piSchema)=>{
delete arr[index];
arr[index]=piSchema;
})
}
})
// schema["$definitions"] = $definitions;
return schema;
}
if(schema["items"] ){
var val=schema["items"];
if(! schema["type"])
schema["type"] = "array";
if(_.isArray(val)){
//TODO
}else{
if(val["$ref"]){
let obj,link;
refArr = get$refType(val["$ref"]);
if(refArr.refType === "yRelWithDef"){
refArr.startpart = base$id
}
if(smap[refArr.startpart]){
obj=smap[refArr.startpart].jsonSchema;
if(refArr.refType === "yAbsFSchema" || refArr.refType === "yAbsWithDef")
{
link = normaliseLinks(obj,refArr);
if(!wmap[base$id][refArr.startpart]){
wmap[base$id][refArr.startpart]=link;
}
}
if(refArr.refType === "yAbsFSchema"){
// schema["$typeVal"].push(value["$ref"]); //No need
}
else if (refArr.refType === "yRelWithDef" || refArr.refType === "yAbsWithDef"){
let ischema = pointer.get(obj, refArr.endpart);
processISchema(ischema,refArr.startpart).then((piSchema)=>{//check // not sending correct id
schema["items"]=piSchema;
})
}
}
}
else{
//TODO if such a scenario
}
}
}
// schema.$definitions = $definitions
return schema;
})
var processFurther = Promise.method(function(val,key,$id){
let base$id =$id
if(val["$ref"]){
let obj,link;
if(! ($id in wmap) )
wmap[$id] = {};
let refArr = get$refType(val["$ref"]);
if(refArr.refType === "yRelWithDef"){
refArr.startpart = $id
}
if(smap[refArr.startpart]){
obj=smap[refArr.startpart].jsonSchema;
if(refArr.refType != "yRelWithDef"){
link = normaliseLinks(obj,refArr);
if(!wmap[base$id][refArr.startpart]){
wmap[base$id][refArr.startpart]=link;
}
}
else if(refArr.refType === "yAbsFSchema"){
val.$linkVal = link.$linkVal;
val.$linkPath = link.$linkPath;
return val;
}
if(pointer.has(obj,refArr.endpart)){
var ischema = _.cloneDeep(pointer.get(obj, refArr.endpart));
_.forOwn(val,(v,k)=>{
if(k != "$ref"){
ischema[k]=v;
}
});
return processISchema(ischema,refArr.startpart);
}
}
}
else {
//TODO if any other keyword
return val
}
})
var Schema=function(ajv,schemaMap){
this._ajv = ajv;
this._schemaPathMap=schemaMap;
......@@ -150,22 +475,38 @@ Schema.setSchemaPathMap=function(schemaMap){
}
Schema.load = function(schemaMap,schemaPath,outDir){
smap=schemaMap;
let keys = Object.keys(schemaMap);
return Promise.mapSeries(keys,(schemaKey) => {
{
var props = Object.keys(wmap);
for (var i = 0; i < props.length; i++) {
delete wmap[props[i]];
}
}
let schema = schemaMap[schemaKey].jsonSchema;
sPath=schemaMap[schemaKey].filePath;
return Schema.getExamples(schemaMap[schemaKey].filePath,schema)
.then((egs_schema) => Schema.getDescription(schemaMap[schemaKey].filePath,egs_schema))
.then((all_schema) => {
var schemaClone = _.cloneDeep(all_schema);
return Promise.props({
wSchema:schemaClone,
mSchema:traverseSchema(all_schema,schemaMap[schemaKey].filePath)
// return Promise.props({
// wSchema:schemaClone,
// mSchema:traverseSchema(all_schema,schemaMap[schemaKey].filePath)
// })
return processSchema(schemaClone).then((s)=>{
return {mSchema:s,wSchema:all_schema,dep:wmap}
})
}).then((object)=>{
return Promise.all([Writer.generateMarkdown(schemaMap[schemaKey].filePath,object.mSchema,schemaPath,outDir),
return Promise.all([Writer.generateMarkdown(schemaMap[schemaKey].filePath,object.mSchema,schemaPath,outDir,object.dep),
Writer.generateNewSchemaFiles(schemaMap[schemaKey].filePath,object.wSchema,schemaPath,outDir)]);
})
// })
}).then(()=>{
// console.log(JSON.stringify(wmap));
})
.catch((err) => console.error(err));
}
......
......
......@@ -26,12 +26,13 @@ var writeFile = function(outputDir, fileName, data) {
}
}
Writer.generateMarkdown = function(filename, schema,schemaPath,outDir) {
Writer.generateMarkdown = function(filename, schema,schemaPath,outDir,dependencyMap) {
schema.metaElements = {};
var ctx = {
schema: schema,
_: _,
validUrl: validUrl,
dependencyMap:dependencyMap
};
ejs.renderFile(path.join(__dirname,'../templates/md/topSchema.ejs'), ctx , { debug: false },function(err,str){
......
......
......@@ -8,21 +8,13 @@ function displayStringIfExists(object,key,str){
if(object[key])
return str;
}
%><%- HelperFunctions.displayType(nschema) %><%- displayIfExists(nschema,"description") %><%- HelperFunctions.getSimpleKeywords(nschema) %><%- displayStringIfExists(nschema,"properties"," \n**Properties**") %><% if(nschema.properties){ var resetVal=HelperFunctions.nestLevel;
Object.keys(nschema.properties).map((prop) => { var value= nschema.properties[prop]; HelperFunctions.nestLevel= resetVal+1;%><%- " \n"+Array(HelperFunctions.nestLevel * 4).join(" ") %><% if(value["title"]) {%><%- "* **"+value["title"]+"**" %><%} else{ %><%- "* **"+HelperFunctions.linkProperty(prop)+"**" %><% } %><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:true,nchild:0}) %><% }); } %><%
Object.keys(nschema).map((keyword) => {
var value=nschema[keyword];
switch(keyword){
case "oneOf":
case "allOf":
case "anyOf":
case "items":{ %><%- HelperFunctions.getDescriptionForKeyword(keyword,value) %><%
if(_.isArray(value)){
value.map((item,index)=>{%><%- include('innerSchema', {nschema: item, HelperFunctions:HelperFunctions,flag:false,nchild : Object.keys(value).length}) %><% });
}
else if(typeof value === "object"){%><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:false,nchild : Object.keys(value).length}) %><% }
} break;
default: return;
}
})
%><%- HelperFunctions.checkRefrence(nschema,flag,nchild) %>
%><%- HelperFunctions.displayType(nschema,1) %><%- HelperFunctions.displayFormat(nschema)%>
<% if(nschema["$oSchema"]) { %>* **Defined In:** <%- HelperFunctions.createLink(nschema.$oSchema.$linkVal,nschema.$oSchema.$linkPath) %>
<% }%><%- displayIfExists(nschema,"description") %><%- HelperFunctions.getSimpleKeywords(nschema) %><%- displayStringIfExists(nschema,sName + "properties"," \n**Properties**") %><%
if(nschema.properties){ var resetVal=HelperFunctions.nestLevel;
Object.keys(nschema.properties).map((prop) => { var value= nschema.properties[prop]; HelperFunctions.nestLevel= resetVal+1;%><%- " \n"+Array(HelperFunctions.nestLevel * 4).join(" ") %><% if(value["title"])
{%><%- "* **"+value["title"]+"**" %><%} else{ %><%- "* **"+HelperFunctions.linkProperty(prop)+"**" %><%
} %><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:true,nchild:0})
%><% });
} %>
<%- HelperFunctions.checkRefrence(nschema,flag,nchild) %>
......@@ -3,7 +3,7 @@
nestLevel:0,
isRequired : function (key,requiredProperties) {
if( _.indexOf(requiredProperties,key,0) != -1 )
return " \n_Required Property_";
return " \n* **Required**";
else
return "";
},
......@@ -71,27 +71,123 @@
});
return str;
},
displayType: function(value){
displayType: function(value,level){
var typeVal=value["type"];
var word1="";
var str1=" \n**Type:** ", str2="";
if(value["format"])
str2=str2 + '`'+value["format"]+ '` ';
switch(typeVal){
case "oneOf" : word1 = "Only one of "; break;
case "anyOf" : word1 = "Either "; break;
case "array" : word1 = "Array of "; break;
}
var str2="",str="",str3="";
if(level === 1)
str=" \n* **Type:** "
else if(level === 3)
str=" "
else if(level === 4)
str=" \n * Type: "
else if(level === 2)
str= " \n * "
// var str=" \n "//" Type: ",
if(typeVal === "anyOf" || typeVal === "oneOf"){
var arr= value[typeVal]; //if not throw error
_.each(arr,function(item,index){
if(item["type"] != "anyOf" && item["type"] != "oneOf" && item["type"] != "array"){
if(item["$ref"]){
if(index === 0)
{str2= str2 + HelperFunctions.createLink(item["$linkVal"],item["$linkPath"]);}
else
str2= str2 + " or "+ HelperFunctions.createLink(item["$linkVal"],item["$linkPath"])
}
else{
//TODO
}
}
else{
str2= str2 + HelperFunctions.displayType(item,2);
//return HelperFunctions.displayType(item);
}
})
}
else if(typeVal === "array" && value["items"] ){
//str2=str2+"Array Of ";
if(_.isArray(value["items"])){
_.forOwn(value["items"],(item,key,object)=>{
if(item["type"] != "anyOf" && item["type"] != "oneOf" && item["type"] != "array"){
if(item["$ref"]){
// str2= str2 + HelperFunctions.createLink(item["$linkVal"],item["$linkPath"]) + " or "
}
else{
//TODO
}
}
else{
str2= str2 + HelperFunctions.displayType(item,2);
}
})
}
else if(typeof value["items"] === "object"){
if(value["items"]["type"] != "anyOf" && value["items"]["type"] != "oneOf" && value["items"]["type"] != "array"){
if(value["items"]["$ref"]){
str2= str2 + HelperFunctions.createLink(value["$linkVal"],value["$linkPath"])
}
else{
str2=""
if(value["items"]["properties"]){
var nschema=value["items"];
str3=str3+"following Properties ";
_.forOwn(nschema.properties,(val,key) =>
{
str3=str3+"\n * **"+HelperFunctions.linkProperty(key)+"**"+HelperFunctions.displayType(val,4)+displayIfExists(val,"description")
})
}else {
if(value["items"]["type"].length > 1)
str3 = str3 + value["items"]["type"];
}
}
}
else{
str2= str2 + HelperFunctions.displayType(value["items"],3);
}
}
}
else if(typeVal){
if(_.isArray(typeVal)){
_.each(typeVal, (item,index) => {
if(index != typeVal.length - 1)
str2=str2 + '`'+item+ '`, '
else str2=str2 + '`'+item+ '`';
str2=str2 +item+ ', '
else str2=str2 + item;
})
}
else
str2=str2 + '`'+typeVal+ '`';
str2=str2 + typeVal;
}
if(str2.length > 1)
return str1 + str2;
else
return str+ word1 + str2 ;
else if(str3.length > 1)
return str+ word1 + str3 ;
else{
return ""
}
},
displayFormat: function(value){
var str = "";
if(value["format"])
str = str + " \n* **Format:** " +value["format"] ;
return str;
},
getSimpleKeywords: function (object){
var str="";
......@@ -119,12 +215,61 @@
})
return str;
},
getDependencies: function(dependencyMap,schema){
var id="",title="";
if(schema["$id"])
id=schema["$id"];
if(schema["title"])
title=schema["title"]
var mainId=id;
var str = title + " is based on: \n";
var usemap={};
var str2="";
var recurse = function(dmap,level){
if(dmap){
if(Object.keys(dmap).length > 0){
_.forOwn(dmap,(val,key) => {
if(!(key in usemap)){
str2 = str2 + " \n" +Array(level * 4).join(" ") + "* "+HelperFunctions.createLink(val.$linkVal,val.$linkPath);
// console.log("str2");
usemap[key]=1;
if(dependencyMap[key] && Object.keys(dependencyMap[key]).length > 0){
if(key != mainId)
recurse(dependencyMap[key],level+1)
}
else
return str2;
}
else
return ""
})
}
else {
return ""
}
}
else
return ""
return str2;
}
if(Object.keys(dependencyMap[id]).length > 0)
return str + recurse(dependencyMap[id],0)
}
}
function displayIfExists(object,key){
if(object[key])
return " \n" + HelperFunctions.escapeText(object[key]);
else
return ""
}
function displayStringIfExists(object,key,str){
......@@ -132,34 +277,19 @@ function displayStringIfExists(object,key,str){
return " \n" + str;
}
%>
%>
<%- displayStringIfExists(schema,"title","# "+schema["title"]) %>
<%- HelperFunctions.displayType(schema) %>
<%- HelperFunctions.getDependencies(dependencyMap,schema) %>
<% HelperFunctions.displayType(schema,1) %>
<%- displayIfExists(schema,"description") %>
<% Object.keys(schema).map((keyword) => {
var value=schema[keyword];
switch(keyword){
case "oneOf":
case "allOf":
case "anyOf":
case "items":{
%><%- HelperFunctions.getDescriptionForKeyword(keyword,value) %><%if(_.isArray(value)){
value.map((item,index)=>{%><%- include('innerSchema', {nschema: item, HelperFunctions:HelperFunctions,flag:false,nchild : value.length}) %><% });
}else if(typeof value === "object"){
%><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:false,nchild : Object.keys(value).length}) %><% }
} break;
default: return;
}
})
%><%- HelperFunctions.getSimpleKeywords(schema) %>
<% if(schema.properties){ %>
<%- HelperFunctions.getSimpleKeywords(schema) %>
<% if(schema.properties && Object.keys(schema.properties).length > 0){ %>
## Properties
<% Object.keys(schema.properties).map((prop) => { var value= schema.properties[prop]; HelperFunctions.nestLevel = -1; %>
### <%- HelperFunctions.linkProperty(prop) %><%- HelperFunctions.isRequired(prop,schema.required) %><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:true,nchild:0}) %><% });} %>
### <%- HelperFunctions.linkProperty(prop) %><%- HelperFunctions.isRequired(prop,schema.required) %><%- include('innerSchema', {nschema: value, HelperFunctions:HelperFunctions,flag:true,nchild:0,sName:HelperFunctions.linkProperty(prop)}) %><% });} %>
<% if(schema.definitions){ %>
<% if(schema.$definitions){ %>
## Definitions
<% Object.keys(schema.definitions).map((def) => { var value= schema.definitions[def]; HelperFunctions.nestLevel = -1; %>
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment