raml-typesystem
Advanced tools
Comparing version 0.0.82 to 0.0.83
@@ -52,2 +52,5 @@ import ts = require("./typesystem"); | ||
getTypeRegistry(): TypeRegistry; | ||
libraries(): { | ||
[name: string]: TypeCollection; | ||
}; | ||
} | ||
@@ -54,0 +57,0 @@ export declare class AccumulatingRegistry extends ts.TypeRegistry { |
@@ -202,2 +202,5 @@ "use strict"; | ||
}; | ||
TypeCollection.prototype.libraries = function () { | ||
return this.uses; | ||
}; | ||
return TypeCollection; | ||
@@ -930,2 +933,8 @@ }()); | ||
} | ||
for (var _d = 0, superTypes_1 = superTypes; _d < superTypes_1.length; _d++) { | ||
var st = superTypes_1[_d]; | ||
if (st.superTypes().indexOf(ts.REFERENCE) >= 0) { | ||
r.get(st.name()); | ||
} | ||
} | ||
var result = ts.derive(name, superTypes); | ||
@@ -946,3 +955,3 @@ if (ignoreTypeAttr && tp) { | ||
var key = childNode.key(); | ||
actual = childNode.childWithKey("value"); | ||
var actual = childNode.childWithKey("value"); | ||
var x = childNode; | ||
@@ -1011,2 +1020,5 @@ if (key != "example" && key != "discriminatorValue" && actual) { | ||
else { | ||
if (key == "required" && !isPropertyType) { | ||
return; | ||
} | ||
if (key === "facets") { | ||
@@ -1048,3 +1060,3 @@ hasfacetsOrOtherStuffDoesNotAllowedInExternals = [key]; | ||
}); | ||
if (result.metaOfType(meta.DiscriminatorValue).length == 0) { | ||
if (result.metaOfType(meta.DiscriminatorValue).length == 0 && global) { | ||
result.addMeta(new meta.DiscriminatorValue(result.name(), false)); | ||
@@ -1071,3 +1083,3 @@ } | ||
if (ap) { | ||
actual = ap.childWithKey("value"); | ||
var actual = ap.childWithKey("value"); | ||
if (actual) { | ||
@@ -1074,0 +1086,0 @@ ap = actual; |
@@ -359,5 +359,2 @@ "use strict"; | ||
var st = this.validateProp(i, this.name, this.type, p); | ||
if (!st.isOk() && this.optional && i[this.name] == null) { | ||
return ts.ok(); | ||
} | ||
return st; | ||
@@ -364,0 +361,0 @@ } |
@@ -21,2 +21,7 @@ import tsInterfaces = require("./typesystem-interfaces"); | ||
} | ||
export interface IExtendedContentProvider extends IContentProvider { | ||
rootPath(): string; | ||
isWebPath(p: string): boolean; | ||
relativePath(from: string, to: string): string; | ||
} | ||
export declare class JSONSchemaObject { | ||
@@ -26,2 +31,3 @@ private schema; | ||
jsonSchema: any; | ||
private graph; | ||
constructor(schema: string, provider: IContentProvider); | ||
@@ -49,4 +55,2 @@ private EXAMPLE_ERROR_ENTRY; | ||
private setupId(json, path); | ||
private toProperWebURL(p); | ||
private decodeURL(p); | ||
private acceptErrors(key, errors, exampleContent, throwImmediately?, isWarning?); | ||
@@ -56,2 +60,3 @@ contentAsync(_reference: any): Promise; | ||
private static EXAMPLE_ERROR_CODES; | ||
private updateGraph(json, schemaPath); | ||
} | ||
@@ -58,0 +63,0 @@ export interface ValidationError { |
@@ -73,2 +73,8 @@ "use strict"; | ||
}; | ||
function isExtendedContentProvider(x) { | ||
var hasRootPath = x.rootPath != null && (typeof x.rootPath === "function"); | ||
var hasIsWebPath = x.isWebPath != null && (typeof x.isWebPath === "function"); | ||
var hasRelativePath = x.relativePath != null && (typeof x.relativePath === "function"); | ||
return hasRootPath && hasIsWebPath && hasRelativePath; | ||
} | ||
var DummyProvider = /** @class */ (function () { | ||
@@ -111,3 +117,3 @@ function DummyProvider() { | ||
var exampleKey = function (content, schema, contextPath) { | ||
return "__EXAMPLE_" + content + schema + contextPath; | ||
return "__EXAMPLE_" + ("" + content).trim() + schema.trim() + contextPath; | ||
}; | ||
@@ -136,3 +142,5 @@ var JSONSchemaObject = /** @class */ (function () { | ||
var api = require('json-schema-compatibility'); | ||
this.setupId(jsonSchemaObject, this.provider.contextPath()); | ||
var contextPath = this.provider.contextPath(); | ||
this.setupId(jsonSchemaObject, contextPath); | ||
this.updateGraph(jsonSchemaObject, contextPath); | ||
var schemaVer = "" + jsonSchemaObject["$schema"]; | ||
@@ -147,2 +155,5 @@ if (schemaVer.indexOf("http://json-schema.org/draft-04/") == -1) { | ||
catch (e) { | ||
if (ts.ValidationError.isInstance(e)) { | ||
throw e; | ||
} | ||
throw new ts.ValidationError(typesystem_1.messageRegistry.INVALID_JSON_SCHEMA_DETAILS, { msg: e.message }); | ||
@@ -258,3 +269,3 @@ } | ||
if (_this.provider.isAbsolutePath(reference)) { | ||
resolvedRef = _this.toProperWebURL(reference); | ||
resolvedRef = toProperWebURL(reference); | ||
} | ||
@@ -320,2 +331,20 @@ else { | ||
} | ||
else { | ||
var schKey = exampleKey("__SCHEMA_VALIDATION__", this.schema, this.provider.contextPath()); | ||
var schError = globalCache.getValue(schKey); | ||
if (schError) { | ||
if (schError instanceof Error) { | ||
if (ts.ValidationError.isInstance(schError)) { | ||
var ve = schError; | ||
var newVe = new ts.ValidationError(ve.messageEntry, ve.parameters); | ||
newVe.filePath = ve.filePath; | ||
newVe.additionalErrors = ve.additionalErrors; | ||
newVe.internalPath = ve.internalPath; | ||
newVe.isWarning = ve.isWarning; | ||
schError = newVe; | ||
} | ||
throw schError; | ||
} | ||
} | ||
} | ||
if (alreadyAccepted.length == 0) { | ||
@@ -346,3 +375,3 @@ tryParseJSON(content, true); | ||
var remoteSchemeContent; | ||
var reference = _this.decodeURL(_reference); | ||
var reference = decodeURL(_reference); | ||
var result = { reference: _reference }; | ||
@@ -354,3 +383,5 @@ try { | ||
var jsonObject = JSON.parse(content_1); | ||
_this.setupId(jsonObject, _this.provider.normalizePath(reference)); | ||
var nRef = _this.provider.normalizePath(reference); | ||
_this.setupId(jsonObject, nRef); | ||
_this.updateGraph(jsonObject, nRef); | ||
remoteSchemeContent = api.v4(jsonObject); | ||
@@ -363,2 +394,3 @@ delete remoteSchemeContent['$schema']; | ||
exception.filePath = reference; | ||
globalCache.setValue(key, exception); | ||
throw exception; | ||
@@ -424,2 +456,4 @@ } | ||
} | ||
else { | ||
} | ||
var validator = jsonUtil.getValidator(); | ||
@@ -463,5 +497,8 @@ // if(alreadyAccepted.length==0&&this.jsonSchema.id){ | ||
var acceptedReferences = []; | ||
missingReferences.forEach(function (_reference) { | ||
missingReferences.forEach(function (_reference, i) { | ||
if (i > 0) { | ||
return; | ||
} | ||
var remoteSchemeContent; | ||
var reference = _this.decodeURL(_reference); | ||
var reference = decodeURL(_reference); | ||
var result = { reference: _reference }; | ||
@@ -473,3 +510,5 @@ try { | ||
var jsonObject = JSON.parse(content); | ||
_this.setupId(jsonObject, _this.provider.normalizePath(reference)); | ||
var nRef = _this.provider.normalizePath(reference); | ||
_this.setupId(jsonObject, nRef); | ||
_this.updateGraph(jsonObject, nRef); | ||
remoteSchemeContent = api.v4(jsonObject); | ||
@@ -482,2 +521,3 @@ delete remoteSchemeContent['$schema']; | ||
exception.filePath = reference; | ||
globalCache.setValue(key, exception); | ||
throw exception; | ||
@@ -516,37 +556,5 @@ } | ||
} | ||
json.id = this.toProperWebURL(json.id); | ||
json.id = toProperWebURL(json.id); | ||
this.patchSchema(json); | ||
}; | ||
JSONSchemaObject.prototype.toProperWebURL = function (p) { | ||
if (p == null || p.trim().length == 0) { | ||
return p; | ||
} | ||
var l = "https://".length; | ||
if (p.length >= l && p.substring(0, l) == "https://") { | ||
return p; | ||
} | ||
p = p.replace("//", "__\/DOUBLESLASH\/__"); | ||
p = p.replace(/^([a-zA-Z]):/, '$1__\/COLON\/__'); | ||
var protoclStr = "https://__/APPENDED_PROTOCOL/__"; | ||
if (p.charAt(0) != "/") { | ||
protoclStr += "/"; | ||
} | ||
return protoclStr + p; | ||
}; | ||
JSONSchemaObject.prototype.decodeURL = function (p) { | ||
if (p == null || p.trim().length == 0) { | ||
return p; | ||
} | ||
var protocolStr = "https://__/APPENDED_PROTOCOL/__"; | ||
var l = protocolStr.length; | ||
if (p.length < l || p.substring(0, l) != protocolStr) { | ||
return p; | ||
} | ||
p = p.substring(l, p.length); | ||
if (p.indexOf("__/COLON/__") > 0 && p.charAt(0) == "/") { | ||
p = p.substring(1); | ||
} | ||
p = p.replace("__/DOUBLESLASH/__", "//").replace("__/COLON/__", ":"); | ||
return p; | ||
}; | ||
JSONSchemaObject.prototype.acceptErrors = function (key, errors, exampleContent, throwImmediately, isWarning) { | ||
@@ -590,3 +598,3 @@ var _this = this; | ||
var _this = this; | ||
var reference = this.decodeURL(_reference); | ||
var reference = decodeURL(_reference); | ||
var remoteSchemeContent; | ||
@@ -607,3 +615,5 @@ var api = require('json-schema-compatibility'); | ||
var jsonObject = JSON.parse(cnt); | ||
_this.setupId(jsonObject, _this.provider.normalizePath(reference)); | ||
var nRef = _this.provider.normalizePath(reference); | ||
_this.setupId(jsonObject, nRef); | ||
_this.updateGraph(jsonObject, nRef); | ||
remoteSchemeContent = api.v4(jsonObject); | ||
@@ -622,2 +632,37 @@ delete remoteSchemeContent['$schema']; | ||
}; | ||
JSONSchemaObject.prototype.updateGraph = function (json, schemaPath) { | ||
if (schemaPath.indexOf("#") < 0) { | ||
schemaPath += "#"; | ||
} | ||
if (!this.graph) { | ||
this.graph = new SchemaGraph(schemaPath); | ||
} | ||
var cycle = this.graph.addNode(json, schemaPath); | ||
if (cycle) { | ||
if (isExtendedContentProvider(this.provider)) { | ||
var ep_1 = this.provider; | ||
var rootPath_1 = ep_1.rootPath(); | ||
var rpl_1 = rootPath_1.length; | ||
cycle = cycle.map(function (x) { | ||
var p = x.trim(); | ||
if (ep_1.isWebPath(p)) { | ||
if (ep_1.isWebPath(rootPath_1) && p.length >= rpl_1 && p.substring(0, rpl_1) == rootPath_1) { | ||
p = p.substring(rpl_1); | ||
} | ||
} | ||
else { | ||
p = ep_1.relativePath(rootPath_1, p).replace(/\\/g, "/"); | ||
} | ||
if (p.length && p.charAt(p.length - 1) == '#') { | ||
p = p.substring(0, p.length - 1); | ||
} | ||
return p; | ||
}); | ||
} | ||
var ve = new ts.ValidationError(typesystem_1.messageRegistry.CIRCULAR_REFS_IN_JSON_SCHEMA_DETAILS, { | ||
cycle: cycle.join(" -> ") | ||
}); | ||
throw ve; | ||
} | ||
}; | ||
JSONSchemaObject.SCHEMA_ERROR_CODES = { | ||
@@ -667,2 +712,34 @@ "KEYWORD_TYPE_EXPECTED": true, | ||
exports.JSONSchemaObject = JSONSchemaObject; | ||
function toProperWebURL(p) { | ||
if (p == null || p.trim().length == 0) { | ||
return p; | ||
} | ||
var l = "https://".length; | ||
if (p.length >= l && p.substring(0, l) == "https://") { | ||
return p; | ||
} | ||
p = p.replace("//", "__\/DOUBLESLASH\/__"); | ||
p = p.replace(/^([a-zA-Z]):/, '$1__\/COLON\/__'); | ||
var protoclStr = "https://__/APPENDED_PROTOCOL/__"; | ||
if (p.charAt(0) != "/") { | ||
protoclStr += "/"; | ||
} | ||
return protoclStr + p; | ||
} | ||
function decodeURL(p) { | ||
if (p == null || p.trim().length == 0) { | ||
return p; | ||
} | ||
var protocolStr = "https://__/APPENDED_PROTOCOL/__"; | ||
var l = protocolStr.length; | ||
if (p.length < l || p.substring(0, l) != protocolStr) { | ||
return p; | ||
} | ||
p = p.substring(l, p.length); | ||
if (p.indexOf("__/COLON/__") > 0 && p.charAt(0) == "/") { | ||
p = p.substring(1); | ||
} | ||
p = p.replace("__/DOUBLESLASH/__", "//").replace("__/COLON/__", ":"); | ||
return p; | ||
} | ||
var MAX_EXAMPLES_TRESHOLD = 10; | ||
@@ -873,3 +950,3 @@ var XMLSchemaObject = /** @class */ (function () { | ||
} | ||
var key = "__SCHEMA_" + content + contextPath; | ||
var key = "__SCHEMA_" + ("" + content).trim() + contextPath.trim(); | ||
return key; | ||
@@ -1103,2 +1180,92 @@ }; | ||
exports.tryParseJSON = tryParseJSON; | ||
var RefPath = /** @class */ (function () { | ||
function RefPath(segments) { | ||
this.segments = segments; | ||
} | ||
RefPath.prototype.length = function () { | ||
return this.segments.length; | ||
}; | ||
return RefPath; | ||
}()); | ||
var SchemaNode = /** @class */ (function () { | ||
function SchemaNode(url) { | ||
this.url = url; | ||
this.processed = false; | ||
this.refFromRoot = new RefPath([]); | ||
this.refsOut = {}; | ||
this.referees = {}; | ||
} | ||
return SchemaNode; | ||
}()); | ||
var SchemaGraph = /** @class */ (function () { | ||
function SchemaGraph(rootPath) { | ||
this.rootPath = rootPath; | ||
this.nodes = {}; | ||
} | ||
SchemaGraph.prototype.node = function (url) { | ||
return this.nodes[url]; | ||
}; | ||
SchemaGraph.prototype.addNode = function (json, schemaPath) { | ||
var node = this.nodes[schemaPath]; | ||
if (node) { | ||
if (node.processed) { | ||
return; | ||
} | ||
} | ||
else { | ||
node = new SchemaNode(schemaPath); | ||
this.nodes[schemaPath] = node; | ||
} | ||
var refs = extractRefs(json); | ||
var referees = Object.keys(node.referees).map(function (x) { return node.referees[x]; }); | ||
var cycle = null; | ||
var _loop_1 = function (ref) { | ||
var referee = node.referees[ref]; | ||
if (referee) { | ||
cycle = [this_1.rootPath].concat(referee.refFromRoot.segments).concat(referee.refsOut[schemaPath].segments).concat([ref]); | ||
} | ||
var refNode = this_1.nodes[ref]; | ||
if (!refNode) { | ||
refNode = new SchemaNode(ref); | ||
refNode.refFromRoot = new RefPath(node.refFromRoot.segments.concat([ref])); | ||
this_1.nodes[ref] = refNode; | ||
} | ||
var newReferees = referees.filter(function (x) { return !refNode.referees[x.url]; }); | ||
for (var _i = 0, newReferees_1 = newReferees; _i < newReferees_1.length; _i++) { | ||
var r = newReferees_1[_i]; | ||
refNode.referees[r.url] = r; | ||
r.refsOut[ref] = new RefPath(r.refsOut[schemaPath].segments.concat([ref])); | ||
} | ||
node.refsOut[ref] = new RefPath([ref]); | ||
refNode.referees[node.url] = node; | ||
}; | ||
var this_1 = this; | ||
for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { | ||
var ref = refs_1[_i]; | ||
_loop_1(ref); | ||
} | ||
node.processed = true; | ||
return cycle; | ||
}; | ||
return SchemaGraph; | ||
}()); | ||
function extractRefs(obj) { | ||
return _.unique(doExtractRefs(obj, [])); | ||
} | ||
function doExtractRefs(obj, refs) { | ||
if (Array.isArray(obj)) { | ||
obj.forEach(function (x) { return doExtractRefs(x, refs); }); | ||
} | ||
else if (obj != null && typeof obj === "object") { | ||
Object.keys(obj).forEach(function (x) { | ||
if (x === "$ref" && typeof obj[x] === "string") { | ||
refs.push(decodeURL(obj[x])); | ||
} | ||
else if (typeof obj[x] === "object") { | ||
doExtractRefs(obj[x], refs); | ||
} | ||
}); | ||
} | ||
return refs; | ||
} | ||
//# sourceMappingURL=schemaUtil.js.map |
@@ -195,2 +195,6 @@ export interface IValidationPath { | ||
library(name: string): IParsedTypeCollection; | ||
libraries(): { | ||
[key: string]: IParsedTypeCollection; | ||
}; | ||
addLibrary(namespace: string, lib: IParsedTypeCollection): void; | ||
} | ||
@@ -197,0 +201,0 @@ export interface ITypeRegistry { |
{ | ||
"name": "raml-typesystem", | ||
"version": "0.0.82", | ||
"version": "0.0.83", | ||
"main": "dist/src/index.js", | ||
@@ -5,0 +5,0 @@ "scripts": { |
@@ -114,9 +114,9 @@ { | ||
}, | ||
"24" : { | ||
"code" : "24", | ||
"message": "" | ||
"DISPLAY_NAME_STRING": { | ||
"code" : "DISPLAY_NAME_STRING", | ||
"message" : "Property 'displayName' must be a string" | ||
}, | ||
"25" : { | ||
"code" : "25", | ||
"message": "" | ||
"DESCRIPTION_STRING": { | ||
"code" : "DESCRIPTION_STRING", | ||
"message" : "Property 'description' must be a string" | ||
}, | ||
@@ -323,2 +323,6 @@ "NOTHING" : { | ||
}, | ||
"CIRCULAR_REFS_IN_JSON_SCHEMA_DETAILS" : { | ||
"code" : "CIRCULAR_REFS_IN_JSON_SCHEMA_DETAILS", | ||
"message": "JSON schema contains circular references: {{cycle}}" | ||
}, | ||
"EXAMPLE_SCHEMA_FAILURE" : { | ||
@@ -325,0 +329,0 @@ "code" : "EXAMPLE_SCHEMA_FAILURE", |
@@ -10,3 +10,2 @@ import ts=require("./typesystem"); | ||
import {Annotation, Example, Examples} from "./metainfo"; | ||
import {Type} from "typescript"; | ||
import {FacetDeclaration} from "./metainfo"; | ||
@@ -225,2 +224,6 @@ import {HasProperty} from "./restrictions"; | ||
} | ||
libraries(){ | ||
return this.uses; | ||
} | ||
} | ||
@@ -936,3 +939,3 @@ | ||
var sAnnotations:ParseNode[][] = []; | ||
var actual = tp.childWithKey("value"); | ||
let actual = tp.childWithKey("value"); | ||
if(actual&&(actual.kind()==NodeKind.SCALAR||actual.kind()==NodeKind.ARRAY)){ | ||
@@ -996,2 +999,7 @@ sAnnotations = [ tp.children().filter(x=>{ | ||
} | ||
for(let st of superTypes){ | ||
if(st.superTypes().indexOf(ts.REFERENCE)>=0){ | ||
r.get(st.name()); | ||
} | ||
} | ||
var result=ts.derive(name,superTypes); | ||
@@ -1014,3 +1022,3 @@ if(ignoreTypeAttr && tp){ | ||
var key = childNode.key(); | ||
actual = childNode.childWithKey("value"); | ||
let actual = childNode.childWithKey("value"); | ||
var x = childNode; | ||
@@ -1081,2 +1089,5 @@ if(key!="example"&&key!="discriminatorValue"&&actual){ | ||
else { | ||
if(key == "required" && !isPropertyType){ | ||
return; | ||
} | ||
if (key === "facets") { | ||
@@ -1119,3 +1130,3 @@ hasfacetsOrOtherStuffDoesNotAllowedInExternals = [key]; | ||
}); | ||
if(result.metaOfType(meta.DiscriminatorValue).length==0){ | ||
if(result.metaOfType(meta.DiscriminatorValue).length==0 && global){ | ||
result.addMeta(new meta.DiscriminatorValue(result.name(),false)); | ||
@@ -1142,3 +1153,3 @@ } | ||
if (ap){ | ||
actual = ap.childWithKey("value"); | ||
let actual = ap.childWithKey("value"); | ||
if(actual){ | ||
@@ -1145,0 +1156,0 @@ ap = actual; |
@@ -367,5 +367,2 @@ import ts=require("./typesystem"); | ||
var st = this.validateProp(i, this.name, this.type,p); | ||
if(!st.isOk()&&this.optional&&i[this.name]==null){ | ||
return ts.ok(); | ||
} | ||
return st; | ||
@@ -372,0 +369,0 @@ } |
@@ -122,2 +122,18 @@ import {XMLSchemaReference} from "raml-xml-validation"; | ||
export interface IExtendedContentProvider extends IContentProvider { | ||
rootPath():string | ||
isWebPath(p:string):boolean | ||
relativePath(from: string, to: string): string; | ||
} | ||
function isExtendedContentProvider(x:IContentProvider){ | ||
const hasRootPath = (<any>x).rootPath != null && (typeof (<any>x).rootPath === "function"); | ||
const hasIsWebPath = (<any>x).isWebPath != null && (typeof (<any>x).isWebPath === "function"); | ||
const hasRelativePath = (<any>x).relativePath != null && (typeof (<any>x).relativePath === "function"); | ||
return hasRootPath && hasIsWebPath && hasRelativePath; | ||
} | ||
class DummyProvider implements IContentProvider { | ||
@@ -166,3 +182,3 @@ contextPath(): string { | ||
var exampleKey = function (content:any, schema:string, contextPath:string) { | ||
return "__EXAMPLE_" + content + schema + contextPath; | ||
return "__EXAMPLE_" + (""+content).trim() + schema.trim() + contextPath; | ||
}; | ||
@@ -172,2 +188,4 @@ export class JSONSchemaObject { | ||
private graph:SchemaGraph; | ||
constructor(private schema:string, private provider: IContentProvider){ | ||
@@ -193,3 +211,5 @@ if(!provider) { | ||
this.setupId(jsonSchemaObject, this.provider.contextPath()); | ||
const contextPath = this.provider.contextPath(); | ||
this.setupId(jsonSchemaObject, contextPath); | ||
this.updateGraph(jsonSchemaObject, contextPath); | ||
var schemaVer=""+jsonSchemaObject["$schema"]; | ||
@@ -203,2 +223,5 @@ if (schemaVer.indexOf("http://json-schema.org/draft-04/")==-1){ | ||
} catch (e){ | ||
if(ts.ValidationError.isInstance(e)){ | ||
throw e; | ||
} | ||
throw new ts.ValidationError(messageRegistry.INVALID_JSON_SCHEMA_DETAILS,{msg:e.message}); | ||
@@ -345,3 +368,3 @@ } | ||
if(this.provider.isAbsolutePath(reference)){ | ||
resolvedRef = this.toProperWebURL(reference); | ||
resolvedRef = toProperWebURL(reference); | ||
} | ||
@@ -415,2 +438,20 @@ else { | ||
} | ||
else{ | ||
let schKey = exampleKey("__SCHEMA_VALIDATION__",this.schema,this.provider.contextPath()); | ||
let schError = globalCache.getValue(schKey); | ||
if(schError) { | ||
if(schError instanceof Error) { | ||
if(ts.ValidationError.isInstance(schError)){ | ||
let ve = <ts.ValidationError>schError; | ||
let newVe = new ts.ValidationError(ve.messageEntry,ve.parameters); | ||
newVe.filePath = ve.filePath; | ||
newVe.additionalErrors = ve.additionalErrors; | ||
newVe.internalPath = ve.internalPath; | ||
newVe.isWarning = ve.isWarning; | ||
schError = newVe; | ||
} | ||
throw schError; | ||
} | ||
} | ||
} | ||
@@ -451,3 +492,3 @@ if(alreadyAccepted.length==0){ | ||
let reference = this.decodeURL(_reference); | ||
let reference = decodeURL(_reference); | ||
var result: any = {reference: _reference}; | ||
@@ -462,3 +503,5 @@ | ||
this.setupId(jsonObject, this.provider.normalizePath(reference)); | ||
const nRef = this.provider.normalizePath(reference); | ||
this.setupId(jsonObject, nRef); | ||
this.updateGraph(jsonObject, nRef); | ||
@@ -473,2 +516,3 @@ remoteSchemeContent = api.v4(jsonObject); | ||
(<ts.ValidationError>exception).filePath = reference; | ||
globalCache.setValue(key, exception); | ||
throw exception; | ||
@@ -543,3 +587,6 @@ } | ||
} | ||
else { | ||
} | ||
var validator = jsonUtil.getValidator(); | ||
@@ -595,6 +642,9 @@ // if(alreadyAccepted.length==0&&this.jsonSchema.id){ | ||
missingReferences.forEach((_reference: any) => { | ||
missingReferences.forEach((_reference: any,i) => { | ||
if(i>0){ | ||
return; | ||
} | ||
var remoteSchemeContent: any; | ||
let reference = this.decodeURL(_reference); | ||
let reference = decodeURL(_reference); | ||
var result: any = {reference: _reference}; | ||
@@ -609,3 +659,5 @@ | ||
this.setupId(jsonObject, this.provider.normalizePath(reference)); | ||
const nRef = this.provider.normalizePath(reference); | ||
this.setupId(jsonObject, nRef); | ||
this.updateGraph(jsonObject, nRef); | ||
@@ -620,2 +672,3 @@ remoteSchemeContent = api.v4(jsonObject); | ||
(<ts.ValidationError>exception).filePath = reference; | ||
globalCache.setValue(key, exception); | ||
throw exception; | ||
@@ -661,42 +714,6 @@ } | ||
} | ||
json.id = this.toProperWebURL(json.id); | ||
json.id = toProperWebURL(json.id); | ||
this.patchSchema(json); | ||
} | ||
private toProperWebURL(p:string):string{ | ||
if(p==null||p.trim().length==0){ | ||
return p; | ||
} | ||
let l = "https://".length; | ||
if(p.length>=l && p.substring(0,l)=="https://"){ | ||
return p; | ||
} | ||
p = p.replace("//","__\/DOUBLESLASH\/__"); | ||
p = p.replace(/^([a-zA-Z]):/,'$1__\/COLON\/__'); | ||
let protoclStr = "https://__/APPENDED_PROTOCOL/__"; | ||
if(p.charAt(0)!="/"){ | ||
protoclStr += "/"; | ||
} | ||
return protoclStr + p; | ||
} | ||
private decodeURL(p:string):string{ | ||
if(p==null||p.trim().length==0){ | ||
return p; | ||
} | ||
let protocolStr = "https://__/APPENDED_PROTOCOL/__"; | ||
let l = protocolStr.length; | ||
if(p.length<l||p.substring(0,l)!=protocolStr){ | ||
return p; | ||
} | ||
p = p.substring(l,p.length); | ||
if(p.indexOf("__/COLON/__")>0&&p.charAt(0)=="/"){ | ||
p = p.substring(1); | ||
} | ||
p = p.replace("__/DOUBLESLASH/__","//").replace("__/COLON/__",":"); | ||
return p; | ||
} | ||
private acceptErrors( | ||
@@ -746,3 +763,3 @@ key: any, | ||
contentAsync(_reference: any): Promise { | ||
let reference = this.decodeURL(_reference); | ||
let reference = decodeURL(_reference); | ||
var remoteSchemeContent: any; | ||
@@ -769,3 +786,5 @@ | ||
this.setupId(jsonObject, this.provider.normalizePath(reference)); | ||
const nRef = this.provider.normalizePath(reference); | ||
this.setupId(jsonObject, nRef); | ||
this.updateGraph(jsonObject, nRef); | ||
@@ -833,4 +852,78 @@ remoteSchemeContent = api.v4(jsonObject); | ||
} | ||
private updateGraph(json: any, schemaPath: string){ | ||
if(schemaPath.indexOf("#")<0){ | ||
schemaPath += "#"; | ||
} | ||
if(!this.graph){ | ||
this.graph = new SchemaGraph(schemaPath); | ||
} | ||
let cycle = this.graph.addNode(json,schemaPath); | ||
if(cycle){ | ||
if(isExtendedContentProvider(this.provider)){ | ||
let ep = <IExtendedContentProvider>this.provider; | ||
let rootPath = ep.rootPath(); | ||
let rpl = rootPath.length; | ||
cycle = cycle.map(x=>{ | ||
let p = x.trim(); | ||
if(ep.isWebPath(p)){ | ||
if(ep.isWebPath(rootPath)&&p.length>=rpl&&p.substring(0,rpl)==rootPath){ | ||
p = p.substring(rpl); | ||
} | ||
} | ||
else{ | ||
p = ep.relativePath(rootPath,p).replace(/\\/g,"/"); | ||
} | ||
if(p.length && p.charAt(p.length-1)=='#'){ | ||
p = p.substring(0,p.length-1); | ||
} | ||
return p; | ||
}); | ||
} | ||
let ve = new ts.ValidationError(messageRegistry.CIRCULAR_REFS_IN_JSON_SCHEMA_DETAILS,{ | ||
cycle : cycle.join(" -> ") | ||
}); | ||
throw ve; | ||
} | ||
} | ||
} | ||
function toProperWebURL(p:string):string{ | ||
if(p==null||p.trim().length==0){ | ||
return p; | ||
} | ||
let l = "https://".length; | ||
if(p.length>=l && p.substring(0,l)=="https://"){ | ||
return p; | ||
} | ||
p = p.replace("//","__\/DOUBLESLASH\/__"); | ||
p = p.replace(/^([a-zA-Z]):/,'$1__\/COLON\/__'); | ||
let protoclStr = "https://__/APPENDED_PROTOCOL/__"; | ||
if(p.charAt(0)!="/"){ | ||
protoclStr += "/"; | ||
} | ||
return protoclStr + p; | ||
} | ||
function decodeURL(p:string):string{ | ||
if(p==null||p.trim().length==0){ | ||
return p; | ||
} | ||
let protocolStr = "https://__/APPENDED_PROTOCOL/__"; | ||
let l = protocolStr.length; | ||
if(p.length<l||p.substring(0,l)!=protocolStr){ | ||
return p; | ||
} | ||
p = p.substring(l,p.length); | ||
if(p.indexOf("__/COLON/__")>0&&p.charAt(0)=="/"){ | ||
p = p.substring(1); | ||
} | ||
p = p.replace("__/DOUBLESLASH/__","//").replace("__/COLON/__",":"); | ||
return p; | ||
} | ||
export interface ValidationError{ | ||
@@ -1131,3 +1224,3 @@ code:string | ||
} | ||
var key = "__SCHEMA_" + content + contextPath; | ||
var key = "__SCHEMA_" + (""+content).trim() + contextPath.trim(); | ||
return key; | ||
@@ -1371,1 +1464,90 @@ }; | ||
} | ||
class RefPath { | ||
constructor(public segments:string[]){} | ||
length(){ | ||
return this.segments.length | ||
} | ||
} | ||
class SchemaNode { | ||
constructor(public url:string){} | ||
processed = false; | ||
refFromRoot:RefPath = new RefPath([]) | ||
refsOut: {[key:string]:RefPath} = {} | ||
referees: {[key:string]:SchemaNode} = {} | ||
} | ||
class SchemaGraph { | ||
constructor(public rootPath:string){} | ||
private nodes:{[key:string]:SchemaNode} = {} | ||
node(url:string){ | ||
return this.nodes[url]; | ||
} | ||
addNode(json:any,schemaPath:string):string[]{ | ||
let node = this.nodes[schemaPath]; | ||
if(node){ | ||
if(node.processed){ | ||
return; | ||
} | ||
} | ||
else{ | ||
node = new SchemaNode(schemaPath); | ||
this.nodes[schemaPath] = node; | ||
} | ||
let refs = extractRefs(json); | ||
let referees = Object.keys(node.referees).map(x=>node.referees[x]); | ||
let cycle:string[] = null; | ||
for(let ref of refs){ | ||
const referee = node.referees[ref]; | ||
if(referee){ | ||
cycle = [this.rootPath].concat(referee.refFromRoot.segments).concat(referee.refsOut[schemaPath].segments).concat([ref]); | ||
} | ||
let refNode = this.nodes[ref]; | ||
if(!refNode){ | ||
refNode = new SchemaNode(ref); | ||
refNode.refFromRoot = new RefPath(node.refFromRoot.segments.concat([ref])); | ||
this.nodes[ref] = refNode; | ||
} | ||
const newReferees:SchemaNode[] = referees.filter(x=>!refNode.referees[x.url]); | ||
for(let r of newReferees){ | ||
refNode.referees[r.url] = r; | ||
r.refsOut[ref] = new RefPath(r.refsOut[schemaPath].segments.concat([ref])); | ||
} | ||
node.refsOut[ref] = new RefPath([ref]); | ||
refNode.referees[node.url] = node; | ||
} | ||
node.processed = true; | ||
return cycle; | ||
} | ||
} | ||
function extractRefs(obj:any):string[]{ | ||
return _.unique(doExtractRefs(obj,[])) | ||
} | ||
function doExtractRefs(obj:any,refs:string[]):string[]{ | ||
if(Array.isArray(obj)){ | ||
obj.forEach(x=>doExtractRefs(x,refs)); | ||
} | ||
else if(obj != null && typeof obj === "object"){ | ||
Object.keys(obj).forEach(x=>{ | ||
if(x === "$ref" && typeof obj[x] === "string"){ | ||
refs.push(decodeURL(obj[x])); | ||
} | ||
else if(typeof obj[x] === "object"){ | ||
doExtractRefs(obj[x],refs); | ||
} | ||
}); | ||
} | ||
return refs; | ||
} |
@@ -239,2 +239,6 @@ export interface IValidationPath{ | ||
library(name:string):IParsedTypeCollection; | ||
libraries():{[key:string]:IParsedTypeCollection} | ||
addLibrary(namespace:string,lib:IParsedTypeCollection):void | ||
} | ||
@@ -241,0 +245,0 @@ export interface ITypeRegistry { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2083346
41681
137