Skip to content

Commit 384afea

Browse files
authored
Merge pull request #668 from postmanlabs/feature/analytics-logging
[APIDES-1706] Update schemapack to return analytics from the module and refactor deref
2 parents 70e779d + 77b5c9f commit 384afea

File tree

6 files changed

+202
-110
lines changed

6 files changed

+202
-110
lines changed

lib/deref.js

Lines changed: 130 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const _ = require('lodash'),
2727
'float',
2828
'double'
2929
],
30+
RESOLVE_REF_DEFAULTS = {
31+
resolveFor: 'CONVERSION',
32+
resolveTo: 'schema',
33+
stack: 0,
34+
stackLimit: 10,
35+
isAllOf: false
36+
},
3037
DEFAULT_SCHEMA_UTILS = require('./30XUtils/schemaUtils30X'),
3138
traverseUtility = require('traverse'),
3239
PROPERTIES_TO_ASSIGN_ON_CASCADE = ['type', 'nullable'];
@@ -84,36 +91,42 @@ module.exports = {
8491
/**
8592
* Creates a schema that's a union of all input schemas (only type: object is supported)
8693
*
87-
* @param {array} schemaArr - array of schemas, all of which must be valid in the returned object
88-
* @param {string} parameterSourceOption tells that the schema object is of request or response
89-
* @param {*} components components in openapi spec.
90-
* @param {object} schemaResolutionCache stores already resolved references
91-
* @param {*} resolveFor - resolve refs for validation/conversion (value to be one of VALIDATION/CONVERSION)
92-
* @param {string} resolveTo The desired JSON-generation mechanism (schema: prefer using the JSONschema to
94+
* @param {array} schemaArr REQUIRED - array of schemas, all of which must be valid in the returned object
95+
* @param {string} parameterSourceOption REQUIRED tells that the schema object is of request or response
96+
* @param {*} components REQUIRED components in openapi spec.
97+
* @param {object} options - REQUIRED a list of options to indicate the type of resolution needed.
98+
* @param {*} options.resolveFor - resolve refs for validation/conversion (value to be one of VALIDATION/CONVERSION)
99+
* @param {string} options.resolveTo The desired JSON-generation mechanism (schema: prefer using the JSONschema to
93100
generate a fake object, example: use specified examples as-is). Default: schema
94-
* @param {*} stack counter which keeps a tab on nested schemas
95-
* @param {*} seenRef References that are repeated. Used to identify circular references.
96-
* @param {*} stackLimit Depth to which the schema should be resolved.
101+
* @param {*} options.stack counter which keeps a tab on nested schemas
102+
* @param {*} options.seenRef References that are repeated. Used to identify circular references.
103+
* @param {*} options.stackLimit Depth to which the schema should be resolved.
97104
* @returns {*} schema - schema that adheres to all individual schemas in schemaArr
98105
*/
99-
resolveAllOf: function (schemaArr, parameterSourceOption, components, schemaResolutionCache,
100-
resolveFor = 'CONVERSION', resolveTo = 'schema', stack = 0, seenRef, stackLimit) {
106+
resolveAllOf: function (schemaArr, parameterSourceOption, components, {
107+
resolveFor = RESOLVE_REF_DEFAULTS.resolveFor,
108+
resolveTo = RESOLVE_REF_DEFAULTS.resolveTo,
109+
stack = RESOLVE_REF_DEFAULTS.stack,
110+
seenRef = {},
111+
stackLimit = RESOLVE_REF_DEFAULTS.stackLimit,
112+
analytics = {}
113+
}) {
101114

102115
if (!(schemaArr instanceof Array)) {
103116
return null;
104117
}
105118

106119
if (schemaArr.length === 1) {
107120
// for just one entry in allOf, don't need to enforce type: object restriction
108-
return this.resolveRefs(schemaArr[0], parameterSourceOption, components, schemaResolutionCache, resolveFor,
109-
resolveTo, stack, seenRef, stackLimit);
121+
return this.resolveRefs(schemaArr[0], parameterSourceOption, components,
122+
{ stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, analytics });
110123
}
111124

112125
try {
113126
return mergeAllOf({
114127
allOf: schemaArr.map((schema) => {
115-
return this.resolveRefs(schema, parameterSourceOption, components, schemaResolutionCache, resolveFor,
116-
resolveTo, stack, seenRef, stackLimit, true);
128+
return this.resolveRefs(schema, parameterSourceOption, components,
129+
{ stack, seenRef: _.cloneDeep(seenRef), resolveFor, resolveTo, stackLimit, isAllOf: true, analytics });
117130
})
118131
}, {
119132
resolvers: {
@@ -130,33 +143,41 @@ module.exports = {
130143

131144
/**
132145
* Resolves references to components for a given schema.
133-
* @param {*} schema (openapi) to resolve references.
134-
* @param {string} parameterSourceOption tells that the schema object is of request or response
135-
* @param {*} components components in openapi spec.
136-
* @param {object} schemaResolutionCache stores already resolved references - more structure detail below
137-
* {'schema reference key': {
138-
* maxStack {Integer} : Defined as how deep of nesting level we reached while resolving schema that's being cached
139-
* resLevel {Integer} : Defined as nesting level at which schema that's being cached was resolved
140-
* schema {Object} : resolved schema that will be cached
141-
* }}
142-
* @param {*} resolveFor - resolve refs for validation/conversion (value to be one of VALIDATION/CONVERSION)
143-
* @param {string} resolveTo The desired JSON-generation mechanism (schema: prefer using the JSONschema to
146+
* @param {*} schema REQUIRED (openapi) to resolve references.
147+
* @param {string} parameterSourceOption REQUIRED tells that the schema object is of request or response
148+
* @param {*} components REQUIRED components in openapi spec.
149+
* @param {object} options REQUIRED a list of options to indicate the type of resolution needed
150+
* @param {*} options.resolveFor - resolve refs for validation/conversion (value to be one of VALIDATION/CONVERSION)
151+
* @param {string} options.resolveTo The desired JSON-generation mechanism (schema: prefer using the JSONschema to
144152
generate a fake object, example: use specified examples as-is). Default: schema
145-
* @param {*} stack counter which keeps a tab on nested schemas
146-
* @param {*} seenRef - References that are repeated. Used to identify circular references.
147-
* @param {*} stackLimit Depth to which the schema should be resolved.
148-
* @returns {*} schema satisfying JSON-schema-faker.
153+
* @param {number} options.stack counter which keeps a tab on nested schemas
154+
* @param {*} otions.seenRef - References that are repeated. Used to identify circular references.
155+
* @param {number} options.stackLimit Depth to which the schema should be resolved.
156+
* @param {Boolean} options.isAllOf
157+
* @param {object} options.analytics
158+
* @returns {*} schema satisfying JSON-schema-faker.
149159
*/
150160

151-
resolveRefs: function (schema, parameterSourceOption, components, schemaResolutionCache,
152-
resolveFor = 'CONVERSION', resolveTo = 'schema', stack = 0, seenRef = {}, stackLimit = 10, isAllOf = false) {
161+
resolveRefs: function (schema, parameterSourceOption, components, {
162+
resolveFor = RESOLVE_REF_DEFAULTS.resolveFor,
163+
resolveTo = RESOLVE_REF_DEFAULTS.resolveTo,
164+
stack = RESOLVE_REF_DEFAULTS.stack,
165+
seenRef = {},
166+
stackLimit = RESOLVE_REF_DEFAULTS.stackLimit,
167+
isAllOf = RESOLVE_REF_DEFAULTS.isAllOf,
168+
analytics = {}
169+
}) {
153170
var resolvedSchema, prop, splitRef,
154171
ERR_TOO_MANY_LEVELS = '<Error: Too many levels of nesting to fake this schema>';
155172
let concreteUtils = components && components.hasOwnProperty('concreteUtils') ?
156173
components.concreteUtils :
157174
DEFAULT_SCHEMA_UTILS;
175+
176+
if (analytics.actualStack < stack) {
177+
analytics.actualStack = stack;
178+
}
179+
158180
stack++;
159-
schemaResolutionCache = schemaResolutionCache || {};
160181

161182
if (stack > stackLimit) {
162183
return { value: ERR_TOO_MANY_LEVELS };
@@ -168,23 +189,43 @@ module.exports = {
168189

169190
if (schema.anyOf) {
170191
if (resolveFor === 'CONVERSION') {
171-
return this.resolveRefs(schema.anyOf[0], parameterSourceOption, components, schemaResolutionCache, resolveFor,
172-
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
192+
return this.resolveRefs(schema.anyOf[0], parameterSourceOption, components, {
193+
resolveFor,
194+
resolveTo,
195+
stack,
196+
seenRef: _.cloneDeep(seenRef),
197+
stackLimit,
198+
analytics
199+
});
173200
}
174201
return { anyOf: _.map(schema.anyOf, (schemaElement) => {
175202
PROPERTIES_TO_ASSIGN_ON_CASCADE.forEach((prop) => {
176203
if (_.isNil(schemaElement[prop]) && !_.isNil(schema[prop])) {
177204
schemaElement[prop] = schema[prop];
178205
}
179206
});
180-
return this.resolveRefs(schemaElement, parameterSourceOption, components, schemaResolutionCache, resolveFor,
181-
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
207+
return this.resolveRefs(schemaElement, parameterSourceOption, components,
208+
{
209+
resolveFor,
210+
resolveTo,
211+
stack,
212+
seenRef: _.cloneDeep(seenRef),
213+
stackLimit,
214+
analytics
215+
});
182216
}) };
183217
}
184218
if (schema.oneOf) {
185219
if (resolveFor === 'CONVERSION') {
186-
return this.resolveRefs(schema.oneOf[0], parameterSourceOption, components, schemaResolutionCache, resolveFor,
187-
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
220+
return this.resolveRefs(schema.oneOf[0], parameterSourceOption, components,
221+
{
222+
resolveFor,
223+
resolveTo,
224+
stack,
225+
seenRef: _.cloneDeep(seenRef),
226+
stackLimit,
227+
analytics
228+
});
188229
}
189230
return { oneOf: _.map(schema.oneOf, (schemaElement) => {
190231
PROPERTIES_TO_ASSIGN_ON_CASCADE.forEach((prop) => {
@@ -193,13 +234,27 @@ module.exports = {
193234
}
194235
});
195236

196-
return this.resolveRefs(schemaElement, parameterSourceOption, components, schemaResolutionCache,
197-
resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
237+
return this.resolveRefs(schemaElement, parameterSourceOption, components,
238+
{
239+
resolveFor,
240+
resolveTo,
241+
stack,
242+
seenRef: _.cloneDeep(seenRef),
243+
stackLimit,
244+
analytics
245+
});
198246
}) };
199247
}
200248
if (schema.allOf) {
201-
return this.resolveAllOf(schema.allOf, parameterSourceOption, components, schemaResolutionCache, resolveFor,
202-
resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
249+
return this.resolveAllOf(schema.allOf, parameterSourceOption, components,
250+
{
251+
resolveFor,
252+
resolveTo,
253+
stack,
254+
seenRef: _.cloneDeep(seenRef),
255+
stackLimit,
256+
analytics
257+
});
203258
}
204259
if (schema.$ref && _.isFunction(schema.$ref.split)) {
205260
let refKey = schema.$ref,
@@ -241,7 +296,14 @@ module.exports = {
241296
}
242297
if (resolvedSchema) {
243298
let refResolvedSchema = this.resolveRefs(resolvedSchema, parameterSourceOption,
244-
components, schemaResolutionCache, resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
299+
components, {
300+
resolveFor,
301+
resolveTo,
302+
stack,
303+
seenRef: _.cloneDeep(seenRef),
304+
stackLimit,
305+
analytics
306+
});
245307

246308
return refResolvedSchema;
247309
}
@@ -266,7 +328,14 @@ module.exports = {
266328
}
267329
else {
268330
tempSchema.additionalProperties = this.resolveRefs(schema.additionalProperties, parameterSourceOption,
269-
components, schemaResolutionCache, resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
331+
components, {
332+
resolveFor,
333+
resolveTo,
334+
stack,
335+
seenRef: _.cloneDeep(seenRef),
336+
stackLimit,
337+
analytics
338+
});
270339
}
271340
}
272341

@@ -300,7 +369,14 @@ module.exports = {
300369
tempSchema.properties[prop] = _.isEmpty(property) ?
301370
{} :
302371
this.resolveRefs(property, parameterSourceOption, components,
303-
schemaResolutionCache, resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
372+
{
373+
resolveFor,
374+
resolveTo,
375+
stack,
376+
seenRef: _.cloneDeep(seenRef),
377+
stackLimit,
378+
analytics
379+
});
304380
}
305381
}
306382
return tempSchema;
@@ -339,7 +415,14 @@ module.exports = {
339415
let tempSchema = _.omit(schema, ['items', 'additionalProperties']);
340416

341417
tempSchema.items = this.resolveRefs(schema.items, parameterSourceOption,
342-
components, schemaResolutionCache, resolveFor, resolveTo, stack, _.cloneDeep(seenRef), stackLimit);
418+
components, {
419+
resolveFor,
420+
resolveTo,
421+
stack,
422+
seenRef: _.cloneDeep(seenRef),
423+
stackLimit,
424+
analytics
425+
});
343426
return tempSchema;
344427
}
345428
else if (!schema.hasOwnProperty('default')) {

0 commit comments

Comments
 (0)