{"version":3,"sources":["formatter/formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAwB,mBAAmB,EAAyB,MAAM,sBAAsB,CAAC;AAC5H,OAAO,EAAiD,IAAI,EAA8C,MAAM,UAAU,CAAC;AAC3H,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,wBAAgB,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,GAAG,cAAc,CAkWnF;AAkCD,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC5C","file":"formatter.d.ts","sourcesContent":["import {\n\tFormattedInputNode,\n\tFormattedInputObject,\n\tFormattedOutputNode,\n\tFormattedOutputObject\n} from './formatter-model';\nimport {\n\tField,\n\tFieldType,\n\tInputField,\n\tList,\n\tModelKind,\n\tNode,\n\tOutputField,\n\tParam,\n\tPlainObject,\n\tReference\n} from 'tt-model';\nimport ts from 'typescript';\nimport { warn } from '@src/utils/log';\n\n/** Format parsed results to generate usable model */\nexport function format(\n\troot: Map<string, Node>,\n\tprogram: ts.Program\n): FormatResponse {\n\tconst result: FormatResponse = {\n\t\tinput: new Map(),\n\t\toutput: new Map()\n\t};\n\tconst inputMap = result.input;\n\tconst outputMap = result.output;\n\t/** Resolved generics */\n\tconst resolvedGenerics: Map<string, PlainObject> = new Map();\n\tconst typeChecker = program.getTypeChecker();\n\t//* Go through nodes\n\tvar rootQueue = Array.from(root.entries());\n\tvar rootQueueIdx = 0;\n\twhile (rootQueueIdx < rootQueue.length) {\n\t\tlet [nodeName, node] = rootQueue[rootQueueIdx++];\n\t\tswitch (node.kind) {\n\t\t\tcase ModelKind.BASIC_SCALAR:\n\t\t\tcase ModelKind.SCALAR:\n\t\t\tcase ModelKind.ENUM:\n\t\t\t\tinputMap.set(nodeName, node);\n\t\t\t\toutputMap.set(nodeName, node);\n\t\t\t\tbreak;\n\t\t\tcase ModelKind.UNION:\n\t\t\t\tinputMap.set(nodeName, node);\n\t\t\t\toutputMap.set(nodeName, node);\n\t\t\t\t// Resolve types\n\t\t\t\tfor (\n\t\t\t\t\tlet i = 0, types = node.types, len = types.length;\n\t\t\t\t\ti < len;\n\t\t\t\t\t++i\n\t\t\t\t) {\n\t\t\t\t\tlet ref = types[i];\n\t\t\t\t\t// fix reference\n\t\t\t\t\tif (root.has(ref.name) === false) ref.name = ref.oName;\n\t\t\t\t\t// Resolve generics\n\t\t\t\t\tref = _resolveReference(\n\t\t\t\t\t\tref,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tnodeName,\n\t\t\t\t\t\tundefined\n\t\t\t\t\t);\n\t\t\t\t\ttypes[i] = ref;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ModelKind.PLAIN_OBJECT:\n\t\t\t\t// Ignore generic objects\n\t\t\t\tif (node.generics != null) break;\n\t\t\t\t//* Resolve fields\n\t\t\t\tlet inputFields: FormattedInputObject['fields'] = [];\n\t\t\t\tlet outputFields: FormattedOutputObject['fields'] = [];\n\t\t\t\t//* Inherited classes (used for sorting fields)\n\t\t\t\tlet inherited: string[] | undefined;\n\t\t\t\tif (node.inherit != null) {\n\t\t\t\t\tinherited = [];\n\t\t\t\t\tfor (\n\t\t\t\t\t\tlet i = 0, cl = node.inherit, len = cl.length;\n\t\t\t\t\t\ti < len;\n\t\t\t\t\t\t++i\n\t\t\t\t\t) {\n\t\t\t\t\t\tinherited.push(cl[i].name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//* Resolve fields\n\t\t\t\tlet resolvedFields: ResolvedFieldInterface[] = [];\n\t\t\t\tnode.visibleFields.forEach(function (v, fieldName) {\n\t\t\t\t\tvar f = (node as PlainObject).fields.get(fieldName);\n\t\t\t\t\tvar inheritedFrom: string | undefined;\n\t\t\t\t\tif (f == null) {\n\t\t\t\t\t\tlet obj = root.get(v.className) as PlainObject;\n\t\t\t\t\t\tif (obj == null)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Missing entity \"${\n\t\t\t\t\t\t\t\t\tv.className\n\t\t\t\t\t\t\t\t}\" inherited to \"${\n\t\t\t\t\t\t\t\t\tnode.name\n\t\t\t\t\t\t\t\t}.${fieldName}\" at ${\n\t\t\t\t\t\t\t\t\t(node as PlainObject).fileName\n\t\t\t\t\t\t\t\t}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tf = obj.fields.get(fieldName);\n\t\t\t\t\t\tinheritedFrom = `${obj.name}.${fieldName}`;\n\t\t\t\t\t\tif (f == null) {\n\t\t\t\t\t\t\t// warn(\n\t\t\t\t\t\t\t// \t`FORMAT>> Ignored field \"${inheritedFrom}\" super of \"${node.name}.${fieldName}\" at ${obj.fileName}`\n\t\t\t\t\t\t\t// );\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Flags\n\t\t\t\t\tvar isRequired = !(v.flags & ts.SymbolFlags.Optional);\n\t\t\t\t\tresolvedFields.push({\n\t\t\t\t\t\tfield: f,\n\t\t\t\t\t\trequired: isRequired,\n\t\t\t\t\t\tinheritedFrom: inheritedFrom,\n\t\t\t\t\t\tindex: f.idx,\n\t\t\t\t\t\tclassName: f.className!\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\t//* Sort fields\n\t\t\t\tresolvedFields.sort(function (a, b) {\n\t\t\t\t\tif (a.className === b.className) return a.index - b.index;\n\t\t\t\t\telse if (a.className === null) return -1;\n\t\t\t\t\telse if (b.className === null) return 1;\n\t\t\t\t\telse if (inherited == null) return 0;\n\t\t\t\t\telse\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tinherited.indexOf(b.className) -\n\t\t\t\t\t\t\tinherited.indexOf(a.className)\n\t\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\t//* Load fields\n\t\t\t\tfor (let i = 0, len = resolvedFields.length; i < len; ++i) {\n\t\t\t\t\tlet {\n\t\t\t\t\t\tfield: f,\n\t\t\t\t\t\tinheritedFrom,\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t\trequired: isRequired\n\t\t\t\t\t} = resolvedFields[i];\n\t\t\t\t\t// Input field\n\t\t\t\t\tif (f.input != null) {\n\t\t\t\t\t\tlet fin = f.input;\n\t\t\t\t\t\tinputFields.push({\n\t\t\t\t\t\t\tkind: fin.kind,\n\t\t\t\t\t\t\talias: f.alias,\n\t\t\t\t\t\t\tname: fin.name,\n\t\t\t\t\t\t\tdeprecated: fin.deprecated,\n\t\t\t\t\t\t\tdefaultValue: fin.defaultValue,\n\t\t\t\t\t\t\tjsDoc:\n\t\t\t\t\t\t\t\tinheritedFrom == null\n\t\t\t\t\t\t\t\t\t? fin.jsDoc\n\t\t\t\t\t\t\t\t\t: _sortJsDoc(\n\t\t\t\t\t\t\t\t\t\t\tfin.jsDoc.concat(\n\t\t\t\t\t\t\t\t\t\t\t\t`@inherit-from ${inheritedFrom}`\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t  ),\n\t\t\t\t\t\t\trequired: isRequired,\n\t\t\t\t\t\t\ttype: _resolveType(\n\t\t\t\t\t\t\t\tfin.type,\n\t\t\t\t\t\t\t\tfin,\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t\tinheritedFrom\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tasserts: fin.asserts,\n\t\t\t\t\t\t\tvalidate: fin.validate\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (f.output != null) {\n\t\t\t\t\t\tlet fout = f.output;\n\t\t\t\t\t\toutputFields.push({\n\t\t\t\t\t\t\tkind: fout.kind,\n\t\t\t\t\t\t\tname: fout.name,\n\t\t\t\t\t\t\talias: fout.alias,\n\t\t\t\t\t\t\tdeprecated: fout.deprecated,\n\t\t\t\t\t\t\tjsDoc:\n\t\t\t\t\t\t\t\tinheritedFrom == null\n\t\t\t\t\t\t\t\t\t? fout.jsDoc\n\t\t\t\t\t\t\t\t\t: _sortJsDoc(\n\t\t\t\t\t\t\t\t\t\t\tfout.jsDoc.concat(\n\t\t\t\t\t\t\t\t\t\t\t\t`@inherit-from ${inheritedFrom}`\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t  ),\n\t\t\t\t\t\t\tmethod: fout.method,\n\t\t\t\t\t\t\tparam:\n\t\t\t\t\t\t\t\tfout.param == null\n\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t: _resolveType(\n\t\t\t\t\t\t\t\t\t\t\tfout.param,\n\t\t\t\t\t\t\t\t\t\t\tfout,\n\t\t\t\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t\t\t\t\tinheritedFrom\n\t\t\t\t\t\t\t\t\t  ),\n\t\t\t\t\t\t\trequired: isRequired,\n\t\t\t\t\t\t\ttype: _resolveType(\n\t\t\t\t\t\t\t\tfout.type,\n\t\t\t\t\t\t\t\tfout,\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t\tinheritedFrom\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//* Entities\n\t\t\t\tlet nodeJsDoc = _sortJsDoc(node.jsDoc);\n\t\t\t\tif (inputFields.length !== 0) {\n\t\t\t\t\t// Create object\n\t\t\t\t\tlet formattedInputObj: FormattedInputObject = {\n\t\t\t\t\t\tkind: ModelKind.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\tdeprecated: node.deprecated,\n\t\t\t\t\t\tjsDoc: nodeJsDoc,\n\t\t\t\t\t\tfields: inputFields,\n\t\t\t\t\t\tvalidate: node.validate\n\t\t\t\t\t};\n\t\t\t\t\tinputMap.set(nodeName, formattedInputObj);\n\t\t\t\t}\n\t\t\t\tif (outputFields.length !== 0) {\n\t\t\t\t\tlet formattedOutputObj: FormattedOutputObject = {\n\t\t\t\t\t\tkind: ModelKind.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\tdeprecated: node.deprecated,\n\t\t\t\t\t\tjsDoc: nodeJsDoc,\n\t\t\t\t\t\tfields: outputFields\n\t\t\t\t\t};\n\t\t\t\t\toutputMap.set(nodeName, formattedOutputObj);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ModelKind.OBJECT_LITERAL:\n\t\t\t\t{\n\t\t\t\t\t// TODO Implement object literals\n\t\t\t\t\tthrow new Error('Object literal are not supported yet.');\n\t\t\t\t\t// //* Resolve fields\n\t\t\t\t\t// let inputFields: FormattedInputObject['fields'] = [];\n\t\t\t\t\t// let outputFields: FormattedOutputObject['fields'] = [];\n\t\t\t\t\t// //* Load fields\n\t\t\t\t\t// node.fields.forEach(function (field, fieldName) {\n\t\t\t\t\t// \t// Input field\n\t\t\t\t\t// \tif (field.input != null) {\n\t\t\t\t\t// \t\tlet fin = field.input;\n\t\t\t\t\t// \t\tinputFields.push({\n\t\t\t\t\t// \t\t\tkind: fin.kind,\n\t\t\t\t\t// \t\t\talias: fin.alias,\n\t\t\t\t\t// \t\t\tname: fin.name,\n\t\t\t\t\t// \t\t\tdeprecated: fin.deprecated,\n\t\t\t\t\t// \t\t\tdefaultValue: fin.defaultValue,\n\t\t\t\t\t// \t\t\tjsDoc: fin.jsDoc,\n\t\t\t\t\t// \t\t\trequired: fin.required,\n\t\t\t\t\t// \t\t\ttype: _resolveType(\n\t\t\t\t\t// \t\t\t\tfin.type,\n\t\t\t\t\t// \t\t\t\tfin,\n\t\t\t\t\t// \t\t\t\tfield.className!,\n\t\t\t\t\t// \t\t\t\tundefined\n\t\t\t\t\t// \t\t\t),\n\t\t\t\t\t// \t\t\tasserts: fin.asserts,\n\t\t\t\t\t// \t\t\tvalidate: fin.validate,\n\t\t\t\t\t// \t\t});\n\t\t\t\t\t// \t}\n\t\t\t\t\t// \tif (field.output != null) {\n\t\t\t\t\t// \t\tlet fout = field.output;\n\t\t\t\t\t// \t\toutputFields.push({\n\t\t\t\t\t// \t\t\tkind: fout.kind,\n\t\t\t\t\t// \t\t\tname: fout.name,\n\t\t\t\t\t// \t\t\talias: fout.alias,\n\t\t\t\t\t// \t\t\tdeprecated: fout.deprecated,\n\t\t\t\t\t// \t\t\tjsDoc: fout.jsDoc,\n\t\t\t\t\t// \t\t\tmethod: fout.method,\n\t\t\t\t\t// \t\t\tparam:\n\t\t\t\t\t// \t\t\t\tfout.param == null\n\t\t\t\t\t// \t\t\t\t\t? undefined\n\t\t\t\t\t// \t\t\t\t\t: _resolveType(\n\t\t\t\t\t// \t\t\t\t\t\t\tfout.param,\n\t\t\t\t\t// \t\t\t\t\t\t\tfout,\n\t\t\t\t\t// \t\t\t\t\t\t\tfield.className!,\n\t\t\t\t\t// \t\t\t\t\t\t\tundefined\n\t\t\t\t\t// \t\t\t\t\t  ),\n\t\t\t\t\t// \t\t\trequired: fout.required,\n\t\t\t\t\t// \t\t\ttype: _resolveType(\n\t\t\t\t\t// \t\t\t\tfout.type,\n\t\t\t\t\t// \t\t\t\tfout,\n\t\t\t\t\t// \t\t\t\tfield.className!,\n\t\t\t\t\t// \t\t\t\tundefined\n\t\t\t\t\t// \t\t\t),\n\t\t\t\t\t// \t\t});\n\t\t\t\t\t// \t}\n\t\t\t\t\t// });\n\t\t\t\t\t// //* Entities\n\t\t\t\t\t// let nodeJsDoc = _sortJsDoc(node.jsDoc);\n\t\t\t\t\t// if (inputFields.length !== 0) {\n\t\t\t\t\t// \t// Create object\n\t\t\t\t\t// \tlet formattedInputObj: FormattedInputObject = {\n\t\t\t\t\t// \t\tkind: ModelKind.FORMATTED_INPUT_OBJECT,\n\t\t\t\t\t// \t\tname: undefined,\n\t\t\t\t\t// \t\tescapedName: undefined,\n\t\t\t\t\t// \t\tdeprecated: node.deprecated,\n\t\t\t\t\t// \t\tjsDoc: nodeJsDoc,\n\t\t\t\t\t// \t\tfields: inputFields,\n\t\t\t\t\t// \t};\n\t\t\t\t\t// \tinputMap.set(nodeName, formattedInputObj);\n\t\t\t\t\t// }\n\t\t\t\t\t// if (outputFields.length !== 0) {\n\t\t\t\t\t// \tlet formattedOutputObj: FormattedOutputObject = {\n\t\t\t\t\t// \t\tkind: ModelKind.FORMATTED_OUTPUT_OBJECT,\n\t\t\t\t\t// \t\tname: undefined,\n\t\t\t\t\t// \t\tescapedName: undefined,\n\t\t\t\t\t// \t\tdeprecated: node.deprecated,\n\t\t\t\t\t// \t\tjsDoc: nodeJsDoc,\n\t\t\t\t\t// \t\tfields: outputFields,\n\t\t\t\t\t// \t};\n\t\t\t\t\t// \toutputMap.set(nodeName, formattedOutputObj);\n\t\t\t\t\t// }\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tlet neverV: never = node;\n\t\t\t\t// @ts-ignore\n\t\t\t\tthrow new Error(`Unknown kind: ${ModelKind[neverV.kind]}`);\n\t\t}\n\t}\n\treturn result;\n\n\t/** Resolve generic types */\n\tfunction _resolveType<T extends FieldType | Param>(\n\t\ttype: T,\n\t\tfield: InputField | OutputField,\n\t\tclassName: string,\n\t\tinheritedFrom: string | undefined\n\t): T {\n\t\t// Check if field has generic type\n\t\tvar p: FieldType | Param = type;\n\t\tvar q: (FieldType | Param)[] = [];\n\t\twhile (p.kind !== ModelKind.REF) {\n\t\t\tq.push(p);\n\t\t\tp = p.type!;\n\t\t\tif (p == null) return type;\n\t\t}\n\t\t// fix reference\n\t\tif (root.has(p.name) === false) p.name = p.oName;\n\t\t// Generics\n\t\tvar resolvedRef: FieldType | Param = _resolveReference(\n\t\t\tp,\n\t\t\tfield,\n\t\t\tclassName,\n\t\t\tinheritedFrom\n\t\t);\n\t\tif (resolvedRef === p) return type;\n\t\tif (q.length !== 0) {\n\t\t\tq.reverse();\n\t\t\tfor (let i = 0, len = q.length; i < len; ++i) {\n\t\t\t\tresolvedRef = { ...q[i], type: resolvedRef } as List | Param;\n\t\t\t}\n\t\t}\n\t\treturn resolvedRef as T;\n\t}\n\t/** Resolve generic type */\n\tfunction _resolveReference(\n\t\tref: Reference,\n\t\tfield: InputField | OutputField | undefined,\n\t\tclassName: string,\n\t\tinheritedFrom: string | undefined\n\t): Reference {\n\t\tvar refNode = root.get(ref.name);\n\t\t//* Case normal reference\n\t\tif (refNode != null && ref.params == null) return ref;\n\t\t//* Case Generic or Logical entity\n\t\tvar escapedName = _getGenericEscapedName(ref);\n\t\tvar gEntity = resolvedGenerics.get(escapedName);\n\t\tif (gEntity == null) {\n\t\t\t// Check has not entity with same name as this one escaped name\n\t\t\tif (root.has(escapedName))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Found entity \"${escapedName}\" witch equals to the escaped name of generic: ${_getGenericName(\n\t\t\t\t\t\tref\n\t\t\t\t\t)} at ${ref.fileName}`\n\t\t\t\t);\n\t\t\t// logical entity (like \"Omit\" & \"Partial\")\n\t\t\tif (refNode == null)\n\t\t\t\tgEntity = _getLogicEntity(\n\t\t\t\t\tref,\n\t\t\t\t\tescapedName,\n\t\t\t\t\tfield,\n\t\t\t\t\tclassName,\n\t\t\t\t\tinheritedFrom\n\t\t\t\t);\n\t\t\telse if (refNode.kind !== ModelKind.PLAIN_OBJECT)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected PlainObject as reference of generic \"${_getGenericName(\n\t\t\t\t\t\tref\n\t\t\t\t\t)}\". Got \"${ModelKind[refNode.kind]}\" at \"${\n\t\t\t\t\t\tinheritedFrom ?? className\n\t\t\t\t\t}.${field?.name}\" at ${ref.fileName}`\n\t\t\t\t);\n\t\t\telse {\n\t\t\t\tlet name = _getGenericName(ref);\n\t\t\t\tgEntity = {\n\t\t\t\t\tkind: ModelKind.PLAIN_OBJECT,\n\t\t\t\t\tname: name,\n\t\t\t\t\tescapedName: escapedName,\n\t\t\t\t\tdeprecated: refNode.deprecated,\n\t\t\t\t\tjsDoc: _sortJsDoc(refNode.jsDoc.concat(`@Generic ${name}`)),\n\t\t\t\t\tfields: _resolveGenericFields(refNode, ref),\n\t\t\t\t\tfileName: refNode.fileName,\n\t\t\t\t\tgenerics: undefined,\n\t\t\t\t\tinherit: refNode.inherit,\n\t\t\t\t\townedFields: refNode.ownedFields,\n\t\t\t\t\tvisibleFields: refNode.visibleFields,\n\t\t\t\t\tvalidate: refNode.validate\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Push to generics\n\t\t\tresolvedGenerics.set(escapedName, gEntity);\n\t\t\trootQueue.push([escapedName, gEntity]);\n\t\t}\n\t\treturn {\n\t\t\tkind: ModelKind.REF,\n\t\t\tfileName: ref.fileName,\n\t\t\tname: escapedName,\n\t\t\toName: escapedName,\n\t\t\tfullName: undefined,\n\t\t\tparams: undefined,\n\t\t\tvisibleFields: undefined\n\t\t};\n\t}\n\n\t/** Generate logic entities: like Partials & Omit */\n\tfunction _getLogicEntity(\n\t\tref: Reference,\n\t\tescapedName: string,\n\t\tfield: InputField | OutputField | undefined,\n\t\tclassName: string,\n\t\tinheritedFrom: string | undefined\n\t): PlainObject {\n\t\t// Check reference node\n\t\tif (ref.visibleFields == null)\n\t\t\tthrow new Error(\n\t\t\t\t`Unexpected Logical Reference expression at \"${\n\t\t\t\t\tinheritedFrom ?? className\n\t\t\t\t}.${field?.name}\" at ${ref.fileName}`\n\t\t\t);\n\t\t// Prepare entity\n\t\tvar name = _getGenericName(ref);\n\t\tvar partialNode = root.get(ref.name) as PlainObject | undefined;\n\t\tvar jsDoc = partialNode == null ? [] : _sortJsDoc(partialNode.jsDoc); // .concat(`@Partial ${name}`)\n\t\tvar entity: PlainObject = {\n\t\t\tkind: ModelKind.PLAIN_OBJECT,\n\t\t\tname: name,\n\t\t\tescapedName: escapedName,\n\t\t\tdeprecated: partialNode?.deprecated,\n\t\t\tjsDoc: jsDoc,\n\t\t\tfields: new Map(),\n\t\t\tfileName: partialNode?.fileName ?? ref.fileName,\n\t\t\tgenerics: undefined,\n\t\t\tinherit: partialNode?.inherit,\n\t\t\townedFields: 0,\n\t\t\tvisibleFields: ref.visibleFields,\n\t\t\t// TODO maybe resolve validate cb for @Partial & @Omit\n\t\t\tvalidate: undefined\n\t\t};\n\t\t// Return entity\n\t\treturn entity;\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];\nfunction _sortJsDoc(arr: string[]) {\n\tvar arr2 = [];\n\tfor (let i = 0, len = arr.length; i < len; ++i) {\n\t\tlet t = arr[i]?.trim();\n\t\tif (t && arr2.indexOf(t) === -1) arr2.push(t);\n\t}\n\treturn arr2.sort((a, b) => {\n\t\tif (a.startsWith('@')) {\n\t\t\tif (b.startsWith('@')) {\n\t\t\t\tlet i = a.indexOf(' ');\n\t\t\t\tlet at = i === -1 ? a : a.substr(0, i);\n\t\t\t\ti = b.indexOf(' ');\n\t\t\t\tlet bt = i === -1 ? b : b.substr(0, i);\n\t\t\t\treturn (\n\t\t\t\t\tsortJsDocKeywords.indexOf(at) -\n\t\t\t\t\tsortJsDocKeywords.indexOf(bt)\n\t\t\t\t);\n\t\t\t} else return 1;\n\t\t} else return -1;\n\t});\n}\n\n/** Format response */\nexport interface FormatResponse {\n\tinput: Map<string, FormattedInputNode>;\n\toutput: Map<string, FormattedOutputNode>;\n}\n\n/** Resolved fields */\ninterface ResolvedFieldInterface {\n\tfield: Field;\n\trequired: boolean;\n\tinheritedFrom: string | undefined;\n\tindex: number;\n\tclassName: string;\n}\n\n// Get generic escaped name\nfunction _getGenericEscapedName(ref: Reference): string {\n\treturn (\n\t\tref.fullName\n\t\t\t?.replace(/[>\\]]/g, '')\n\t\t\t.replace(/[<\\],|]/g, '_')\n\t\t\t.replace(/\\W/g, '') ?? _getGenericEscapedNameE(ref)\n\t);\n}\nfunction _getGenericEscapedNameE(ref: FieldType): string {\n\tswitch (ref.kind) {\n\t\tcase ModelKind.REF:\n\t\t\tif (ref.params == null) return ref.name;\n\t\t\telse\n\t\t\t\treturn `${ref.name}_${ref.params\n\t\t\t\t\t.map(_getGenericEscapedNameE)\n\t\t\t\t\t.join('_')}`;\n\t\tcase ModelKind.LIST:\n\t\t\treturn '_' + _getGenericEscapedNameE(ref.type);\n\t\tdefault:\n\t\t\tlet t: never = ref;\n\t\t\tthrow new Error('Unsupported kind');\n\t}\n}\n// Get generic name\nfunction _getGenericName(ref: Reference): string {\n\treturn ref.fullName ?? _getGenericNameE(ref);\n}\nfunction _getGenericNameE(ref: FieldType): string {\n\tswitch (ref.kind) {\n\t\tcase ModelKind.REF:\n\t\t\tif (ref.params == null) return ref.name;\n\t\t\telse\n\t\t\t\treturn `${ref.name}<${ref.params\n\t\t\t\t\t.map(_getGenericNameE)\n\t\t\t\t\t.join(', ')}>`;\n\t\tcase ModelKind.LIST:\n\t\t\treturn _getGenericNameE(ref.type) + '[]';\n\t\tdefault:\n\t\t\tlet t: never = ref;\n\t\t\tthrow new Error('Unsupported kind');\n\t}\n}\n\nfunction _resolveGenericFields(\n\trefNode: PlainObject,\n\tref: Reference\n): Map<string, Field> {\n\tvar generics = refNode.generics;\n\tif (generics == null) return refNode.fields;\n\tvar fields: Map<string, Field> = new Map();\n\tvar params = ref.params!;\n\tif (generics.length !== params.length)\n\t\tthrow new Error(\n\t\t\t`Unexpected params length on ${refNode.name} and ${ref.name} at ${ref.fileName}`\n\t\t);\n\t// Map param\n\trefNode.fields.forEach(function (field, fieldName) {\n\t\tvar f: Field = {\n\t\t\talias: field.alias,\n\t\t\tinput: field.input && _resolve(field.input),\n\t\t\toutput: field.output && _resolve(field.output),\n\t\t\tclassName: field.className,\n\t\t\tidx: field.idx\n\t\t};\n\t\tfields.set(fieldName, f);\n\t});\n\treturn fields;\n\t/** Resolve */\n\tfunction _resolve<\n\t\tT extends InputField | OutputField | FieldType | Param | undefined\n\t>(f: T): T {\n\t\tvar r: T;\n\t\tif (f == null) return f;\n\t\tswitch (f.kind) {\n\t\t\tcase ModelKind.INPUT_FIELD:\n\t\t\tcase ModelKind.LIST:\n\t\t\tcase ModelKind.PARAM:\n\t\t\t\tr = { ...f, type: _resolve(f.type) };\n\t\t\t\tbreak;\n\t\t\tcase ModelKind.OUTPUT_FIELD:\n\t\t\t\tr = { ...f, type: _resolve(f.type), param: _resolve(f.param) };\n\t\t\t\tbreak;\n\t\t\tcase ModelKind.REF:\n\t\t\t\tlet i = generics!.indexOf(f.name);\n\t\t\t\tif (i === -1) r = f;\n\t\t\t\telse r = params[i] as T;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t//@ts-ignore\n\t\t\t\tthrow new Error(`Unexpected kind: ${ModelKind[f.kind]}`);\n\t\t}\n\t\treturn r;\n\t}\n}\n"]}