UNPKG

swagger2-to-object

Version:

Use Swagger v2 JSON Collections to generate sample JavaScript objects for requests and responses

408 lines (318 loc) 11.2 kB
// Ported from https://github.com/swagger-api/swagger-ui (Apache License, Version 2.0) // see: https://github.com/swagger-api/swagger-ui/blob/master/src/core/plugins/samples/fn.js // & https://github.com/swagger-api/swagger-ui/blob/master/src/core/utils.js // // TODO: fix missing immutable import (currently just returns false for isImmutable) //Im = require("immutable") const stringCollection = { ref: "#/definitions/Collection«string»", schema: { "type": "array", "items": { "type": "string" } } } const primitives = { "string": () => "string", "string_email": () => "user@example.com", "string_date-time": () => new Date().toISOString(), "number": () => 0, "number_float": () => 0.0, "integer": () => 0, "boolean": (schema) => typeof schema.default === "boolean" ? schema.default : true } const primitive = (schema) => { schema = objectify(schema); let { type, format } = schema; let fn = primitives[`${type}_${format}`] || primitives[type]; if (isFunc(fn)) { return fn(schema); } return `Unknown Type: ${schema.type}`; } const isFunc = (thing) => typeof (thing) === "function" const isImmutable = (maybe) => false //Im.Iterable.isIterable(maybe) const isObject = (obj) => !!obj && typeof obj === "object" const getRef = (obj) => isObject(obj) ? obj.$ref : undefined const isRef = (obj) => getRef(obj) const normalizeArray = (arr) => Array.isArray(arr) ? arr : [arr]; function objectify(thing) { if (!isObject(thing)) { return {}; } if (isImmutable(thing)) { return thing.toObject(); } return thing; } function resolveRef(refObj, refsLookup) { var ref = getRef(refObj); if (ref === stringCollection.ref) { return stringCollection.schema; } else { var schema = refsLookup[ref]; return schema; } } function genSchemaObject(schema, refsLookup, config = {}, fieldName = null, parentSchema = null, swaggerPath = null) { if (isRef(schema)) { var ref = schema.$ref; schema = resolveRef(schema, refsLookup); schema._$ref = ref; } let { type, example, properties, additionalProperties, items } = objectify(schema); let { includeReadOnly, includeWriteOnly } = config; if (example !== undefined) { return example; } if (!type) { if (properties) { type = "object"; } else if (items) { type = "array"; } else { return; } } if (type === "file") { return; } if (type === "object") { let props = objectify(properties); let obj = {}; for (var name in props) { if (props[name].readOnly && !includeReadOnly) { continue; } if (props[name].writeOnly && !includeWriteOnly) { continue; } if (isRef(props[name])) { props[name] = resolveRef(props[name], refsLookup); } obj[name] = genSchemaObject(props[name], refsLookup, config, name, schema, swaggerPath); } if (additionalProperties === true) { obj.additionalProp1 = {}; } else if (additionalProperties) { let additionalProps = objectify(additionalProperties); let additionalPropVal = genSchemaObject(additionalProps, refsLookup, config, fieldName, schema, swaggerPath); for (let i = 1; i < 4; i++) { obj[`additionalProp${i}`] = additionalPropVal; } } return obj; } if (type === "array") { if (isRef(items)) { items = resolveRef(items, refsLookup); } return [genSchemaObject(items, refsLookup, config, fieldName, schema, swaggerPath)]; } var value; if (schema["enum"]) { if (schema["default"]) { value = schema["default"]; } else { var enumValues = normalizeArray(schema["enum"]).map((v) => v.toLowerCase()); // educated guess based on parent schema reference if (parentSchema && parentSchema._$ref) { var parentRef = parentSchema._$ref.toLowerCase(); value = enumValues.find((v) => parentRef.includes(v)); } // educated guess based on swagger path description if (!value && swaggerPath && swaggerPath.description) { var swaggerPath = swaggerPath.description ? swaggerPath.description.toLowerCase() : ""; value = enumValues.find((v) => swaggerPath.includes(v)); } if (value) { return value; } value = enumValues[0]; } } if (!value) { value = primitive(schema); } if (fieldName && value === primitives.string() ) { value = fieldName; } if (typeof value === "string") { value = value.toLowerCase(); } return value; } function getRefForSchema (schema, unknownTypeCounter) { if (schema.$ref) { return schema.$ref; } else if (isObject(schema.items) && schema.items.$ref) { return schema.items.$ref; } else { return `unknown_type_${unknownTypeCounter}`; } } function genSpecResponseObjects (swaggerSpec, options) { var refsLookup = buildSwaggerRefsLookup(swaggerSpec, options); var specResponses = {}; var unknownTypeCounter = 0; var includeUnknownTypes = options && options.includeUnknownTypes; var paths = swaggerSpec.paths; for (var key in paths) { if (!paths.hasOwnProperty(key)) { continue; } var pathRoot = paths[key]; for (var pathKey in pathRoot) { if (!pathRoot.hasOwnProperty(pathKey)) { continue; } var responses = pathRoot[pathKey].responses; if (!responses) { continue; } for (var responseKey in responses) { if (!responses.hasOwnProperty(responseKey)) { continue; } var response = responses[responseKey]; var schema = response.schema; if (!schema) { continue; } var obj = genSchemaObject(response.schema, refsLookup); var ref = getRefForSchema(schema, unknownTypeCounter); if (!specResponses[ref]) { if (ref.includes("unknown_type_")) { unknownTypeCounter++; if (!includeUnknownTypes) { continue; } } specResponses[ref] = obj; } } } } return specResponses; } function genSpecRequestObjects (swaggerSpec, options) { var refsLookup = buildSwaggerRefsLookup(swaggerSpec, options); var specRequests = {}; var unknownTypeCounter = 0; var includeUnknownTypes = options && options.includeUnknownTypes; var paths = swaggerSpec.paths; for (var key in paths) { if (!paths.hasOwnProperty(key)) { continue; } var pathRoot = paths[key]; for (var pathKey in pathRoot) { if (!pathRoot.hasOwnProperty(pathKey)) { continue; } var path = pathRoot[pathKey]; let {parameter, obj} = genObjectForPathBody(path, refsLookup, options); if (!obj) { continue; } var schema = parameter.schema; var ref = getRefForSchema(schema, unknownTypeCounter); if (!specRequests[ref]) { if (ref.includes("unknown_type_")) { unknownTypeCounter++; if (!includeUnknownTypes) { continue; } } specRequests[ref] = obj; } } } return specRequests; } function genSpecSchemaObjects (swaggerSpec, options) { var refsLookup = buildSwaggerRefsLookup(swaggerSpec, options); var specObjs = {}; for (var key in refsLookup) { if (!refsLookup.hasOwnProperty(key)) { continue; } specObjs[key] = genSchemaObject(refsLookup[key], refsLookup); } return specObjs; } function genObjectForPathBody (swaggerPath, swaggerRefsLookup, options) { var result = { parameter: undefined, obj: undefined }; if (!swaggerPath.parameters || (swaggerPath.parameters.length < 1)) { return result; } swaggerPath.parameters.forEach((p) => { if (result.obj || !p.in || p.in !== "body") { return; } try { result.obj = genSchemaObject(p.schema, swaggerRefsLookup, {}, null, null, swaggerPath); result.parameter = p; } catch (e) { sampleObj = undefined; if (options && options.debug) { console.log(`Error generating sample from schema: ${JSON.stringify(p.schema)}`); console.log(e); } } }); return result; } function buildSwaggerRefsLookup(swaggerSpec, options) { var refsLookup = {}; var refCount = 0; if (options && options.debug) { console.log(`Building refs lookup for Swagger spec '${swaggerSpec.info.title}'...`); } for (var key in swaggerSpec.definitions) { if (swaggerSpec.definitions.hasOwnProperty(key)) { ref = `#/definitions/${key}`; schema = swaggerSpec.definitions[key]; if (options && options.debug) { console.log(`Schmea for ref '${ref}': `); console.log(`${JSON.stringify(schema, null, 4)}`); } refsLookup[ref] = schema; refCount++; } } if (options && options.debug) { if (refCount > 0) { console.log(`Found ${refCount} schema definitions in Swagger spec`) } else { console.log(`Swagger spec contained no schema definitions`) } } return refsLookup; } module.exports = { buildRefsLookup: () => ({ forSpec: buildSwaggerRefsLookup }), generateObjects: () => ({ for: () => ({ specSchemas: (spec, options) => genSpecSchemaObjects(spec, options), specRequests: (spec, options) => genSpecRequestObjects(spec, options), specResponses: (spec, options) => genSpecResponseObjects(spec, options) }) }), generateObject: () => ({ for: () => ({ pathBodyUsingRefs: (path, refs, options) => (genObjectForPathBody(path, refs, options)).obj, schemaUsingRefs: genSchemaObject, schemaUsingSpec: (schema, spec, options) => genSchemaObject(schema, buildSwaggerRefsLookup(spec, options)) }) }) }