{"version":3,"sources":["parser/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2D,kBAAkB,EAA6D,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACnM,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIpC,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC;;;;EAMpD","file":"format.d.ts","sourcesContent":["import { FormattedEnum, FormattedEnumMember, formattedInputField, FormattedInputNode, FormattedInputObject, FormattedNode, formattedOutputField, FormattedOutputNode } from './formatted-model';\nimport { parse } from './parser';\nimport { InputNode, OutputNode, InputObject, OutputObject, InputField } from './model';\nimport {\n\tKind,\n\tOutputField\n} from './model';\n\n/** Format parsed results to generate usable model */\nexport function format(\n\troot: ReturnType<typeof parse>\n) {\n\treturn {\n\t\tinput: _resolveEntities(root.input, root.inputHelperEntities),\n\t\toutput: _resolveEntities(root.output, root.outputHelperEntities),\n\t\trootConfig: root.rootConfig\n\t};\n}\n\n/** Resolve entities */\nfunction _resolveEntities(map: Map<string, InputNode>, helperEntities: Map<string, InputObject>): Map<string, FormattedInputNode>;\nfunction _resolveEntities(map: Map<string, OutputNode>, helperEntities: Map<string, OutputObject>): Map<string, FormattedOutputNode>;\nfunction _resolveEntities(map: Map<string, InputNode | OutputNode>, helperEntities: Map<string, InputObject | OutputObject>) {\n\tconst result: Map<string, FormattedInputNode | FormattedOutputNode> = new Map();\n\tconst errors: string[] = [];\n\tmap.forEach((node, nodeName) => {\n\t\ttry {\n\t\t\tswitch (node.kind) {\n\t\t\t\tcase Kind.BASIC_SCALAR:\n\t\t\t\tcase Kind.SCALAR:\n\t\t\t\t\t(node as any as FormattedNode).jsDoc = _compileJsDoc(node.jsDoc);\n\t\t\t\t\tresult.set(nodeName, node as any as FormattedInputNode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase Kind.UNION: {\n\t\t\t\t\t(node as any as FormattedNode).jsDoc = _compileJsDoc(node.jsDoc);\n\t\t\t\t\tresult.set(nodeName, node as any as FormattedInputNode);\n\t\t\t\t\t// Check types found\n\t\t\t\t\tlet missingTypes = node.types.filter(t => !result.has(t.name));\n\t\t\t\t\tif (missingTypes.length > 0)\n\t\t\t\t\t\tthrow `Missing types [${missingTypes.map(t => t.name).join(', ')}] on union \"${node.name}\" at ${node.fileNames.join(', ')}`;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase Kind.INPUT_OBJECT: {\n\t\t\t\t\tlet entity: FormattedInputNode = {\n\t\t\t\t\t\tkind: Kind.FORMATTED_INPUT_OBJECT,\n\t\t\t\t\t\tname: node.name,\n\t\t\t\t\t\tescapedName: node.escapedName!,\n\t\t\t\t\t\tfields: _formatInputFields(node),\n\t\t\t\t\t\twrappers: node.wrappers,\n\t\t\t\t\t\tbefore: node.before,\n\t\t\t\t\t\tafter: node.after,\n\t\t\t\t\t\tjsDoc: _compileJsDoc(node.jsDoc),\n\t\t\t\t\t\tdeprecated: node.deprecated,\n\t\t\t\t\t\tconvert: node.convert\n\t\t\t\t\t}\n\t\t\t\t\t_sortFields(entity.fields, node);\n\t\t\t\t\tresult.set(nodeName, entity);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase Kind.OUTPUT_OBJECT: {\n\t\t\t\t\tlet entity: FormattedOutputNode = {\n\t\t\t\t\t\tkind: Kind.FORMATTED_OUTPUT_OBJECT,\n\t\t\t\t\t\tname: node.name,\n\t\t\t\t\t\tescapedName: node.escapedName!,\n\t\t\t\t\t\tfields: _formatOutputFields(node),\n\t\t\t\t\t\twrappers: node.wrappers,\n\t\t\t\t\t\tbefore: node.before,\n\t\t\t\t\t\tafter: node.after,\n\t\t\t\t\t\tjsDoc: _compileJsDoc(node.jsDoc),\n\t\t\t\t\t\tdeprecated: node.deprecated,\n\t\t\t\t\t\tconvert: node.convert\n\t\t\t\t\t}\n\t\t\t\t\t_sortFields(entity.fields, node);\n\t\t\t\t\tresult.set(nodeName, entity);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase Kind.ENUM: {\n\t\t\t\t\t(node as any as FormattedEnum).jsDoc = _compileJsDoc(node.jsDoc);\n\t\t\t\t\tresult.set(nodeName, node as any as FormattedEnum);\n\t\t\t\t\tfor (let i = 0, members = node.members, len = members.length; i < len; ++i) {\n\t\t\t\t\t\tlet member = members[i];\n\t\t\t\t\t\t(member as any as FormattedEnumMember).jsDoc = _compileJsDoc(member.jsDoc);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tlet neverV: never = node;\n\t\t\t\t\tthrow new Error(`Unknown kind:` + neverV);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (typeof err === 'string') errors.push(err);\n\t\t\telse throw err;\n\t\t}\n\t});\n\tif (errors.length > 0)\n\t\tthrow new Error(`FORMAT-ERR>>\\n\\t${errors.join(\"\\n\\t\")}`)\n\treturn result;\n\n\t/** Format input fields */\n\tfunction _formatInputFields(obj: InputObject): formattedInputField[] {\n\t\tconst result: formattedInputField[] = [];\n\t\tobj.fields.forEach(function (field) {\n\t\t\t// Look for implementation\n\t\t\tconst fieldImp = _getFieldImp(obj, field);\n\t\t\t// Create formatted field\n\t\t\tconst formattedField: formattedInputField = {\n\t\t\t\tkind: Kind.INPUT_FIELD,\n\t\t\t\tname: field.name,\n\t\t\t\talias: field.alias,\n\t\t\t\trequired: field.required,\n\t\t\t\tasserts: field.asserts,\n\t\t\t\tclassName: field.className,\n\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\tdeprecated: field.deprecated,\n\t\t\t\tfileNames: field.fileNames,\n\t\t\t\tidx: field.idx,\n\t\t\t\tjsDoc: _compileJsDoc(fieldImp ? field.jsDoc.concat(fieldImp.jsDoc) : field.jsDoc),\n\t\t\t\tpipe: fieldImp ? [...field.pipe, ...fieldImp.pipe] : [...field.pipe],\n\t\t\t\ttype: field.type,\n\t\t\t\tconvert: undefined,\n\t\t\t\tvalidators: field.validators\n\t\t\t};\n\t\t\tif (fieldImp != null && fieldImp.pipe.length) {\n\t\t\t\tformattedField.type = fieldImp.type;\n\t\t\t}\n\t\t\tformattedField.convert = _getWrapper(field);\n\t\t\tresult.push(formattedField);\n\t\t});\n\t\treturn result;\n\t}\n\t/** Format output fields */\n\tfunction _formatOutputFields(obj: OutputObject): formattedOutputField[] {\n\t\tconst result: formattedOutputField[] = [];\n\t\tobj.fields.forEach(function (field) {\n\t\t\t// Look for implementation\n\t\t\tconst fieldImp = _getFieldImp(obj, field);\n\t\t\t// Create formatted field\n\t\t\tconst formattedField: formattedOutputField = {\n\t\t\t\tkind: Kind.OUTPUT_FIELD,\n\t\t\t\tname: field.name,\n\t\t\t\talias: field.alias,\n\t\t\t\trequired: field.required,\n\t\t\t\tclassName: field.className,\n\t\t\t\tdefaultValue: field.defaultValue,\n\t\t\t\tdeprecated: field.deprecated,\n\t\t\t\tfileNames: field.fileNames,\n\t\t\t\tidx: field.idx,\n\t\t\t\tjsDoc: _compileJsDoc(fieldImp ? field.jsDoc.concat(fieldImp.jsDoc) : field.jsDoc),\n\t\t\t\tmethod: field.method,\n\t\t\t\ttype: field.type,\n\t\t\t\tparam: field.param,\n\t\t\t\tconvert: undefined,\n\t\t\t\tresolvers: field.resolvers // TODO replace with list of methods\n\t\t\t};\n\t\t\tif (formattedField.method == null && fieldImp != null && fieldImp.method != null) {\n\t\t\t\tformattedField.method = fieldImp.method;\n\t\t\t\tformattedField.type = fieldImp.type;\n\t\t\t\tformattedField.param = fieldImp.param;\n\t\t\t}\n\t\t\t// Converter\n\t\t\tformattedField.convert = _getWrapper(field);\n\t\t\tresult.push(formattedField);\n\t\t});\n\t\treturn result;\n\t}\n\t/** Get field implementation */\n\tfunction _getFieldImp(node: InputObject, field: InputField): InputField | undefined;\n\tfunction _getFieldImp(node: OutputObject, field: OutputField): OutputField | undefined;\n\tfunction _getFieldImp(node: InputObject | OutputObject, field: InputField | OutputField): InputField | OutputField | undefined {\n\t\tlet fieldName = field.name;\n\t\t// Check using current object\n\t\tlet fieldImp = helperEntities.get(node.name)?.fields.get(fieldName);\n\t\tif (fieldImp != null) return fieldImp;\n\t\t// Load using inheritance\n\t\tif (node.inherit != null) {\n\t\t\tfor (let i = 0, inherit = node.inherit, len = inherit.length; i < len; ++i) {\n\t\t\t\tif (fieldImp = helperEntities.get(inherit[i])?.fields.get(fieldName)) break;\n\t\t\t}\n\t\t\tif (fieldImp != null) return fieldImp;\n\t\t}\n\t\t// By field explicit class\n\t\tif (field.className != null) fieldImp = helperEntities.get(field.className)?.fields.get(fieldName);\n\t\treturn fieldImp;\n\t}\n\t/** Sort fields */\n\tfunction _sortFields(fields: formattedOutputField[] | formattedInputField[], node: OutputObject | InputObject) {\n\t\tif (node.orderByName) {\n\t\t\tfields.sort((a, b) => a.name.localeCompare(b.name));\n\t\t} else if (node.inherit != null) {\n\t\t\tlet inherit = [node.name, ...node.inherit];\n\t\t\tfields.sort(function (a, b) {\n\t\t\t\tif (a.className === b.className)\n\t\t\t\t\treturn a.idx - b.idx;\n\t\t\t\telse if (a.className != null && b.className != null)\n\t\t\t\t\treturn inherit.indexOf(b.className) - inherit.indexOf(a.className);\n\t\t\t\telse return 0;\n\t\t\t});\n\t\t} else {\n\t\t\tfields.sort(function (a, b) {\n\t\t\t\treturn a.idx - b.idx;\n\t\t\t});\n\t\t}\n\t}\n\t/** Get entity wrapper */\n\tfunction _getWrapper(field: InputField | OutputField) {\n\t\tif (field.type != null) {\n\t\t\tlet ref = field.type;\n\t\t\twhile (ref.kind !== Kind.REF) ref = ref.type;\n\t\t\tlet entity = map.get(ref.name);\n\t\t\tif (entity == null)\n\t\t\t\tthrow `Missing entity \"${ref.name}\" referenced at ${ref.fileName}`;\n\t\t\treturn (entity as InputObject | OutputObject).convert;\n\t\t}\n\t}\n}\n\n/** Sort jsDoc */\nconst sortJsDocKeywords = [\n\t'Generic',\n\t'Partial',\n\t'implements',\n\t'extends',\n\t'inherit-from'\n];\n/** Compile js Doc */\nfunction _compileJsDoc(arr: string[] | string | undefined): string | undefined {\n\tif (arr == null) return undefined;\n\telse if (typeof arr === 'string') return arr;\n\telse {\n\t\tvar arr2 = [];\n\t\tfor (let i = 0, len = arr.length; i < len; ++i) {\n\t\t\tlet t = arr[i]?.trim();\n\t\t\tif (t && arr2.indexOf(t) === -1) arr2.push(t);\n\t\t}\n\t\tif (arr2.length === 0) return undefined\n\t\telse return arr2.sort((a, b) => {\n\t\t\tif (a.startsWith('@')) {\n\t\t\t\tif (b.startsWith('@')) {\n\t\t\t\t\tlet i = a.indexOf(' ');\n\t\t\t\t\tlet at = i === -1 ? a : a.substr(0, i);\n\t\t\t\t\ti = b.indexOf(' ');\n\t\t\t\t\tlet bt = i === -1 ? b : b.substr(0, i);\n\t\t\t\t\treturn (\n\t\t\t\t\t\tsortJsDocKeywords.indexOf(at) -\n\t\t\t\t\t\tsortJsDocKeywords.indexOf(bt)\n\t\t\t\t\t);\n\t\t\t\t} else return 1;\n\t\t\t} else return -1;\n\t\t}).join(\"\\n\");\n\t}\n}"]}