z-schema 7.0.0 → 7.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/ZSchema.ts CHANGED
@@ -198,6 +198,11 @@ export class ZSchema {
198
198
  this.setRemoteReference('http://json-schema.org/draft-04/hyper-schema', Draft4HyperSchema, metaschemaOptions);
199
199
  }
200
200
 
201
+ /** Used by SchemaCache to break circular dependency with SchemaCompilation */
202
+ _compileSchema(report: Report, schema: unknown): boolean {
203
+ return SchemaCompilation.compileSchema.call(this, report, schema);
204
+ }
205
+
201
206
  /**
202
207
  * @param schema - JSON object representing schema
203
208
  * @returns {boolean} true if schema is valid.
package/umd/ZSchema.js CHANGED
@@ -11976,257 +11976,6 @@
11976
11976
  var lodash_isequalExports = requireLodash_isequal();
11977
11977
  var isequal = /*@__PURE__*/getDefaultExportFromCjs(lodash_isequalExports);
11978
11978
 
11979
- function mergeReference(scope, ref) {
11980
- if (isAbsoluteUri(ref)) {
11981
- return ref;
11982
- }
11983
- let joinedScope = scope.join('');
11984
- const isScopeAbsolute = isAbsoluteUri(joinedScope);
11985
- const isScopeRelative = isRelativeUri(joinedScope);
11986
- const isRefRelative = isRelativeUri(ref);
11987
- let toRemove;
11988
- if (isScopeAbsolute && isRefRelative) {
11989
- toRemove = joinedScope.match(/\/[^/]*$/);
11990
- if (toRemove) {
11991
- joinedScope = joinedScope.slice(0, toRemove.index + 1);
11992
- }
11993
- }
11994
- else if (isScopeRelative && isRefRelative) {
11995
- joinedScope = '';
11996
- }
11997
- else {
11998
- toRemove = joinedScope.match(/[^#/]+$/);
11999
- if (toRemove) {
12000
- joinedScope = joinedScope.slice(0, toRemove.index);
12001
- }
12002
- }
12003
- let res = joinedScope + ref;
12004
- res = res.replace(/##/, '#');
12005
- return res;
12006
- }
12007
- function collectReferences(obj, results, scope, path) {
12008
- results = results || [];
12009
- scope = scope || [];
12010
- path = path || [];
12011
- if (typeof obj !== 'object' || obj === null) {
12012
- return results;
12013
- }
12014
- if (typeof obj.id === 'string') {
12015
- scope.push(obj.id);
12016
- }
12017
- if (typeof obj.$ref === 'string' && typeof obj.__$refResolved === 'undefined') {
12018
- results.push({
12019
- ref: mergeReference(scope, obj.$ref),
12020
- key: '$ref',
12021
- obj: obj,
12022
- path: path.slice(0),
12023
- });
12024
- }
12025
- if (typeof obj.$schema === 'string' && typeof obj.__$schemaResolved === 'undefined') {
12026
- results.push({
12027
- ref: mergeReference(scope, obj.$schema),
12028
- key: '$schema',
12029
- obj: obj,
12030
- path: path.slice(0),
12031
- });
12032
- }
12033
- let idx;
12034
- if (Array.isArray(obj)) {
12035
- idx = obj.length;
12036
- while (idx--) {
12037
- path.push(idx.toString());
12038
- collectReferences(obj[idx], results, scope, path);
12039
- path.pop();
12040
- }
12041
- }
12042
- else {
12043
- const keys = Object.keys(obj);
12044
- idx = keys.length;
12045
- while (idx--) {
12046
- // do not recurse through resolved references and other z-schema props
12047
- if (keys[idx].indexOf('__$') === 0) {
12048
- continue;
12049
- }
12050
- path.push(keys[idx]);
12051
- collectReferences(obj[keys[idx]], results, scope, path);
12052
- path.pop();
12053
- }
12054
- }
12055
- if (typeof obj.id === 'string') {
12056
- scope.pop();
12057
- }
12058
- return results;
12059
- }
12060
- const compileArrayOfSchemasLoop = function (mainReport, arr) {
12061
- let idx = arr.length, compiledCount = 0;
12062
- while (idx--) {
12063
- // try to compile each schema separately
12064
- const report = new Report(mainReport);
12065
- const isValid = compileSchema.call(this, report, arr[idx]);
12066
- if (isValid) {
12067
- compiledCount++;
12068
- }
12069
- // copy errors to report
12070
- mainReport.errors = mainReport.errors.concat(report.errors);
12071
- }
12072
- return compiledCount;
12073
- };
12074
- function findId$1(arr, id) {
12075
- let idx = arr.length;
12076
- while (idx--) {
12077
- if (arr[idx].id === id) {
12078
- return arr[idx];
12079
- }
12080
- }
12081
- return null;
12082
- }
12083
- const compileArrayOfSchemas = function (report, arr) {
12084
- let compiled = 0, lastLoopCompiled;
12085
- do {
12086
- // remove all UNRESOLVABLE_REFERENCE errors before compiling array again
12087
- let idx = report.errors.length;
12088
- while (idx--) {
12089
- if (report.errors[idx].code === 'UNRESOLVABLE_REFERENCE') {
12090
- report.errors.splice(idx, 1);
12091
- }
12092
- }
12093
- // remember how many were compiled in the last loop
12094
- lastLoopCompiled = compiled;
12095
- // count how many are compiled now
12096
- compiled = compileArrayOfSchemasLoop.call(this, report, arr);
12097
- // fix __$missingReferences if possible
12098
- idx = arr.length;
12099
- while (idx--) {
12100
- const sch = arr[idx];
12101
- if (sch.__$missingReferences) {
12102
- let idx2 = sch.__$missingReferences.length;
12103
- while (idx2--) {
12104
- const refObj = sch.__$missingReferences[idx2];
12105
- const response = findId$1(arr, refObj.ref);
12106
- if (response) {
12107
- // this might create circular references
12108
- refObj.obj['__' + refObj.key + 'Resolved'] = response;
12109
- // it's resolved now so delete it
12110
- sch.__$missingReferences.splice(idx2, 1);
12111
- }
12112
- }
12113
- if (sch.__$missingReferences.length === 0) {
12114
- delete sch.__$missingReferences;
12115
- }
12116
- }
12117
- }
12118
- // keep repeating if not all compiled and at least one more was compiled in the last loop
12119
- } while (compiled !== arr.length && compiled !== lastLoopCompiled);
12120
- return report.isValid();
12121
- };
12122
- function compileSchema(report, schema) {
12123
- report.commonErrorMessage = 'SCHEMA_COMPILATION_FAILED';
12124
- // if schema is a string, assume it's a uri
12125
- if (typeof schema === 'string') {
12126
- const loadedSchema = getSchemaByUri.call(this, report, schema);
12127
- if (!loadedSchema) {
12128
- report.addError('SCHEMA_NOT_REACHABLE', [schema]);
12129
- return false;
12130
- }
12131
- schema = loadedSchema;
12132
- }
12133
- // if schema is an array, assume it's an array of schemas
12134
- if (Array.isArray(schema)) {
12135
- return compileArrayOfSchemas.call(this, report, schema);
12136
- }
12137
- // if we have an id than it should be cached already (if this instance has compiled it)
12138
- if (schema.__$compiled && schema.id && checkCacheForUri.call(this, schema.id) === false) {
12139
- schema.__$compiled = undefined;
12140
- }
12141
- // do not re-compile schemas
12142
- if (schema.__$compiled) {
12143
- return true;
12144
- }
12145
- if (schema.id && typeof schema.id === 'string') {
12146
- // add this to our schemaCache (before compilation in case we have references including id)
12147
- cacheSchemaByUri.call(this, schema.id, schema);
12148
- }
12149
- // this method can be called recursively, so we need to remember our root
12150
- let isRoot = false;
12151
- if (!report.rootSchema) {
12152
- report.rootSchema = schema;
12153
- isRoot = true;
12154
- }
12155
- // delete all __$missingReferences from previous compilation attempts
12156
- const isValidExceptReferences = report.isValid();
12157
- delete schema.__$missingReferences;
12158
- // collect all references that need to be resolved - $ref and $schema
12159
- const refs = collectReferences.call(this, schema);
12160
- let idx = refs.length;
12161
- while (idx--) {
12162
- // resolve all the collected references into __xxxResolved pointer
12163
- const refObj = refs[idx];
12164
- let response = getSchemaByUri.call(this, report, refObj.ref, schema);
12165
- // we can try to use custom schemaReader if available
12166
- if (!response) {
12167
- const schemaReader = this.getSchemaReader();
12168
- if (schemaReader) {
12169
- // it's supposed to return a valid schema
12170
- const s = schemaReader(refObj.ref);
12171
- if (s) {
12172
- // it needs to have the id
12173
- s.id = refObj.ref;
12174
- // try to compile the schema
12175
- const subreport = new Report(report);
12176
- if (!compileSchema.call(this, subreport, s)) {
12177
- // copy errors to report
12178
- report.errors = report.errors.concat(subreport.errors);
12179
- }
12180
- else {
12181
- response = getSchemaByUri.call(this, report, refObj.ref, schema);
12182
- }
12183
- }
12184
- }
12185
- }
12186
- if (!response) {
12187
- const hasNotValid = report.hasError('REMOTE_NOT_VALID', [refObj.ref]);
12188
- const isAbsolute = isAbsoluteUri(refObj.ref);
12189
- let isDownloaded = false;
12190
- const ignoreUnresolvableRemotes = this.options.ignoreUnresolvableReferences === true;
12191
- if (isAbsolute) {
12192
- // we shouldn't add UNRESOLVABLE_REFERENCE for schemas we already have downloaded
12193
- // and set through setRemoteReference method
12194
- isDownloaded = checkCacheForUri.call(this, refObj.ref);
12195
- }
12196
- if (hasNotValid) ;
12197
- else if (ignoreUnresolvableRemotes && isAbsolute) ;
12198
- else if (isDownloaded) ;
12199
- else {
12200
- Array.prototype.push.apply(report.path, refObj.path);
12201
- report.addError('UNRESOLVABLE_REFERENCE', [refObj.ref]);
12202
- report.path = report.path.slice(0, -refObj.path.length);
12203
- // pusblish unresolved references out
12204
- if (isValidExceptReferences) {
12205
- schema.__$missingReferences = schema.__$missingReferences || [];
12206
- schema.__$missingReferences.push(refObj);
12207
- }
12208
- }
12209
- }
12210
- // this might create circular references
12211
- refObj.obj['__' + refObj.key + 'Resolved'] = response;
12212
- }
12213
- const isValid = report.isValid();
12214
- if (isValid) {
12215
- schema.__$compiled = true;
12216
- }
12217
- else {
12218
- if (schema.id && typeof schema.id === 'string') {
12219
- // remove this schema from schemaCache because it failed to compile
12220
- removeFromCacheByUri.call(this, schema.id);
12221
- }
12222
- }
12223
- // we don't need the root pointer anymore
12224
- if (isRoot) {
12225
- report.rootSchema = undefined;
12226
- }
12227
- return isValid;
12228
- }
12229
-
12230
11979
  const SchemaValidators = {
12231
11980
  $ref: function (report, schema) {
12232
11981
  // http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
@@ -12872,7 +12621,7 @@
12872
12621
  // if (res && res[0] === "/") { res = res.slice(1); }
12873
12622
  return res;
12874
12623
  }
12875
- function findId(schema, id) {
12624
+ function findId$1(schema, id) {
12876
12625
  // process only arrays and objects
12877
12626
  if (typeof schema !== 'object' || schema === null) {
12878
12627
  return;
@@ -12890,7 +12639,7 @@
12890
12639
  if (Array.isArray(schema)) {
12891
12640
  idx = schema.length;
12892
12641
  while (idx--) {
12893
- result = findId(schema[idx], id);
12642
+ result = findId$1(schema[idx], id);
12894
12643
  if (result) {
12895
12644
  return result;
12896
12645
  }
@@ -12904,7 +12653,7 @@
12904
12653
  if (k.indexOf('__$') === 0) {
12905
12654
  continue;
12906
12655
  }
12907
- result = findId(schema[k], id);
12656
+ result = findId$1(schema[k], id);
12908
12657
  if (result) {
12909
12658
  return result;
12910
12659
  }
@@ -12984,7 +12733,7 @@
12984
12733
  }
12985
12734
  else {
12986
12735
  remoteReport = new Report(report);
12987
- if (compileSchema.call(this, remoteReport, result)) {
12736
+ if (this._compileSchema(remoteReport, result)) {
12988
12737
  const savedOptions = this.options;
12989
12738
  try {
12990
12739
  // If custom validationOptions were provided to setRemoteReference(),
@@ -13013,7 +12762,7 @@
13013
12762
  const key = decodeJSONPointer(parts[idx]);
13014
12763
  if (idx === 0) {
13015
12764
  // it's an id
13016
- result = findId(result, key);
12765
+ result = findId$1(result, key);
13017
12766
  }
13018
12767
  else {
13019
12768
  // it's a path behind id
@@ -13024,6 +12773,257 @@
13024
12773
  return result;
13025
12774
  }
13026
12775
 
12776
+ function mergeReference(scope, ref) {
12777
+ if (isAbsoluteUri(ref)) {
12778
+ return ref;
12779
+ }
12780
+ let joinedScope = scope.join('');
12781
+ const isScopeAbsolute = isAbsoluteUri(joinedScope);
12782
+ const isScopeRelative = isRelativeUri(joinedScope);
12783
+ const isRefRelative = isRelativeUri(ref);
12784
+ let toRemove;
12785
+ if (isScopeAbsolute && isRefRelative) {
12786
+ toRemove = joinedScope.match(/\/[^/]*$/);
12787
+ if (toRemove) {
12788
+ joinedScope = joinedScope.slice(0, toRemove.index + 1);
12789
+ }
12790
+ }
12791
+ else if (isScopeRelative && isRefRelative) {
12792
+ joinedScope = '';
12793
+ }
12794
+ else {
12795
+ toRemove = joinedScope.match(/[^#/]+$/);
12796
+ if (toRemove) {
12797
+ joinedScope = joinedScope.slice(0, toRemove.index);
12798
+ }
12799
+ }
12800
+ let res = joinedScope + ref;
12801
+ res = res.replace(/##/, '#');
12802
+ return res;
12803
+ }
12804
+ function collectReferences(obj, results, scope, path) {
12805
+ results = results || [];
12806
+ scope = scope || [];
12807
+ path = path || [];
12808
+ if (typeof obj !== 'object' || obj === null) {
12809
+ return results;
12810
+ }
12811
+ if (typeof obj.id === 'string') {
12812
+ scope.push(obj.id);
12813
+ }
12814
+ if (typeof obj.$ref === 'string' && typeof obj.__$refResolved === 'undefined') {
12815
+ results.push({
12816
+ ref: mergeReference(scope, obj.$ref),
12817
+ key: '$ref',
12818
+ obj: obj,
12819
+ path: path.slice(0),
12820
+ });
12821
+ }
12822
+ if (typeof obj.$schema === 'string' && typeof obj.__$schemaResolved === 'undefined') {
12823
+ results.push({
12824
+ ref: mergeReference(scope, obj.$schema),
12825
+ key: '$schema',
12826
+ obj: obj,
12827
+ path: path.slice(0),
12828
+ });
12829
+ }
12830
+ let idx;
12831
+ if (Array.isArray(obj)) {
12832
+ idx = obj.length;
12833
+ while (idx--) {
12834
+ path.push(idx.toString());
12835
+ collectReferences(obj[idx], results, scope, path);
12836
+ path.pop();
12837
+ }
12838
+ }
12839
+ else {
12840
+ const keys = Object.keys(obj);
12841
+ idx = keys.length;
12842
+ while (idx--) {
12843
+ // do not recurse through resolved references and other z-schema props
12844
+ if (keys[idx].indexOf('__$') === 0) {
12845
+ continue;
12846
+ }
12847
+ path.push(keys[idx]);
12848
+ collectReferences(obj[keys[idx]], results, scope, path);
12849
+ path.pop();
12850
+ }
12851
+ }
12852
+ if (typeof obj.id === 'string') {
12853
+ scope.pop();
12854
+ }
12855
+ return results;
12856
+ }
12857
+ const compileArrayOfSchemasLoop = function (mainReport, arr) {
12858
+ let idx = arr.length, compiledCount = 0;
12859
+ while (idx--) {
12860
+ // try to compile each schema separately
12861
+ const report = new Report(mainReport);
12862
+ const isValid = compileSchema.call(this, report, arr[idx]);
12863
+ if (isValid) {
12864
+ compiledCount++;
12865
+ }
12866
+ // copy errors to report
12867
+ mainReport.errors = mainReport.errors.concat(report.errors);
12868
+ }
12869
+ return compiledCount;
12870
+ };
12871
+ function findId(arr, id) {
12872
+ let idx = arr.length;
12873
+ while (idx--) {
12874
+ if (arr[idx].id === id) {
12875
+ return arr[idx];
12876
+ }
12877
+ }
12878
+ return null;
12879
+ }
12880
+ const compileArrayOfSchemas = function (report, arr) {
12881
+ let compiled = 0, lastLoopCompiled;
12882
+ do {
12883
+ // remove all UNRESOLVABLE_REFERENCE errors before compiling array again
12884
+ let idx = report.errors.length;
12885
+ while (idx--) {
12886
+ if (report.errors[idx].code === 'UNRESOLVABLE_REFERENCE') {
12887
+ report.errors.splice(idx, 1);
12888
+ }
12889
+ }
12890
+ // remember how many were compiled in the last loop
12891
+ lastLoopCompiled = compiled;
12892
+ // count how many are compiled now
12893
+ compiled = compileArrayOfSchemasLoop.call(this, report, arr);
12894
+ // fix __$missingReferences if possible
12895
+ idx = arr.length;
12896
+ while (idx--) {
12897
+ const sch = arr[idx];
12898
+ if (sch.__$missingReferences) {
12899
+ let idx2 = sch.__$missingReferences.length;
12900
+ while (idx2--) {
12901
+ const refObj = sch.__$missingReferences[idx2];
12902
+ const response = findId(arr, refObj.ref);
12903
+ if (response) {
12904
+ // this might create circular references
12905
+ refObj.obj['__' + refObj.key + 'Resolved'] = response;
12906
+ // it's resolved now so delete it
12907
+ sch.__$missingReferences.splice(idx2, 1);
12908
+ }
12909
+ }
12910
+ if (sch.__$missingReferences.length === 0) {
12911
+ delete sch.__$missingReferences;
12912
+ }
12913
+ }
12914
+ }
12915
+ // keep repeating if not all compiled and at least one more was compiled in the last loop
12916
+ } while (compiled !== arr.length && compiled !== lastLoopCompiled);
12917
+ return report.isValid();
12918
+ };
12919
+ function compileSchema(report, schema) {
12920
+ report.commonErrorMessage = 'SCHEMA_COMPILATION_FAILED';
12921
+ // if schema is a string, assume it's a uri
12922
+ if (typeof schema === 'string') {
12923
+ const loadedSchema = getSchemaByUri.call(this, report, schema);
12924
+ if (!loadedSchema) {
12925
+ report.addError('SCHEMA_NOT_REACHABLE', [schema]);
12926
+ return false;
12927
+ }
12928
+ schema = loadedSchema;
12929
+ }
12930
+ // if schema is an array, assume it's an array of schemas
12931
+ if (Array.isArray(schema)) {
12932
+ return compileArrayOfSchemas.call(this, report, schema);
12933
+ }
12934
+ // if we have an id than it should be cached already (if this instance has compiled it)
12935
+ if (schema.__$compiled && schema.id && checkCacheForUri.call(this, schema.id) === false) {
12936
+ schema.__$compiled = undefined;
12937
+ }
12938
+ // do not re-compile schemas
12939
+ if (schema.__$compiled) {
12940
+ return true;
12941
+ }
12942
+ if (schema.id && typeof schema.id === 'string') {
12943
+ // add this to our schemaCache (before compilation in case we have references including id)
12944
+ cacheSchemaByUri.call(this, schema.id, schema);
12945
+ }
12946
+ // this method can be called recursively, so we need to remember our root
12947
+ let isRoot = false;
12948
+ if (!report.rootSchema) {
12949
+ report.rootSchema = schema;
12950
+ isRoot = true;
12951
+ }
12952
+ // delete all __$missingReferences from previous compilation attempts
12953
+ const isValidExceptReferences = report.isValid();
12954
+ delete schema.__$missingReferences;
12955
+ // collect all references that need to be resolved - $ref and $schema
12956
+ const refs = collectReferences.call(this, schema);
12957
+ let idx = refs.length;
12958
+ while (idx--) {
12959
+ // resolve all the collected references into __xxxResolved pointer
12960
+ const refObj = refs[idx];
12961
+ let response = getSchemaByUri.call(this, report, refObj.ref, schema);
12962
+ // we can try to use custom schemaReader if available
12963
+ if (!response) {
12964
+ const schemaReader = this.getSchemaReader();
12965
+ if (schemaReader) {
12966
+ // it's supposed to return a valid schema
12967
+ const s = schemaReader(refObj.ref);
12968
+ if (s) {
12969
+ // it needs to have the id
12970
+ s.id = refObj.ref;
12971
+ // try to compile the schema
12972
+ const subreport = new Report(report);
12973
+ if (!compileSchema.call(this, subreport, s)) {
12974
+ // copy errors to report
12975
+ report.errors = report.errors.concat(subreport.errors);
12976
+ }
12977
+ else {
12978
+ response = getSchemaByUri.call(this, report, refObj.ref, schema);
12979
+ }
12980
+ }
12981
+ }
12982
+ }
12983
+ if (!response) {
12984
+ const hasNotValid = report.hasError('REMOTE_NOT_VALID', [refObj.ref]);
12985
+ const isAbsolute = isAbsoluteUri(refObj.ref);
12986
+ let isDownloaded = false;
12987
+ const ignoreUnresolvableRemotes = this.options.ignoreUnresolvableReferences === true;
12988
+ if (isAbsolute) {
12989
+ // we shouldn't add UNRESOLVABLE_REFERENCE for schemas we already have downloaded
12990
+ // and set through setRemoteReference method
12991
+ isDownloaded = checkCacheForUri.call(this, refObj.ref);
12992
+ }
12993
+ if (hasNotValid) ;
12994
+ else if (ignoreUnresolvableRemotes && isAbsolute) ;
12995
+ else if (isDownloaded) ;
12996
+ else {
12997
+ Array.prototype.push.apply(report.path, refObj.path);
12998
+ report.addError('UNRESOLVABLE_REFERENCE', [refObj.ref]);
12999
+ report.path = report.path.slice(0, -refObj.path.length);
13000
+ // pusblish unresolved references out
13001
+ if (isValidExceptReferences) {
13002
+ schema.__$missingReferences = schema.__$missingReferences || [];
13003
+ schema.__$missingReferences.push(refObj);
13004
+ }
13005
+ }
13006
+ }
13007
+ // this might create circular references
13008
+ refObj.obj['__' + refObj.key + 'Resolved'] = response;
13009
+ }
13010
+ const isValid = report.isValid();
13011
+ if (isValid) {
13012
+ schema.__$compiled = true;
13013
+ }
13014
+ else {
13015
+ if (schema.id && typeof schema.id === 'string') {
13016
+ // remove this schema from schemaCache because it failed to compile
13017
+ removeFromCacheByUri.call(this, schema.id);
13018
+ }
13019
+ }
13020
+ // we don't need the root pointer anymore
13021
+ if (isRoot) {
13022
+ report.rootSchema = undefined;
13023
+ }
13024
+ return isValid;
13025
+ }
13026
+
13027
13027
  var id$1 = "http://json-schema.org/draft-04/schema#";
13028
13028
  var $schema$1 = "http://json-schema.org/draft-04/schema#";
13029
13029
  var description = "Core schema meta-schema";
@@ -13565,6 +13565,10 @@
13565
13565
  this.setRemoteReference('http://json-schema.org/draft-04/schema', Draft4Schema, metaschemaOptions);
13566
13566
  this.setRemoteReference('http://json-schema.org/draft-04/hyper-schema', Draft4HyperSchema, metaschemaOptions);
13567
13567
  }
13568
+ /** Used by SchemaCache to break circular dependency with SchemaCompilation */
13569
+ _compileSchema(report, schema) {
13570
+ return compileSchema.call(this, report, schema);
13571
+ }
13568
13572
  /**
13569
13573
  * @param schema - JSON object representing schema
13570
13574
  * @returns {boolean} true if schema is valid.