moonflower 1.4.7 → 1.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/openapi/analyzerModule/analyzerModule.cjs +1 -1
- package/dist/openapi/analyzerModule/analyzerModule.cjs.map +1 -1
- package/dist/openapi/analyzerModule/analyzerModule.d.ts +16 -2
- package/dist/openapi/analyzerModule/analyzerModule.d.ts.map +1 -1
- package/dist/openapi/analyzerModule/analyzerModule.mjs +115 -96
- package/dist/openapi/analyzerModule/analyzerModule.mjs.map +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.cjs +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.cjs.map +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.mjs +81 -81
- package/dist/openapi/analyzerModule/nodeParsers.mjs.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.cjs +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.cjs.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.d.ts +8 -1
- package/dist/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.mjs +132 -107
- package/dist/openapi/analyzerModule/parseEndpoint.mjs.map +1 -1
- package/package.json +1 -1
- package/src/openapi/analyzerModule/analyzerModule.ts +64 -21
- package/src/openapi/analyzerModule/nodeParsers.ts +4 -4
- package/src/openapi/analyzerModule/parseEndpoint.ts +66 -32
- package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.ts +2 -2
- package/src/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.ts +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("ts-morph"),c=require("../../utils/logger.cjs"),u=require("./nodeParsers.cjs"),x=(e,i)=>{const r=e.getFirstDescendantByKind(o.SyntaxKind.PropertyAccessExpression).getText().split(".")[1].toUpperCase(),t=r==="DEL"?"DELETE":r,a=u.resolveEndpointPath(e)??"",n={method:t,path:a,sourceFilePath:i,requestPathParams:[],requestQuery:[],requestHeaders:[],rawBody:void 0,objectBody:[],responses:[],name:void 0,summary:void 0,description:void 0,tags:void 0},d=[],l=(s,g)=>{const f=performance.now(),m=g();return d.push({section:s,timing:performance.now()-f}),m},p=E(e);try{l("useApiEndpoint",()=>K(p.useApiEndpoint)).forEach(g=>{n[g.identifier]=g.value})}catch(s){c.Logger.error("Error",s)}try{n.requestPathParams=l("usePathParams",()=>P(p.usePathParams,a))}catch(s){c.Logger.error("Error",s)}try{n.requestQuery=l("useQueryParams",()=>y(p.useQueryParams,"useQueryParams"))}catch(s){c.Logger.error("Error",s)}try{n.requestHeaders=l("useHeaderParams",()=>y(p.useHeaderParams,"useHeaderParams"))}catch(s){c.Logger.error("Error",s)}try{const s=l("useRequestRawBody",()=>L(p.useRequestRawBody));s&&(n.rawBody=s)}catch(s){c.Logger.error("Error",s)}try{n.objectBody=l("useRequestBody",()=>y(p.useRequestBody,"useRequestBody"))}catch(s){c.Logger.error("Error",s)}try{n.responses=l("response",()=>S(e))}catch(s){c.Logger.error("Error",s)}return{endpoint:n,sectionTimings:d}},E=e=>{const i={useApiEndpoint:null,usePathParams:null,useQueryParams:null,useHeaderParams:null,useRequestBody:null,useRequestRawBody:null};for(const r of e.getDescendantsOfKind(o.SyntaxKind.CallExpression)){const t=r.getFirstChildByKind(o.SyntaxKind.Identifier)?.getText();t&&t in i&&i[t]===null&&(i[t]=r)}return i},K=e=>{if(!e)return[];const i=e.getFirstChildByKind(o.SyntaxKind.SyntaxList),r=u.findNodeImplementation(i.getLastChild());if(!r.isKind(o.SyntaxKind.ObjectLiteralExpression))throw new Error("Non-literal type used in useApiEndpoint");const t=r.asKind(o.SyntaxKind.ObjectLiteralExpression);return u.getValuesOfObjectLiteral(t).filter(n=>n.value!==null)},P=(e,i)=>{if(!e)return[];const r=e.getFirstChildByKind(o.SyntaxKind.SyntaxList),t=u.findNodeImplementation(r.getLastChild());if(!t.isKind(o.SyntaxKind.ObjectLiteralExpression))throw new Error("Non-literal type used in usePathParams");const a=i.split("/").filter(d=>d.startsWith(":")).map(d=>({name:d.substring(1).replace(/\?/,""),optional:d.includes("?")})),n=t.asKind(o.SyntaxKind.ObjectLiteralExpression);return u.getShapeOfValidatorLiteral(n).filter(d=>d.shape!==null).map(d=>({identifier:d.identifier,signature:d.shape,optional:a.some(l=>l.name===d.identifier&&l.optional),description:d.description,errorMessage:d.errorMessage}))},L=e=>{if(!e)return null;const i=e.getFirstChildByKind(o.SyntaxKind.SyntaxList),r=u.findNodeImplementation(i.getLastChild(t=>!t.isKind(o.SyntaxKind.CommaToken)));return{signature:u.getValidatorPropertyShape(r),optional:u.getValidatorPropertyOptionality(r),description:u.getValidatorPropertyStringValue(r,"description"),errorMessage:u.getValidatorPropertyStringValue(r,"errorMessage")}},y=(e,i)=>{if(!e)return[];const r=e.getFirstChildByKind(o.SyntaxKind.SyntaxList),t=u.findNodeImplementation(r.getLastChild());if(!t.isKind(o.SyntaxKind.ObjectLiteralExpression))throw new Error(`Non-literal type used in ${i}`);const a=t.asKind(o.SyntaxKind.ObjectLiteralExpression);return u.getShapeOfValidatorLiteral(a).filter(n=>n.shape!==null).map(n=>({identifier:n.identifier,signature:n.shape,optional:n.optional,description:n.description,errorMessage:n.errorMessage}))},S=e=>{const r=e.getFirstChildByKind(o.SyntaxKind.CallExpression).getFirstChildByKind(o.SyntaxKind.SyntaxList).getFirstChildByKind(o.SyntaxKind.ArrowFunction).getReturnType(),t=r.getText().startsWith("Promise")?r.getTypeArguments()[0]:r,a=u.getProperTypeShape(t,e);return h(a)},h=e=>{if(typeof e=="string")return[{status:e==="void"||e==="null"?204:200,contentType:"text/plain",signature:e,description:"",errorMessage:""}];if(e[0].role==="union_entry"||e[0].role==="literal_string")return h(e[0].shape);if(e[0].role==="property"&&e[0].identifier==="_isUseReturnValue"){const i=(()=>{const t=e.find(a=>a.role==="property"&&a.identifier==="status")?.shape;if(!t||typeof t=="string"||typeof t[0].shape!="string")throw new Error("Invalid useReturnValue hook");return parseInt(t[0].shape)})(),r=(()=>{const t=e.find(a=>a.role==="property"&&a.identifier==="contentType")?.shape;if(!t||typeof t=="string"||typeof t[0].shape!="string")throw new Error("Invalid useReturnValue hook");return t[0].shape})();return[{status:i,contentType:r,signature:e,description:"",errorMessage:""}]}return e[0].role==="union"?typeof e[0].shape=="string"?[{status:e[0].shape==="void"||e[0].shape==="null"?204:200,contentType:"application/json",signature:e[0].shape,description:"",errorMessage:""}]:e[0].shape.flatMap(i=>h([i])):e[0].role==="buffer"?[{status:200,contentType:"application/octet-stream",signature:e,description:"",errorMessage:""}]:[{status:200,contentType:"application/json",signature:e,description:"",errorMessage:""}]};exports.parseEndpoint=x;
|
|
2
2
|
//# sourceMappingURL=parseEndpoint.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseEndpoint.cjs","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"sourcesContent":["import { Node, SyntaxKind, ts } from 'ts-morph'\n\nimport { ApiEndpointDocs } from '../../hooks/useApiEndpoint'\nimport { Logger } from '../../utils/logger'\nimport { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n\tresolveEndpointPath,\n} from './nodeParsers'\n\nexport const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {\n\tconst parsedEndpointMethod = node\n\t\t.getFirstDescendantByKind(SyntaxKind.PropertyAccessExpression)!\n\t\t.getText()\n\t\t.split('.')[1]\n\t\t.toUpperCase()\n\n\tconst endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod\n\n\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\tconst endpointData: EndpointData = {\n\t\tmethod: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n\t\tpath: endpointPath,\n\t\tsourceFilePath,\n\t\trequestPathParams: [],\n\t\trequestQuery: [],\n\t\trequestHeaders: [],\n\t\trawBody: undefined,\n\t\tobjectBody: [],\n\t\tresponses: [],\n\t\tname: undefined,\n\t\tsummary: undefined,\n\t\tdescription: undefined,\n\t\ttags: undefined,\n\t}\n\n\tconst warningData: {\n\t\tsegment: string\n\t\terror: Error\n\t}[] = []\n\n\t// API documentation\n\ttry {\n\t\tconst entries = parseApiDocumentation(node)\n\t\tentries.forEach((param) => {\n\t\t\tendpointData[param.identifier] = param.value as string & string[]\n\t\t})\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'api',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request params\n\ttry {\n\t\tendpointData.requestPathParams = parseRequestParams(node, endpointPath)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'path',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request query\n\ttry {\n\t\tendpointData.requestQuery = parseRequestObjectInput(node, 'useQueryParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'query',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request headers\n\ttry {\n\t\tendpointData.requestHeaders = parseRequestObjectInput(node, 'useHeaderParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'headers',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Raw request body\n\ttry {\n\t\tconst parsedBody = parseRequestRawBody(node)\n\t\tif (parsedBody) {\n\t\t\tendpointData.rawBody = parsedBody\n\t\t}\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'rawBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Object request body\n\ttry {\n\t\tendpointData.objectBody = parseRequestObjectInput(node, 'useRequestBody')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'objectBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request response\n\ttry {\n\t\tendpointData.responses = parseRequestResponse(node)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'response',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\treturn endpointData\n}\n\nconst getHookNode = (\n\tendpointNode: Node<ts.Node>,\n\thookName:\n\t\t| 'useApiEndpoint'\n\t\t| 'usePathParams'\n\t\t| 'useQueryParams'\n\t\t| 'useHeaderParams'\n\t\t| 'useRequestBody'\n\t\t| 'useRequestRawBody',\n) => {\n\tconst callExpressions = endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)\n\tconst matchingCallExpressions = callExpressions.filter((node) => {\n\t\treturn node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === hookName\n\t})\n\treturn matchingCallExpressions[0] ?? null\n}\n\nconst parseApiDocumentation = (node: Node<ts.Node>) => {\n\tconst hookNode = getHookNode(node, 'useApiEndpoint')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in useApiEndpoint')\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\n\tconst values = getValuesOfObjectLiteral(objectLiteral).filter((param) => param.value !== null)\n\treturn values as {\n\t\tidentifier: keyof ApiEndpointDocs\n\t\tvalue: (typeof values)[number]['value']\n\t}[]\n}\n\nconst parseRequestParams = (node: Node<ts.Node>, endpointPath: string): EndpointData['requestPathParams'] => {\n\tconst hookNode = getHookNode(node, 'usePathParams')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in usePathParams')\n\t}\n\n\tconst declaredParams = endpointPath\n\t\t.split('/')\n\t\t.filter((segment) => segment.startsWith(':'))\n\t\t.map((segment) => ({\n\t\t\tname: segment.substring(1).replace(/\\?/, ''),\n\t\t\toptional: segment.includes('?'),\n\t\t}))\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: declaredParams.some((declared) => declared.name === param.identifier && declared.optional),\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestRawBody = (node: Node<ts.Node>): NonNullable<EndpointData['rawBody']> | null => {\n\tconst hookNode = getHookNode(node, 'useRequestRawBody')\n\tif (!hookNode) {\n\t\treturn null\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(\n\t\tparamNode.getLastChild((node) => !node.isKind(SyntaxKind.CommaToken))!,\n\t)\n\n\treturn {\n\t\tsignature: getValidatorPropertyShape(valueNode),\n\t\toptional: getValidatorPropertyOptionality(valueNode),\n\t\tdescription: getValidatorPropertyStringValue(valueNode, 'description'),\n\t\terrorMessage: getValidatorPropertyStringValue(valueNode, 'errorMessage'),\n\t}\n}\n\nconst parseRequestObjectInput = (\n\tnode: Node<ts.Node>,\n\tnodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',\n): EndpointData['requestQuery'] | EndpointData['objectBody'] => {\n\tconst hookNode = getHookNode(node, nodeName)\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error(`Non-literal type used in ${nodeName}`)\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: param.optional,\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestResponse = (node: Node<ts.Node>): EndpointData['responses'] => {\n\tconst implementationNode = node\n\t\t.getFirstChildByKind(SyntaxKind.CallExpression)!\n\t\t.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\t\t.getFirstChildByKind(SyntaxKind.ArrowFunction)!\n\tconst returnType = implementationNode.getReturnType()\n\n\tconst actualType = (() => {\n\t\tif (returnType.getText().startsWith('Promise')) {\n\t\t\treturn returnType.getTypeArguments()[0]\n\t\t}\n\t\treturn returnType\n\t})()\n\n\tconst responseType = getProperTypeShape(actualType, node)\n\n\treturn parseResponseTypes(responseType)\n}\n\nconst parseResponseTypes = (\n\tresponseType: ReturnType<typeof getProperTypeShape>,\n): EndpointData['responses'] => {\n\t// TODO: Add support for response descriptions and errors\n\tif (typeof responseType === 'string') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: responseType === 'void' || responseType === 'null' ? 204 : 200,\n\t\t\t\tcontentType: 'text/plain',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union_entry' || responseType[0].role === 'literal_string') {\n\t\treturn parseResponseTypes(responseType[0].shape)\n\t}\n\n\t// Response type is a useReturnValue hook\n\tif (responseType[0].role === 'property' && responseType[0].identifier === '_isUseReturnValue') {\n\t\tconst status = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'status',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn parseInt(property[0].shape)\n\t\t})()\n\t\tconst contentType = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'contentType',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn property[0].shape\n\t\t})()\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus,\n\t\t\t\tcontentType,\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union') {\n\t\tif (typeof responseType[0].shape === 'string') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tstatus: responseType[0].shape === 'void' || responseType[0].shape === 'null' ? 204 : 200,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tsignature: responseType[0].shape,\n\t\t\t\t\tdescription: '',\n\t\t\t\t\terrorMessage: '',\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn responseType[0].shape.flatMap((unionEntry) => {\n\t\t\treturn parseResponseTypes([unionEntry])\n\t\t})\n\t}\n\n\tif (responseType[0].role === 'buffer') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\tcontentType: 'application/octet-stream',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\treturn [\n\t\t{\n\t\t\tstatus: 200,\n\t\t\tcontentType: 'application/json',\n\t\t\tsignature: responseType,\n\t\t\tdescription: '',\n\t\t\terrorMessage: '',\n\t\t},\n\t]\n}\n"],"names":["parseEndpoint","node","sourceFilePath","parsedEndpointMethod","SyntaxKind","endpointMethod","endpointPath","resolveEndpointPath","endpointData","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","getHookNode","endpointNode","hookName","hookNode","paramNode","valueNode","findNodeImplementation","objectLiteral","getValuesOfObjectLiteral","declaredParams","segment","getShapeOfValidatorLiteral","declared","getValidatorPropertyShape","getValidatorPropertyOptionality","getValidatorPropertyStringValue","nodeName","returnType","actualType","responseType","getProperTypeShape","parseResponseTypes","status","property","response","contentType","unionEntry"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parseEndpoint.cjs","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"sourcesContent":["import { Node, SyntaxKind, ts } from 'ts-morph'\n\nimport { ApiEndpointDocs } from '../../hooks/useApiEndpoint'\nimport { Logger } from '../../utils/logger'\nimport { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n\tresolveEndpointPath,\n} from './nodeParsers'\n\nexport type SectionTiming = { section: string; timing: number }\n\nexport const parseEndpoint = (\n\tnode: Node<ts.Node>,\n\tsourceFilePath: string,\n): { endpoint: EndpointData; sectionTimings: SectionTiming[] } => {\n\tconst parsedEndpointMethod = node\n\t\t.getFirstDescendantByKind(SyntaxKind.PropertyAccessExpression)!\n\t\t.getText()\n\t\t.split('.')[1]\n\t\t.toUpperCase()\n\n\tconst endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod\n\n\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\tconst endpointData: EndpointData = {\n\t\tmethod: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n\t\tpath: endpointPath,\n\t\tsourceFilePath,\n\t\trequestPathParams: [],\n\t\trequestQuery: [],\n\t\trequestHeaders: [],\n\t\trawBody: undefined,\n\t\tobjectBody: [],\n\t\tresponses: [],\n\t\tname: undefined,\n\t\tsummary: undefined,\n\t\tdescription: undefined,\n\t\ttags: undefined,\n\t}\n\n\tconst warningData: {\n\t\tsegment: string\n\t\terror: Error\n\t}[] = []\n\n\tconst sectionTimings: SectionTiming[] = []\n\n\tconst time = <T>(section: string, fn: () => T): T => {\n\t\tconst t1 = performance.now()\n\t\tconst result = fn()\n\t\tsectionTimings.push({ section, timing: performance.now() - t1 })\n\t\treturn result\n\t}\n\n\tconst hookNodes = getHookNodes(node)\n\n\t// API documentation\n\ttry {\n\t\tconst entries = time('useApiEndpoint', () => parseApiDocumentation(hookNodes.useApiEndpoint))\n\t\tentries.forEach((param) => {\n\t\t\tendpointData[param.identifier] = param.value as string & string[]\n\t\t})\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'api',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request params\n\ttry {\n\t\tendpointData.requestPathParams = time('usePathParams', () =>\n\t\t\tparseRequestParams(hookNodes.usePathParams, endpointPath),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'path',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request query\n\ttry {\n\t\tendpointData.requestQuery = time('useQueryParams', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useQueryParams, 'useQueryParams'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'query',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request headers\n\ttry {\n\t\tendpointData.requestHeaders = time('useHeaderParams', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useHeaderParams, 'useHeaderParams'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'headers',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Raw request body\n\ttry {\n\t\tconst parsedBody = time('useRequestRawBody', () => parseRequestRawBody(hookNodes.useRequestRawBody))\n\t\tif (parsedBody) {\n\t\t\tendpointData.rawBody = parsedBody\n\t\t}\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'rawBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Object request body\n\ttry {\n\t\tendpointData.objectBody = time('useRequestBody', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useRequestBody, 'useRequestBody'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'objectBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request response\n\ttry {\n\t\tendpointData.responses = time('response', () => parseRequestResponse(node))\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'response',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\treturn { endpoint: endpointData, sectionTimings }\n}\n\ntype HookName =\n\t| 'useApiEndpoint'\n\t| 'usePathParams'\n\t| 'useQueryParams'\n\t| 'useHeaderParams'\n\t| 'useRequestBody'\n\t| 'useRequestRawBody'\n\nconst getHookNodes = (endpointNode: Node<ts.Node>): Record<HookName, Node<ts.CallExpression> | null> => {\n\tconst result: Record<HookName, Node<ts.CallExpression> | null> = {\n\t\tuseApiEndpoint: null,\n\t\tusePathParams: null,\n\t\tuseQueryParams: null,\n\t\tuseHeaderParams: null,\n\t\tuseRequestBody: null,\n\t\tuseRequestRawBody: null,\n\t}\n\tfor (const node of endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n\t\tconst name = node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() as HookName | undefined\n\t\tif (name && name in result && result[name] === null) {\n\t\t\tresult[name] = node\n\t\t}\n\t}\n\treturn result\n}\n\nconst parseApiDocumentation = (hookNode: Node<ts.CallExpression> | null) => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in useApiEndpoint')\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\n\tconst values = getValuesOfObjectLiteral(objectLiteral).filter((param) => param.value !== null)\n\treturn values as {\n\t\tidentifier: keyof ApiEndpointDocs\n\t\tvalue: (typeof values)[number]['value']\n\t}[]\n}\n\nconst parseRequestParams = (\n\thookNode: Node<ts.CallExpression> | null,\n\tendpointPath: string,\n): EndpointData['requestPathParams'] => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in usePathParams')\n\t}\n\n\tconst declaredParams = endpointPath\n\t\t.split('/')\n\t\t.filter((segment) => segment.startsWith(':'))\n\t\t.map((segment) => ({\n\t\t\tname: segment.substring(1).replace(/\\?/, ''),\n\t\t\toptional: segment.includes('?'),\n\t\t}))\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: declaredParams.some((declared) => declared.name === param.identifier && declared.optional),\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestRawBody = (\n\thookNode: Node<ts.CallExpression> | null,\n): NonNullable<EndpointData['rawBody']> | null => {\n\tif (!hookNode) {\n\t\treturn null\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(\n\t\tparamNode.getLastChild((node) => !node.isKind(SyntaxKind.CommaToken))!,\n\t)\n\n\treturn {\n\t\tsignature: getValidatorPropertyShape(valueNode),\n\t\toptional: getValidatorPropertyOptionality(valueNode),\n\t\tdescription: getValidatorPropertyStringValue(valueNode, 'description'),\n\t\terrorMessage: getValidatorPropertyStringValue(valueNode, 'errorMessage'),\n\t}\n}\n\nconst parseRequestObjectInput = (\n\thookNode: Node<ts.CallExpression> | null,\n\tnodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',\n): EndpointData['requestQuery'] | EndpointData['objectBody'] => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error(`Non-literal type used in ${nodeName}`)\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: param.optional,\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestResponse = (node: Node<ts.Node>): EndpointData['responses'] => {\n\tconst implementationNode = node\n\t\t.getFirstChildByKind(SyntaxKind.CallExpression)!\n\t\t.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\t\t.getFirstChildByKind(SyntaxKind.ArrowFunction)!\n\tconst returnType = implementationNode.getReturnType()\n\n\tconst actualType = (() => {\n\t\tif (returnType.getText().startsWith('Promise')) {\n\t\t\treturn returnType.getTypeArguments()[0]\n\t\t}\n\t\treturn returnType\n\t})()\n\n\tconst responseType = getProperTypeShape(actualType, node)\n\n\treturn parseResponseTypes(responseType)\n}\n\nconst parseResponseTypes = (\n\tresponseType: ReturnType<typeof getProperTypeShape>,\n): EndpointData['responses'] => {\n\t// TODO: Add support for response descriptions and errors\n\tif (typeof responseType === 'string') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: responseType === 'void' || responseType === 'null' ? 204 : 200,\n\t\t\t\tcontentType: 'text/plain',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union_entry' || responseType[0].role === 'literal_string') {\n\t\treturn parseResponseTypes(responseType[0].shape)\n\t}\n\n\t// Response type is a useReturnValue hook\n\tif (responseType[0].role === 'property' && responseType[0].identifier === '_isUseReturnValue') {\n\t\tconst status = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'status',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn parseInt(property[0].shape)\n\t\t})()\n\t\tconst contentType = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'contentType',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn property[0].shape\n\t\t})()\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus,\n\t\t\t\tcontentType,\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union') {\n\t\tif (typeof responseType[0].shape === 'string') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tstatus: responseType[0].shape === 'void' || responseType[0].shape === 'null' ? 204 : 200,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tsignature: responseType[0].shape,\n\t\t\t\t\tdescription: '',\n\t\t\t\t\terrorMessage: '',\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn responseType[0].shape.flatMap((unionEntry) => {\n\t\t\treturn parseResponseTypes([unionEntry])\n\t\t})\n\t}\n\n\tif (responseType[0].role === 'buffer') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\tcontentType: 'application/octet-stream',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\treturn [\n\t\t{\n\t\t\tstatus: 200,\n\t\t\tcontentType: 'application/json',\n\t\t\tsignature: responseType,\n\t\t\tdescription: '',\n\t\t\terrorMessage: '',\n\t\t},\n\t]\n}\n"],"names":["parseEndpoint","node","sourceFilePath","parsedEndpointMethod","SyntaxKind","endpointMethod","endpointPath","resolveEndpointPath","endpointData","sectionTimings","time","section","fn","t1","result","hookNodes","getHookNodes","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","endpointNode","name","hookNode","paramNode","valueNode","findNodeImplementation","objectLiteral","getValuesOfObjectLiteral","declaredParams","segment","getShapeOfValidatorLiteral","declared","getValidatorPropertyShape","getValidatorPropertyOptionality","getValidatorPropertyStringValue","nodeName","returnType","actualType","responseType","getProperTypeShape","parseResponseTypes","status","property","response","contentType","unionEntry"],"mappings":"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"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { Node, ts } from 'ts-morph';
|
|
2
2
|
import { EndpointData } from '../types';
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export type SectionTiming = {
|
|
5
|
+
section: string;
|
|
6
|
+
timing: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const parseEndpoint: (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
9
|
+
endpoint: EndpointData;
|
|
10
|
+
sectionTimings: SectionTiming[];
|
|
11
|
+
};
|
|
5
12
|
//# sourceMappingURL=parseEndpoint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseEndpoint.d.ts","sourceRoot":"","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,EAAE,EAAE,MAAM,UAAU,CAAA;AAI/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAYvC,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"parseEndpoint.d.ts","sourceRoot":"","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,EAAE,EAAE,MAAM,UAAU,CAAA;AAI/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAYvC,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D,eAAO,MAAM,aAAa,SACnB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,kBACH,MAAM,KACpB;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,cAAc,EAAE,aAAa,EAAE,CAAA;CAuI3D,CAAA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { SyntaxKind as
|
|
2
|
-
import { Logger as
|
|
3
|
-
import { resolveEndpointPath as
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
method:
|
|
7
|
-
path:
|
|
8
|
-
sourceFilePath:
|
|
1
|
+
import { SyntaxKind as o } from "ts-morph";
|
|
2
|
+
import { Logger as l } from "../../utils/logger.mjs";
|
|
3
|
+
import { resolveEndpointPath as L, findNodeImplementation as g, getValuesOfObjectLiteral as B, getShapeOfValidatorLiteral as m, getValidatorPropertyStringValue as y, getValidatorPropertyOptionality as R, getValidatorPropertyShape as x, getProperTypeShape as w } from "./nodeParsers.mjs";
|
|
4
|
+
const O = (e, i) => {
|
|
5
|
+
const r = e.getFirstDescendantByKind(o.PropertyAccessExpression).getText().split(".")[1].toUpperCase(), t = r === "DEL" ? "DELETE" : r, a = L(e) ?? "", s = {
|
|
6
|
+
method: t,
|
|
7
|
+
path: a,
|
|
8
|
+
sourceFilePath: i,
|
|
9
9
|
requestPathParams: [],
|
|
10
10
|
requestQuery: [],
|
|
11
11
|
requestHeaders: [],
|
|
@@ -16,156 +16,181 @@ const w = (t, s) => {
|
|
|
16
16
|
summary: void 0,
|
|
17
17
|
description: void 0,
|
|
18
18
|
tags: void 0
|
|
19
|
-
}
|
|
19
|
+
}, u = [], d = (n, p) => {
|
|
20
|
+
const E = performance.now(), P = p();
|
|
21
|
+
return u.push({ section: n, timing: performance.now() - E }), P;
|
|
22
|
+
}, c = v(e);
|
|
20
23
|
try {
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
d("useApiEndpoint", () => K(c.useApiEndpoint)).forEach((p) => {
|
|
25
|
+
s[p.identifier] = p.value;
|
|
23
26
|
});
|
|
24
|
-
} catch (
|
|
25
|
-
|
|
27
|
+
} catch (n) {
|
|
28
|
+
l.error("Error", n);
|
|
26
29
|
}
|
|
27
30
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
s.requestPathParams = d(
|
|
32
|
+
"usePathParams",
|
|
33
|
+
() => q(c.usePathParams, a)
|
|
34
|
+
);
|
|
35
|
+
} catch (n) {
|
|
36
|
+
l.error("Error", n);
|
|
31
37
|
}
|
|
32
38
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
s.requestQuery = d(
|
|
40
|
+
"useQueryParams",
|
|
41
|
+
() => h(c.useQueryParams, "useQueryParams")
|
|
42
|
+
);
|
|
43
|
+
} catch (n) {
|
|
44
|
+
l.error("Error", n);
|
|
36
45
|
}
|
|
37
46
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
s.requestHeaders = d(
|
|
48
|
+
"useHeaderParams",
|
|
49
|
+
() => h(c.useHeaderParams, "useHeaderParams")
|
|
50
|
+
);
|
|
51
|
+
} catch (n) {
|
|
52
|
+
l.error("Error", n);
|
|
41
53
|
}
|
|
42
54
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
} catch (
|
|
46
|
-
|
|
55
|
+
const n = d("useRequestRawBody", () => C(c.useRequestRawBody));
|
|
56
|
+
n && (s.rawBody = n);
|
|
57
|
+
} catch (n) {
|
|
58
|
+
l.error("Error", n);
|
|
47
59
|
}
|
|
48
60
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
s.objectBody = d(
|
|
62
|
+
"useRequestBody",
|
|
63
|
+
() => h(c.useRequestBody, "useRequestBody")
|
|
64
|
+
);
|
|
65
|
+
} catch (n) {
|
|
66
|
+
l.error("Error", n);
|
|
52
67
|
}
|
|
53
68
|
try {
|
|
54
|
-
|
|
55
|
-
} catch (
|
|
56
|
-
|
|
69
|
+
s.responses = d("response", () => b(e));
|
|
70
|
+
} catch (n) {
|
|
71
|
+
l.error("Error", n);
|
|
72
|
+
}
|
|
73
|
+
return { endpoint: s, sectionTimings: u };
|
|
74
|
+
}, v = (e) => {
|
|
75
|
+
const i = {
|
|
76
|
+
useApiEndpoint: null,
|
|
77
|
+
usePathParams: null,
|
|
78
|
+
useQueryParams: null,
|
|
79
|
+
useHeaderParams: null,
|
|
80
|
+
useRequestBody: null,
|
|
81
|
+
useRequestRawBody: null
|
|
82
|
+
};
|
|
83
|
+
for (const r of e.getDescendantsOfKind(o.CallExpression)) {
|
|
84
|
+
const t = r.getFirstChildByKind(o.Identifier)?.getText();
|
|
85
|
+
t && t in i && i[t] === null && (i[t] = r);
|
|
57
86
|
}
|
|
58
|
-
return
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
if (!s)
|
|
87
|
+
return i;
|
|
88
|
+
}, K = (e) => {
|
|
89
|
+
if (!e)
|
|
62
90
|
return [];
|
|
63
|
-
const
|
|
64
|
-
if (!r.isKind(
|
|
91
|
+
const i = e.getFirstChildByKind(o.SyntaxList), r = g(i.getLastChild());
|
|
92
|
+
if (!r.isKind(o.ObjectLiteralExpression))
|
|
65
93
|
throw new Error("Non-literal type used in useApiEndpoint");
|
|
66
|
-
const
|
|
67
|
-
return
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
if (!o)
|
|
94
|
+
const t = r.asKind(o.ObjectLiteralExpression);
|
|
95
|
+
return B(t).filter((s) => s.value !== null);
|
|
96
|
+
}, q = (e, i) => {
|
|
97
|
+
if (!e)
|
|
71
98
|
return [];
|
|
72
|
-
const r =
|
|
73
|
-
if (!
|
|
99
|
+
const r = e.getFirstChildByKind(o.SyntaxList), t = g(r.getLastChild());
|
|
100
|
+
if (!t.isKind(o.ObjectLiteralExpression))
|
|
74
101
|
throw new Error("Non-literal type used in usePathParams");
|
|
75
|
-
const
|
|
76
|
-
name:
|
|
77
|
-
optional:
|
|
78
|
-
})),
|
|
79
|
-
return
|
|
80
|
-
identifier:
|
|
81
|
-
signature:
|
|
82
|
-
optional:
|
|
83
|
-
description:
|
|
84
|
-
errorMessage:
|
|
102
|
+
const a = i.split("/").filter((u) => u.startsWith(":")).map((u) => ({
|
|
103
|
+
name: u.substring(1).replace(/\?/, ""),
|
|
104
|
+
optional: u.includes("?")
|
|
105
|
+
})), s = t.asKind(o.ObjectLiteralExpression);
|
|
106
|
+
return m(s).filter((u) => u.shape !== null).map((u) => ({
|
|
107
|
+
identifier: u.identifier,
|
|
108
|
+
signature: u.shape,
|
|
109
|
+
optional: a.some((d) => d.name === u.identifier && d.optional),
|
|
110
|
+
description: u.description,
|
|
111
|
+
errorMessage: u.errorMessage
|
|
85
112
|
}));
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
if (!s)
|
|
113
|
+
}, C = (e) => {
|
|
114
|
+
if (!e)
|
|
89
115
|
return null;
|
|
90
|
-
const
|
|
91
|
-
|
|
116
|
+
const i = e.getFirstChildByKind(o.SyntaxList), r = g(
|
|
117
|
+
i.getLastChild((t) => !t.isKind(o.CommaToken))
|
|
92
118
|
);
|
|
93
119
|
return {
|
|
94
|
-
signature:
|
|
95
|
-
optional:
|
|
96
|
-
description:
|
|
97
|
-
errorMessage:
|
|
120
|
+
signature: x(r),
|
|
121
|
+
optional: R(r),
|
|
122
|
+
description: y(r, "description"),
|
|
123
|
+
errorMessage: y(r, "errorMessage")
|
|
98
124
|
};
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
if (!o)
|
|
125
|
+
}, h = (e, i) => {
|
|
126
|
+
if (!e)
|
|
102
127
|
return [];
|
|
103
|
-
const r =
|
|
104
|
-
if (!
|
|
105
|
-
throw new Error(`Non-literal type used in ${
|
|
106
|
-
const
|
|
107
|
-
return
|
|
108
|
-
identifier:
|
|
109
|
-
signature:
|
|
110
|
-
optional:
|
|
111
|
-
description:
|
|
112
|
-
errorMessage:
|
|
128
|
+
const r = e.getFirstChildByKind(o.SyntaxList), t = g(r.getLastChild());
|
|
129
|
+
if (!t.isKind(o.ObjectLiteralExpression))
|
|
130
|
+
throw new Error(`Non-literal type used in ${i}`);
|
|
131
|
+
const a = t.asKind(o.ObjectLiteralExpression);
|
|
132
|
+
return m(a).filter((s) => s.shape !== null).map((s) => ({
|
|
133
|
+
identifier: s.identifier,
|
|
134
|
+
signature: s.shape,
|
|
135
|
+
optional: s.optional,
|
|
136
|
+
description: s.description,
|
|
137
|
+
errorMessage: s.errorMessage
|
|
113
138
|
}));
|
|
114
|
-
},
|
|
115
|
-
const
|
|
116
|
-
return
|
|
117
|
-
},
|
|
118
|
-
if (typeof
|
|
139
|
+
}, b = (e) => {
|
|
140
|
+
const r = e.getFirstChildByKind(o.CallExpression).getFirstChildByKind(o.SyntaxList).getFirstChildByKind(o.ArrowFunction).getReturnType(), t = r.getText().startsWith("Promise") ? r.getTypeArguments()[0] : r, a = w(t, e);
|
|
141
|
+
return f(a);
|
|
142
|
+
}, f = (e) => {
|
|
143
|
+
if (typeof e == "string")
|
|
119
144
|
return [
|
|
120
145
|
{
|
|
121
|
-
status:
|
|
146
|
+
status: e === "void" || e === "null" ? 204 : 200,
|
|
122
147
|
contentType: "text/plain",
|
|
123
|
-
signature:
|
|
148
|
+
signature: e,
|
|
124
149
|
description: "",
|
|
125
150
|
errorMessage: ""
|
|
126
151
|
}
|
|
127
152
|
];
|
|
128
|
-
if (
|
|
129
|
-
return
|
|
130
|
-
if (
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
(
|
|
153
|
+
if (e[0].role === "union_entry" || e[0].role === "literal_string")
|
|
154
|
+
return f(e[0].shape);
|
|
155
|
+
if (e[0].role === "property" && e[0].identifier === "_isUseReturnValue") {
|
|
156
|
+
const i = (() => {
|
|
157
|
+
const t = e.find(
|
|
158
|
+
(a) => a.role === "property" && a.identifier === "status"
|
|
134
159
|
)?.shape;
|
|
135
|
-
if (!
|
|
160
|
+
if (!t || typeof t == "string" || typeof t[0].shape != "string")
|
|
136
161
|
throw new Error("Invalid useReturnValue hook");
|
|
137
|
-
return parseInt(
|
|
138
|
-
})(),
|
|
139
|
-
const
|
|
140
|
-
(
|
|
162
|
+
return parseInt(t[0].shape);
|
|
163
|
+
})(), r = (() => {
|
|
164
|
+
const t = e.find(
|
|
165
|
+
(a) => a.role === "property" && a.identifier === "contentType"
|
|
141
166
|
)?.shape;
|
|
142
|
-
if (!
|
|
167
|
+
if (!t || typeof t == "string" || typeof t[0].shape != "string")
|
|
143
168
|
throw new Error("Invalid useReturnValue hook");
|
|
144
|
-
return
|
|
169
|
+
return t[0].shape;
|
|
145
170
|
})();
|
|
146
171
|
return [
|
|
147
172
|
{
|
|
148
|
-
status:
|
|
149
|
-
contentType:
|
|
150
|
-
signature:
|
|
173
|
+
status: i,
|
|
174
|
+
contentType: r,
|
|
175
|
+
signature: e,
|
|
151
176
|
description: "",
|
|
152
177
|
errorMessage: ""
|
|
153
178
|
}
|
|
154
179
|
];
|
|
155
180
|
}
|
|
156
|
-
return
|
|
181
|
+
return e[0].role === "union" ? typeof e[0].shape == "string" ? [
|
|
157
182
|
{
|
|
158
|
-
status:
|
|
183
|
+
status: e[0].shape === "void" || e[0].shape === "null" ? 204 : 200,
|
|
159
184
|
contentType: "application/json",
|
|
160
|
-
signature:
|
|
185
|
+
signature: e[0].shape,
|
|
161
186
|
description: "",
|
|
162
187
|
errorMessage: ""
|
|
163
188
|
}
|
|
164
|
-
] :
|
|
189
|
+
] : e[0].shape.flatMap((i) => f([i])) : e[0].role === "buffer" ? [
|
|
165
190
|
{
|
|
166
191
|
status: 200,
|
|
167
192
|
contentType: "application/octet-stream",
|
|
168
|
-
signature:
|
|
193
|
+
signature: e,
|
|
169
194
|
description: "",
|
|
170
195
|
errorMessage: ""
|
|
171
196
|
}
|
|
@@ -173,13 +198,13 @@ const w = (t, s) => {
|
|
|
173
198
|
{
|
|
174
199
|
status: 200,
|
|
175
200
|
contentType: "application/json",
|
|
176
|
-
signature:
|
|
201
|
+
signature: e,
|
|
177
202
|
description: "",
|
|
178
203
|
errorMessage: ""
|
|
179
204
|
}
|
|
180
205
|
];
|
|
181
206
|
};
|
|
182
207
|
export {
|
|
183
|
-
|
|
208
|
+
O as parseEndpoint
|
|
184
209
|
};
|
|
185
210
|
//# sourceMappingURL=parseEndpoint.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseEndpoint.mjs","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"sourcesContent":["import { Node, SyntaxKind, ts } from 'ts-morph'\n\nimport { ApiEndpointDocs } from '../../hooks/useApiEndpoint'\nimport { Logger } from '../../utils/logger'\nimport { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n\tresolveEndpointPath,\n} from './nodeParsers'\n\nexport const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {\n\tconst parsedEndpointMethod = node\n\t\t.getFirstDescendantByKind(SyntaxKind.PropertyAccessExpression)!\n\t\t.getText()\n\t\t.split('.')[1]\n\t\t.toUpperCase()\n\n\tconst endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod\n\n\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\tconst endpointData: EndpointData = {\n\t\tmethod: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n\t\tpath: endpointPath,\n\t\tsourceFilePath,\n\t\trequestPathParams: [],\n\t\trequestQuery: [],\n\t\trequestHeaders: [],\n\t\trawBody: undefined,\n\t\tobjectBody: [],\n\t\tresponses: [],\n\t\tname: undefined,\n\t\tsummary: undefined,\n\t\tdescription: undefined,\n\t\ttags: undefined,\n\t}\n\n\tconst warningData: {\n\t\tsegment: string\n\t\terror: Error\n\t}[] = []\n\n\t// API documentation\n\ttry {\n\t\tconst entries = parseApiDocumentation(node)\n\t\tentries.forEach((param) => {\n\t\t\tendpointData[param.identifier] = param.value as string & string[]\n\t\t})\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'api',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request params\n\ttry {\n\t\tendpointData.requestPathParams = parseRequestParams(node, endpointPath)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'path',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request query\n\ttry {\n\t\tendpointData.requestQuery = parseRequestObjectInput(node, 'useQueryParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'query',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request headers\n\ttry {\n\t\tendpointData.requestHeaders = parseRequestObjectInput(node, 'useHeaderParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'headers',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Raw request body\n\ttry {\n\t\tconst parsedBody = parseRequestRawBody(node)\n\t\tif (parsedBody) {\n\t\t\tendpointData.rawBody = parsedBody\n\t\t}\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'rawBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Object request body\n\ttry {\n\t\tendpointData.objectBody = parseRequestObjectInput(node, 'useRequestBody')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'objectBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request response\n\ttry {\n\t\tendpointData.responses = parseRequestResponse(node)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'response',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\treturn endpointData\n}\n\nconst getHookNode = (\n\tendpointNode: Node<ts.Node>,\n\thookName:\n\t\t| 'useApiEndpoint'\n\t\t| 'usePathParams'\n\t\t| 'useQueryParams'\n\t\t| 'useHeaderParams'\n\t\t| 'useRequestBody'\n\t\t| 'useRequestRawBody',\n) => {\n\tconst callExpressions = endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)\n\tconst matchingCallExpressions = callExpressions.filter((node) => {\n\t\treturn node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === hookName\n\t})\n\treturn matchingCallExpressions[0] ?? null\n}\n\nconst parseApiDocumentation = (node: Node<ts.Node>) => {\n\tconst hookNode = getHookNode(node, 'useApiEndpoint')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in useApiEndpoint')\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\n\tconst values = getValuesOfObjectLiteral(objectLiteral).filter((param) => param.value !== null)\n\treturn values as {\n\t\tidentifier: keyof ApiEndpointDocs\n\t\tvalue: (typeof values)[number]['value']\n\t}[]\n}\n\nconst parseRequestParams = (node: Node<ts.Node>, endpointPath: string): EndpointData['requestPathParams'] => {\n\tconst hookNode = getHookNode(node, 'usePathParams')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in usePathParams')\n\t}\n\n\tconst declaredParams = endpointPath\n\t\t.split('/')\n\t\t.filter((segment) => segment.startsWith(':'))\n\t\t.map((segment) => ({\n\t\t\tname: segment.substring(1).replace(/\\?/, ''),\n\t\t\toptional: segment.includes('?'),\n\t\t}))\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: declaredParams.some((declared) => declared.name === param.identifier && declared.optional),\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestRawBody = (node: Node<ts.Node>): NonNullable<EndpointData['rawBody']> | null => {\n\tconst hookNode = getHookNode(node, 'useRequestRawBody')\n\tif (!hookNode) {\n\t\treturn null\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(\n\t\tparamNode.getLastChild((node) => !node.isKind(SyntaxKind.CommaToken))!,\n\t)\n\n\treturn {\n\t\tsignature: getValidatorPropertyShape(valueNode),\n\t\toptional: getValidatorPropertyOptionality(valueNode),\n\t\tdescription: getValidatorPropertyStringValue(valueNode, 'description'),\n\t\terrorMessage: getValidatorPropertyStringValue(valueNode, 'errorMessage'),\n\t}\n}\n\nconst parseRequestObjectInput = (\n\tnode: Node<ts.Node>,\n\tnodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',\n): EndpointData['requestQuery'] | EndpointData['objectBody'] => {\n\tconst hookNode = getHookNode(node, nodeName)\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error(`Non-literal type used in ${nodeName}`)\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: param.optional,\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestResponse = (node: Node<ts.Node>): EndpointData['responses'] => {\n\tconst implementationNode = node\n\t\t.getFirstChildByKind(SyntaxKind.CallExpression)!\n\t\t.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\t\t.getFirstChildByKind(SyntaxKind.ArrowFunction)!\n\tconst returnType = implementationNode.getReturnType()\n\n\tconst actualType = (() => {\n\t\tif (returnType.getText().startsWith('Promise')) {\n\t\t\treturn returnType.getTypeArguments()[0]\n\t\t}\n\t\treturn returnType\n\t})()\n\n\tconst responseType = getProperTypeShape(actualType, node)\n\n\treturn parseResponseTypes(responseType)\n}\n\nconst parseResponseTypes = (\n\tresponseType: ReturnType<typeof getProperTypeShape>,\n): EndpointData['responses'] => {\n\t// TODO: Add support for response descriptions and errors\n\tif (typeof responseType === 'string') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: responseType === 'void' || responseType === 'null' ? 204 : 200,\n\t\t\t\tcontentType: 'text/plain',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union_entry' || responseType[0].role === 'literal_string') {\n\t\treturn parseResponseTypes(responseType[0].shape)\n\t}\n\n\t// Response type is a useReturnValue hook\n\tif (responseType[0].role === 'property' && responseType[0].identifier === '_isUseReturnValue') {\n\t\tconst status = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'status',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn parseInt(property[0].shape)\n\t\t})()\n\t\tconst contentType = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'contentType',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn property[0].shape\n\t\t})()\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus,\n\t\t\t\tcontentType,\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union') {\n\t\tif (typeof responseType[0].shape === 'string') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tstatus: responseType[0].shape === 'void' || responseType[0].shape === 'null' ? 204 : 200,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tsignature: responseType[0].shape,\n\t\t\t\t\tdescription: '',\n\t\t\t\t\terrorMessage: '',\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn responseType[0].shape.flatMap((unionEntry) => {\n\t\t\treturn parseResponseTypes([unionEntry])\n\t\t})\n\t}\n\n\tif (responseType[0].role === 'buffer') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\tcontentType: 'application/octet-stream',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\treturn [\n\t\t{\n\t\t\tstatus: 200,\n\t\t\tcontentType: 'application/json',\n\t\t\tsignature: responseType,\n\t\t\tdescription: '',\n\t\t\terrorMessage: '',\n\t\t},\n\t]\n}\n"],"names":["parseEndpoint","node","sourceFilePath","parsedEndpointMethod","SyntaxKind","endpointMethod","endpointPath","resolveEndpointPath","endpointData","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","getHookNode","endpointNode","hookName","hookNode","paramNode","valueNode","findNodeImplementation","objectLiteral","getValuesOfObjectLiteral","declaredParams","segment","getShapeOfValidatorLiteral","declared","getValidatorPropertyShape","getValidatorPropertyOptionality","getValidatorPropertyStringValue","nodeName","returnType","actualType","responseType","getProperTypeShape","parseResponseTypes","status","property","response","contentType","unionEntry"],"mappings":";;;AAgBa,MAAAA,IAAgB,CAACC,GAAqBC,MAA2B;AAC7E,QAAMC,IAAuBF,EAC3B,yBAAyBG,EAAW,wBAAwB,EAC5D,QAAQ,EACR,MAAM,GAAG,EAAE,CAAC,EACZ,YAAY,GAERC,IAAiBF,MAAyB,QAAQ,WAAWA,GAE7DG,IAAeC,EAAoBN,CAAI,KAAK,IAE5CO,IAA6B;AAAA,IAClC,QAAQH;AAAA,IACR,MAAMC;AAAA,IACN,gBAAAJ;AAAA,IACA,mBAAmB,CAAC;AAAA,IACpB,cAAc,CAAC;AAAA,IACf,gBAAgB,CAAC;AAAA,IACjB,SAAS;AAAA,IACT,YAAY,CAAC;AAAA,IACb,WAAW,CAAC;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,EACP;AAQI,MAAA;AAEK,IADQO,EAAsBR,CAAI,EAClC,QAAQ,CAACS,MAAU;AACb,MAAAF,EAAAE,EAAM,UAAU,IAAIA,EAAM;AAAA,IAAA,CACvC;AAAA,WACOC,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACU,IAAAH,EAAA,oBAAoBK,EAAmBZ,GAAMK,CAAY;AAAA,WAC9DK,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACU,IAAAH,EAAA,eAAeM,EAAwBb,GAAM,gBAAgB;AAAA,WAClEU,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACU,IAAAH,EAAA,iBAAiBM,EAAwBb,GAAM,iBAAiB;AAAA,WACrEU,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACG,UAAAI,IAAaC,EAAoBf,CAAI;AAC3C,IAAIc,MACHP,EAAa,UAAUO;AAAA,WAEhBJ,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACU,IAAAH,EAAA,aAAaM,EAAwBb,GAAM,gBAAgB;AAAA,WAChEU,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAItB,MAAA;AACU,IAAAH,EAAA,YAAYS,EAAqBhB,CAAI;AAAA,WAC1CU,GAAK;AAKN,IAAAC,EAAA,MAAM,SAASD,CAAG;AAAA,EAAA;AAGnB,SAAAH;AACR,GAEMU,IAAc,CACnBC,GACAC,MAQwBD,EAAa,qBAAqBf,EAAW,cAAc,EACnC,OAAO,CAACH,MAChDA,EAAK,oBAAoBG,EAAW,UAAU,GAAG,cAAcgB,CACtE,EAC8B,CAAC,KAAK,MAGhCX,IAAwB,CAACR,MAAwB;AAChD,QAAAoB,IAAWH,EAAYjB,GAAM,gBAAgB;AACnD,MAAI,CAACoB;AACJ,WAAO,CAAC;AAET,QAAMC,IAAYD,EAAS,oBAAoBjB,EAAW,UAAU,GAC9DmB,IAAYC,EAAuBF,EAAU,aAAA,CAAe;AAElE,MAAI,CAACC,EAAU,OAAOnB,EAAW,uBAAuB;AACjD,UAAA,IAAI,MAAM,yCAAyC;AAG1D,QAAMqB,IAAgBF,EAAU,OAAOnB,EAAW,uBAAuB;AAGlE,SADQsB,EAAyBD,CAAa,EAAE,OAAO,CAACf,MAAUA,EAAM,UAAU,IAAI;AAK9F,GAEMG,IAAqB,CAACZ,GAAqBK,MAA4D;AACtG,QAAAe,IAAWH,EAAYjB,GAAM,eAAe;AAClD,MAAI,CAACoB;AACJ,WAAO,CAAC;AAGT,QAAMC,IAAYD,EAAS,oBAAoBjB,EAAW,UAAU,GAC9DmB,IAAYC,EAAuBF,EAAU,aAAA,CAAe;AAElE,MAAI,CAACC,EAAU,OAAOnB,EAAW,uBAAuB;AACjD,UAAA,IAAI,MAAM,wCAAwC;AAGzD,QAAMuB,IAAiBrB,EACrB,MAAM,GAAG,EACT,OAAO,CAACsB,MAAYA,EAAQ,WAAW,GAAG,CAAC,EAC3C,IAAI,CAACA,OAAa;AAAA,IAClB,MAAMA,EAAQ,UAAU,CAAC,EAAE,QAAQ,MAAM,EAAE;AAAA,IAC3C,UAAUA,EAAQ,SAAS,GAAG;AAAA,EAAA,EAC7B,GAEGH,IAAgBF,EAAU,OAAOnB,EAAW,uBAAuB;AACzE,SAAOyB,EAA2BJ,CAAa,EAC7C,OAAO,CAACf,MAAUA,EAAM,UAAU,IAAI,EACtC,IAAI,CAACA,OAAW;AAAA,IAChB,YAAYA,EAAM;AAAA,IAClB,WAAWA,EAAM;AAAA,IACjB,UAAUiB,EAAe,KAAK,CAACG,MAAaA,EAAS,SAASpB,EAAM,cAAcoB,EAAS,QAAQ;AAAA,IACnG,aAAapB,EAAM;AAAA,IACnB,cAAcA,EAAM;AAAA,EAAA,EACnB;AACJ,GAEMM,IAAsB,CAACf,MAAqE;AAC3F,QAAAoB,IAAWH,EAAYjB,GAAM,mBAAmB;AACtD,MAAI,CAACoB;AACG,WAAA;AAER,QAAMC,IAAYD,EAAS,oBAAoBjB,EAAW,UAAU,GAC9DmB,IAAYC;AAAA,IACjBF,EAAU,aAAa,CAACrB,MAAS,CAACA,EAAK,OAAOG,EAAW,UAAU,CAAC;AAAA,EACrE;AAEO,SAAA;AAAA,IACN,WAAW2B,EAA0BR,CAAS;AAAA,IAC9C,UAAUS,EAAgCT,CAAS;AAAA,IACnD,aAAaU,EAAgCV,GAAW,aAAa;AAAA,IACrE,cAAcU,EAAgCV,GAAW,cAAc;AAAA,EACxE;AACD,GAEMT,IAA0B,CAC/Bb,GACAiC,MAC+D;AACzD,QAAAb,IAAWH,EAAYjB,GAAMiC,CAAQ;AAC3C,MAAI,CAACb;AACJ,WAAO,CAAC;AAET,QAAMC,IAAYD,EAAS,oBAAoBjB,EAAW,UAAU,GAC9DmB,IAAYC,EAAuBF,EAAU,aAAA,CAAe;AAElE,MAAI,CAACC,EAAU,OAAOnB,EAAW,uBAAuB;AACvD,UAAM,IAAI,MAAM,4BAA4B8B,CAAQ,EAAE;AAGvD,QAAMT,IAAgBF,EAAU,OAAOnB,EAAW,uBAAuB;AACzE,SAAOyB,EAA2BJ,CAAa,EAC7C,OAAO,CAACf,MAAUA,EAAM,UAAU,IAAI,EACtC,IAAI,CAACA,OAAW;AAAA,IAChB,YAAYA,EAAM;AAAA,IAClB,WAAWA,EAAM;AAAA,IACjB,UAAUA,EAAM;AAAA,IAChB,aAAaA,EAAM;AAAA,IACnB,cAAcA,EAAM;AAAA,EAAA,EACnB;AACJ,GAEMO,IAAuB,CAAChB,MAAmD;AAK1E,QAAAkC,IAJqBlC,EACzB,oBAAoBG,EAAW,cAAc,EAC7C,oBAAoBA,EAAW,UAAU,EACzC,oBAAoBA,EAAW,aAAa,EACR,cAAc,GAE9CgC,IACDD,EAAW,QAAA,EAAU,WAAW,SAAS,IACrCA,EAAW,iBAAiB,EAAE,CAAC,IAEhCA,GAGFE,IAAeC,EAAmBF,GAAYnC,CAAI;AAExD,SAAOsC,EAAmBF,CAAY;AACvC,GAEME,IAAqB,CAC1BF,MAC+B;AAE3B,MAAA,OAAOA,KAAiB;AACpB,WAAA;AAAA,MACN;AAAA,QACC,QAAQA,MAAiB,UAAUA,MAAiB,SAAS,MAAM;AAAA,QACnE,aAAa;AAAA,QACb,WAAWA;AAAA,QACX,aAAa;AAAA,QACb,cAAc;AAAA,MAAA;AAAA,IAEhB;AAGG,MAAAA,EAAa,CAAC,EAAE,SAAS,iBAAiBA,EAAa,CAAC,EAAE,SAAS;AACtE,WAAOE,EAAmBF,EAAa,CAAC,EAAE,KAAK;AAI5C,MAAAA,EAAa,CAAC,EAAE,SAAS,cAAcA,EAAa,CAAC,EAAE,eAAe,qBAAqB;AAC9F,UAAMG,KAAU,MAAM;AACrB,YAAMC,IAAWJ,EAAa;AAAA,QAC7B,CAACK,MAAaA,EAAS,SAAS,cAAcA,EAAS,eAAe;AAAA,MAAA,GACpE;AACC,UAAA,CAACD,KAAY,OAAOA,KAAa,YAAY,OAAOA,EAAS,CAAC,EAAE,SAAU;AACvE,cAAA,IAAI,MAAM,6BAA6B;AAE9C,aAAO,SAASA,EAAS,CAAC,EAAE,KAAK;AAAA,IAAA,GAC/B,GACGE,KAAe,MAAM;AAC1B,YAAMF,IAAWJ,EAAa;AAAA,QAC7B,CAACK,MAAaA,EAAS,SAAS,cAAcA,EAAS,eAAe;AAAA,MAAA,GACpE;AACC,UAAA,CAACD,KAAY,OAAOA,KAAa,YAAY,OAAOA,EAAS,CAAC,EAAE,SAAU;AACvE,cAAA,IAAI,MAAM,6BAA6B;AAEvC,aAAAA,EAAS,CAAC,EAAE;AAAA,IAAA,GACjB;AACI,WAAA;AAAA,MACN;AAAA,QACC,QAAAD;AAAA,QACA,aAAAG;AAAA,QACA,WAAWN;AAAA,QACX,aAAa;AAAA,QACb,cAAc;AAAA,MAAA;AAAA,IAEhB;AAAA,EAAA;AAGD,SAAIA,EAAa,CAAC,EAAE,SAAS,UACxB,OAAOA,EAAa,CAAC,EAAE,SAAU,WAC7B;AAAA,IACN;AAAA,MACC,QAAQA,EAAa,CAAC,EAAE,UAAU,UAAUA,EAAa,CAAC,EAAE,UAAU,SAAS,MAAM;AAAA,MACrF,aAAa;AAAA,MACb,WAAWA,EAAa,CAAC,EAAE;AAAA,MAC3B,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAEhB,IAGMA,EAAa,CAAC,EAAE,MAAM,QAAQ,CAACO,MAC9BL,EAAmB,CAACK,CAAU,CAAC,CACtC,IAGEP,EAAa,CAAC,EAAE,SAAS,WACrB;AAAA,IACN;AAAA,MACC,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAWA;AAAA,MACX,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAEhB,IAGM;AAAA,IACN;AAAA,MACC,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAWA;AAAA,MACX,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAEhB;AACD;"}
|
|
1
|
+
{"version":3,"file":"parseEndpoint.mjs","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"sourcesContent":["import { Node, SyntaxKind, ts } from 'ts-morph'\n\nimport { ApiEndpointDocs } from '../../hooks/useApiEndpoint'\nimport { Logger } from '../../utils/logger'\nimport { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n\tresolveEndpointPath,\n} from './nodeParsers'\n\nexport type SectionTiming = { section: string; timing: number }\n\nexport const parseEndpoint = (\n\tnode: Node<ts.Node>,\n\tsourceFilePath: string,\n): { endpoint: EndpointData; sectionTimings: SectionTiming[] } => {\n\tconst parsedEndpointMethod = node\n\t\t.getFirstDescendantByKind(SyntaxKind.PropertyAccessExpression)!\n\t\t.getText()\n\t\t.split('.')[1]\n\t\t.toUpperCase()\n\n\tconst endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod\n\n\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\tconst endpointData: EndpointData = {\n\t\tmethod: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n\t\tpath: endpointPath,\n\t\tsourceFilePath,\n\t\trequestPathParams: [],\n\t\trequestQuery: [],\n\t\trequestHeaders: [],\n\t\trawBody: undefined,\n\t\tobjectBody: [],\n\t\tresponses: [],\n\t\tname: undefined,\n\t\tsummary: undefined,\n\t\tdescription: undefined,\n\t\ttags: undefined,\n\t}\n\n\tconst warningData: {\n\t\tsegment: string\n\t\terror: Error\n\t}[] = []\n\n\tconst sectionTimings: SectionTiming[] = []\n\n\tconst time = <T>(section: string, fn: () => T): T => {\n\t\tconst t1 = performance.now()\n\t\tconst result = fn()\n\t\tsectionTimings.push({ section, timing: performance.now() - t1 })\n\t\treturn result\n\t}\n\n\tconst hookNodes = getHookNodes(node)\n\n\t// API documentation\n\ttry {\n\t\tconst entries = time('useApiEndpoint', () => parseApiDocumentation(hookNodes.useApiEndpoint))\n\t\tentries.forEach((param) => {\n\t\t\tendpointData[param.identifier] = param.value as string & string[]\n\t\t})\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'api',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request params\n\ttry {\n\t\tendpointData.requestPathParams = time('usePathParams', () =>\n\t\t\tparseRequestParams(hookNodes.usePathParams, endpointPath),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'path',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request query\n\ttry {\n\t\tendpointData.requestQuery = time('useQueryParams', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useQueryParams, 'useQueryParams'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'query',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request headers\n\ttry {\n\t\tendpointData.requestHeaders = time('useHeaderParams', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useHeaderParams, 'useHeaderParams'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'headers',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Raw request body\n\ttry {\n\t\tconst parsedBody = time('useRequestRawBody', () => parseRequestRawBody(hookNodes.useRequestRawBody))\n\t\tif (parsedBody) {\n\t\t\tendpointData.rawBody = parsedBody\n\t\t}\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'rawBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Object request body\n\ttry {\n\t\tendpointData.objectBody = time('useRequestBody', () =>\n\t\t\tparseRequestObjectInput(hookNodes.useRequestBody, 'useRequestBody'),\n\t\t)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'objectBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request response\n\ttry {\n\t\tendpointData.responses = time('response', () => parseRequestResponse(node))\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'response',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\treturn { endpoint: endpointData, sectionTimings }\n}\n\ntype HookName =\n\t| 'useApiEndpoint'\n\t| 'usePathParams'\n\t| 'useQueryParams'\n\t| 'useHeaderParams'\n\t| 'useRequestBody'\n\t| 'useRequestRawBody'\n\nconst getHookNodes = (endpointNode: Node<ts.Node>): Record<HookName, Node<ts.CallExpression> | null> => {\n\tconst result: Record<HookName, Node<ts.CallExpression> | null> = {\n\t\tuseApiEndpoint: null,\n\t\tusePathParams: null,\n\t\tuseQueryParams: null,\n\t\tuseHeaderParams: null,\n\t\tuseRequestBody: null,\n\t\tuseRequestRawBody: null,\n\t}\n\tfor (const node of endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)) {\n\t\tconst name = node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() as HookName | undefined\n\t\tif (name && name in result && result[name] === null) {\n\t\t\tresult[name] = node\n\t\t}\n\t}\n\treturn result\n}\n\nconst parseApiDocumentation = (hookNode: Node<ts.CallExpression> | null) => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in useApiEndpoint')\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\n\tconst values = getValuesOfObjectLiteral(objectLiteral).filter((param) => param.value !== null)\n\treturn values as {\n\t\tidentifier: keyof ApiEndpointDocs\n\t\tvalue: (typeof values)[number]['value']\n\t}[]\n}\n\nconst parseRequestParams = (\n\thookNode: Node<ts.CallExpression> | null,\n\tendpointPath: string,\n): EndpointData['requestPathParams'] => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in usePathParams')\n\t}\n\n\tconst declaredParams = endpointPath\n\t\t.split('/')\n\t\t.filter((segment) => segment.startsWith(':'))\n\t\t.map((segment) => ({\n\t\t\tname: segment.substring(1).replace(/\\?/, ''),\n\t\t\toptional: segment.includes('?'),\n\t\t}))\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: declaredParams.some((declared) => declared.name === param.identifier && declared.optional),\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestRawBody = (\n\thookNode: Node<ts.CallExpression> | null,\n): NonNullable<EndpointData['rawBody']> | null => {\n\tif (!hookNode) {\n\t\treturn null\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(\n\t\tparamNode.getLastChild((node) => !node.isKind(SyntaxKind.CommaToken))!,\n\t)\n\n\treturn {\n\t\tsignature: getValidatorPropertyShape(valueNode),\n\t\toptional: getValidatorPropertyOptionality(valueNode),\n\t\tdescription: getValidatorPropertyStringValue(valueNode, 'description'),\n\t\terrorMessage: getValidatorPropertyStringValue(valueNode, 'errorMessage'),\n\t}\n}\n\nconst parseRequestObjectInput = (\n\thookNode: Node<ts.CallExpression> | null,\n\tnodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',\n): EndpointData['requestQuery'] | EndpointData['objectBody'] => {\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error(`Non-literal type used in ${nodeName}`)\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: param.optional,\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestResponse = (node: Node<ts.Node>): EndpointData['responses'] => {\n\tconst implementationNode = node\n\t\t.getFirstChildByKind(SyntaxKind.CallExpression)!\n\t\t.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\t\t.getFirstChildByKind(SyntaxKind.ArrowFunction)!\n\tconst returnType = implementationNode.getReturnType()\n\n\tconst actualType = (() => {\n\t\tif (returnType.getText().startsWith('Promise')) {\n\t\t\treturn returnType.getTypeArguments()[0]\n\t\t}\n\t\treturn returnType\n\t})()\n\n\tconst responseType = getProperTypeShape(actualType, node)\n\n\treturn parseResponseTypes(responseType)\n}\n\nconst parseResponseTypes = (\n\tresponseType: ReturnType<typeof getProperTypeShape>,\n): EndpointData['responses'] => {\n\t// TODO: Add support for response descriptions and errors\n\tif (typeof responseType === 'string') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: responseType === 'void' || responseType === 'null' ? 204 : 200,\n\t\t\t\tcontentType: 'text/plain',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union_entry' || responseType[0].role === 'literal_string') {\n\t\treturn parseResponseTypes(responseType[0].shape)\n\t}\n\n\t// Response type is a useReturnValue hook\n\tif (responseType[0].role === 'property' && responseType[0].identifier === '_isUseReturnValue') {\n\t\tconst status = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'status',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn parseInt(property[0].shape)\n\t\t})()\n\t\tconst contentType = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'contentType',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn property[0].shape\n\t\t})()\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus,\n\t\t\t\tcontentType,\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union') {\n\t\tif (typeof responseType[0].shape === 'string') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tstatus: responseType[0].shape === 'void' || responseType[0].shape === 'null' ? 204 : 200,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tsignature: responseType[0].shape,\n\t\t\t\t\tdescription: '',\n\t\t\t\t\terrorMessage: '',\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn responseType[0].shape.flatMap((unionEntry) => {\n\t\t\treturn parseResponseTypes([unionEntry])\n\t\t})\n\t}\n\n\tif (responseType[0].role === 'buffer') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\tcontentType: 'application/octet-stream',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\treturn [\n\t\t{\n\t\t\tstatus: 200,\n\t\t\tcontentType: 'application/json',\n\t\t\tsignature: responseType,\n\t\t\tdescription: '',\n\t\t\terrorMessage: '',\n\t\t},\n\t]\n}\n"],"names":["parseEndpoint","node","sourceFilePath","parsedEndpointMethod","SyntaxKind","endpointMethod","endpointPath","resolveEndpointPath","endpointData","sectionTimings","time","section","fn","t1","result","hookNodes","getHookNodes","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","endpointNode","name","hookNode","paramNode","valueNode","findNodeImplementation","objectLiteral","getValuesOfObjectLiteral","declaredParams","segment","getShapeOfValidatorLiteral","declared","getValidatorPropertyShape","getValidatorPropertyOptionality","getValidatorPropertyStringValue","nodeName","returnType","actualType","responseType","getProperTypeShape","parseResponseTypes","status","property","response","contentType","unionEntry"],"mappings":"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"}
|