diff --git a/doc/PostmanCollection.schema b/doc/PostmanCollection.schema new file mode 100644 index 00000000..a6b545a3 --- /dev/null +++ b/doc/PostmanCollection.schema @@ -0,0 +1,42 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "description": "Postman collection", + "$ref": "#/definitions/collection", + "definitions": { + "group": { + "type": "object", + "properties": { + "item": { + "type": "array", + "items": { + "$ref": "#/definitions/collection" + } + } + } + }, + "item": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "response": { + "type": "array", + "items": { + "$ref": "#/definitions/response" + } + } + } + }, + "response": { + "type": "object", + "properties": { + "body": { "type": "string" } + } + }, + "collection": { + "oneOf": [ + { "$ref": "#/definitions/group" }, + { "$ref": "#/definitions/item" } + ] + } + } +} diff --git a/src/PostmanCollection.ts b/src/PostmanCollection.ts index 5a8a16a7..321c15d6 100644 --- a/src/PostmanCollection.ts +++ b/src/PostmanCollection.ts @@ -2,110 +2,39 @@ import { JSONTypeSource } from "."; +function isValidJSON(s: string): boolean { + try { + JSON.parse(s); + return true; + } catch (error) { + return false; + } +} + export function sourcesFromPostmanCollection(collectionJSON: string): JSONTypeSource[] { - const collection = Convert.toPostmanCollection(collectionJSON); - return collection.item.map(item => ({ name: item.name, samples: item.response.map(r => r.body) })); -} + const sources: JSONTypeSource[] = []; -interface PostmanCollection { - item: Item[]; -} - -interface Item { - name: string; - response: Response[]; -} - -interface Response { - body: string; -} - -// Converts JSON strings to/from your types -// and asserts the results of JSON.parse at runtime -module Convert { - export function toPostmanCollection(json: string): PostmanCollection { - return cast(JSON.parse(json), O("PostmanCollection")); - } - - export function postmanCollectionToJson(value: PostmanCollection): string { - return JSON.stringify(value, null, 2); - } - - function cast(obj: any, typ: any): T { - if (!isValid(typ, obj)) { - throw `Invalid value`; + function processCollection(c: any): void { + if (typeof c !== "object") return; + if (Array.isArray(c.item)) { + for (const item of c.item) { + processCollection(item); + } + } + if (typeof c.name === "string" && Array.isArray(c.response)) { + const samples: string[] = []; + for (const r of c.response) { + if (typeof r === "object" && typeof r.body === "string" && isValidJSON(r.body)) { + samples.push(r.body); + } + } + if (samples.length > 0) { + sources.push({ name: c.name, samples }); + } } - return obj; } - function isValid(typ: any, val: any): boolean { - if (typ === undefined) return true; - if (typ === null) return val === null || val === undefined; - return typ.isUnion ? isValidUnion(typ.typs, val) - : typ.isArray ? isValidArray(typ.typ, val) - : typ.isMap ? isValidMap(typ.typ, val) - : typ.isEnum ? isValidEnum(typ.name, val) - : typ.isObject ? isValidObject(typ.cls, val) - : isValidPrimitive(typ, val); - } - - function isValidPrimitive(typ: string, val: any) { - return typeof typ === typeof val; - } - - function isValidUnion(typs: any[], val: any): boolean { - // val must validate against one typ in typs - return typs.find(typ => isValid(typ, val)) !== undefined; - } - - function isValidEnum(enumName: string, val: any): boolean { - const cases = typeMap[enumName]; - return cases.indexOf(val) !== -1; - } - - function isValidArray(typ: any, val: any): boolean { - // val must be an array with no invalid elements - return Array.isArray(val) && val.every(element => { - return isValid(typ, element); - }); - } - - function isValidMap(typ: any, val: any): boolean { - if (val === null || typeof val !== "object" || Array.isArray(val)) return false; - // all values in the map must be typ - return Object.keys(val).every(prop => { - if (!Object.prototype.hasOwnProperty.call(val, prop)) return true; - return isValid(typ, val[prop]); - }); - } - - function isValidObject(className: string, val: any): boolean { - if (val === null || typeof val !== "object" || Array.isArray(val)) return false; - let typeRep = typeMap[className]; - return Object.keys(typeRep).every(prop => { - if (!Object.prototype.hasOwnProperty.call(typeRep, prop)) return true; - return isValid(typeRep[prop], val[prop]); - }); - } - - function A(typ: any) { - return { typ, isArray: true }; - } - - function O(className: string) { - return { cls: className, isObject: true }; - } - - const typeMap: any = { - "PostmanCollection": { - item: A(O("Item")), - }, - "Item": { - name: "", - response: A(O("Response")), - }, - "Response": { - body: "", - }, - }; + processCollection(JSON.parse(collectionJSON)); + console.log("sources are", JSON.stringify(sources)); + return sources; }