moonflower 1.4.8 → 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 +123 -105
- package/dist/openapi/analyzerModule/analyzerModule.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 +121 -106
- package/dist/openapi/analyzerModule/parseEndpoint.mjs.map +1 -1
- package/package.json +1 -1
- package/src/openapi/analyzerModule/analyzerModule.ts +63 -20
- package/src/openapi/analyzerModule/parseEndpoint.ts +31 -9
- package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.ts +2 -2
- package/src/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.ts +1 -1
|
@@ -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\tconst hookNodes = getHookNodes(node)\n\n\t// API documentation\n\ttry {\n\t\tconst entries = 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 = parseRequestParams(hookNodes.usePathParams, 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(hookNodes.useQueryParams, '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(hookNodes.useHeaderParams, '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(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 = parseRequestObjectInput(hookNodes.useRequestBody, '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\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","hookNodes","getHookNodes","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","endpointNode","result","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
|
+
{"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
|
|
1
|
+
import { SyntaxKind as o } from "ts-morph";
|
|
2
2
|
import { Logger as l } from "../../utils/logger.mjs";
|
|
3
|
-
import { resolveEndpointPath as
|
|
4
|
-
const
|
|
5
|
-
const r =
|
|
6
|
-
method:
|
|
7
|
-
path:
|
|
8
|
-
sourceFilePath:
|
|
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,48 +16,63 @@ const j = (t, n) => {
|
|
|
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
|
-
l.error("Error",
|
|
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
|
-
l.error("Error",
|
|
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
|
-
l.error("Error",
|
|
69
|
+
s.responses = d("response", () => b(e));
|
|
70
|
+
} catch (n) {
|
|
71
|
+
l.error("Error", n);
|
|
57
72
|
}
|
|
58
|
-
return
|
|
59
|
-
},
|
|
60
|
-
const
|
|
73
|
+
return { endpoint: s, sectionTimings: u };
|
|
74
|
+
}, v = (e) => {
|
|
75
|
+
const i = {
|
|
61
76
|
useApiEndpoint: null,
|
|
62
77
|
usePathParams: null,
|
|
63
78
|
useQueryParams: null,
|
|
@@ -65,117 +80,117 @@ const j = (t, n) => {
|
|
|
65
80
|
useRequestBody: null,
|
|
66
81
|
useRequestRawBody: null
|
|
67
82
|
};
|
|
68
|
-
for (const r of
|
|
69
|
-
const
|
|
70
|
-
|
|
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);
|
|
71
86
|
}
|
|
72
|
-
return
|
|
73
|
-
},
|
|
74
|
-
if (!
|
|
87
|
+
return i;
|
|
88
|
+
}, K = (e) => {
|
|
89
|
+
if (!e)
|
|
75
90
|
return [];
|
|
76
|
-
const
|
|
77
|
-
if (!r.isKind(
|
|
91
|
+
const i = e.getFirstChildByKind(o.SyntaxList), r = g(i.getLastChild());
|
|
92
|
+
if (!r.isKind(o.ObjectLiteralExpression))
|
|
78
93
|
throw new Error("Non-literal type used in useApiEndpoint");
|
|
79
|
-
const
|
|
80
|
-
return
|
|
81
|
-
},
|
|
82
|
-
if (!
|
|
94
|
+
const t = r.asKind(o.ObjectLiteralExpression);
|
|
95
|
+
return B(t).filter((s) => s.value !== null);
|
|
96
|
+
}, q = (e, i) => {
|
|
97
|
+
if (!e)
|
|
83
98
|
return [];
|
|
84
|
-
const r =
|
|
85
|
-
if (!
|
|
99
|
+
const r = e.getFirstChildByKind(o.SyntaxList), t = g(r.getLastChild());
|
|
100
|
+
if (!t.isKind(o.ObjectLiteralExpression))
|
|
86
101
|
throw new Error("Non-literal type used in usePathParams");
|
|
87
|
-
const
|
|
88
|
-
name:
|
|
89
|
-
optional:
|
|
90
|
-
})),
|
|
91
|
-
return
|
|
92
|
-
identifier:
|
|
93
|
-
signature:
|
|
94
|
-
optional:
|
|
95
|
-
description:
|
|
96
|
-
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
|
|
97
112
|
}));
|
|
98
|
-
},
|
|
99
|
-
if (!
|
|
113
|
+
}, C = (e) => {
|
|
114
|
+
if (!e)
|
|
100
115
|
return null;
|
|
101
|
-
const
|
|
102
|
-
|
|
116
|
+
const i = e.getFirstChildByKind(o.SyntaxList), r = g(
|
|
117
|
+
i.getLastChild((t) => !t.isKind(o.CommaToken))
|
|
103
118
|
);
|
|
104
119
|
return {
|
|
105
|
-
signature:
|
|
106
|
-
optional:
|
|
107
|
-
description:
|
|
108
|
-
errorMessage:
|
|
120
|
+
signature: x(r),
|
|
121
|
+
optional: R(r),
|
|
122
|
+
description: y(r, "description"),
|
|
123
|
+
errorMessage: y(r, "errorMessage")
|
|
109
124
|
};
|
|
110
|
-
},
|
|
111
|
-
if (!
|
|
125
|
+
}, h = (e, i) => {
|
|
126
|
+
if (!e)
|
|
112
127
|
return [];
|
|
113
|
-
const r =
|
|
114
|
-
if (!
|
|
115
|
-
throw new Error(`Non-literal type used in ${
|
|
116
|
-
const
|
|
117
|
-
return
|
|
118
|
-
identifier:
|
|
119
|
-
signature:
|
|
120
|
-
optional:
|
|
121
|
-
description:
|
|
122
|
-
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
|
|
123
138
|
}));
|
|
124
|
-
},
|
|
125
|
-
const r =
|
|
126
|
-
return
|
|
127
|
-
},
|
|
128
|
-
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")
|
|
129
144
|
return [
|
|
130
145
|
{
|
|
131
|
-
status:
|
|
146
|
+
status: e === "void" || e === "null" ? 204 : 200,
|
|
132
147
|
contentType: "text/plain",
|
|
133
|
-
signature:
|
|
148
|
+
signature: e,
|
|
134
149
|
description: "",
|
|
135
150
|
errorMessage: ""
|
|
136
151
|
}
|
|
137
152
|
];
|
|
138
|
-
if (
|
|
139
|
-
return
|
|
140
|
-
if (
|
|
141
|
-
const
|
|
142
|
-
const
|
|
143
|
-
(
|
|
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"
|
|
144
159
|
)?.shape;
|
|
145
|
-
if (!
|
|
160
|
+
if (!t || typeof t == "string" || typeof t[0].shape != "string")
|
|
146
161
|
throw new Error("Invalid useReturnValue hook");
|
|
147
|
-
return parseInt(
|
|
162
|
+
return parseInt(t[0].shape);
|
|
148
163
|
})(), r = (() => {
|
|
149
|
-
const
|
|
150
|
-
(
|
|
164
|
+
const t = e.find(
|
|
165
|
+
(a) => a.role === "property" && a.identifier === "contentType"
|
|
151
166
|
)?.shape;
|
|
152
|
-
if (!
|
|
167
|
+
if (!t || typeof t == "string" || typeof t[0].shape != "string")
|
|
153
168
|
throw new Error("Invalid useReturnValue hook");
|
|
154
|
-
return
|
|
169
|
+
return t[0].shape;
|
|
155
170
|
})();
|
|
156
171
|
return [
|
|
157
172
|
{
|
|
158
|
-
status:
|
|
173
|
+
status: i,
|
|
159
174
|
contentType: r,
|
|
160
|
-
signature:
|
|
175
|
+
signature: e,
|
|
161
176
|
description: "",
|
|
162
177
|
errorMessage: ""
|
|
163
178
|
}
|
|
164
179
|
];
|
|
165
180
|
}
|
|
166
|
-
return
|
|
181
|
+
return e[0].role === "union" ? typeof e[0].shape == "string" ? [
|
|
167
182
|
{
|
|
168
|
-
status:
|
|
183
|
+
status: e[0].shape === "void" || e[0].shape === "null" ? 204 : 200,
|
|
169
184
|
contentType: "application/json",
|
|
170
|
-
signature:
|
|
185
|
+
signature: e[0].shape,
|
|
171
186
|
description: "",
|
|
172
187
|
errorMessage: ""
|
|
173
188
|
}
|
|
174
|
-
] :
|
|
189
|
+
] : e[0].shape.flatMap((i) => f([i])) : e[0].role === "buffer" ? [
|
|
175
190
|
{
|
|
176
191
|
status: 200,
|
|
177
192
|
contentType: "application/octet-stream",
|
|
178
|
-
signature:
|
|
193
|
+
signature: e,
|
|
179
194
|
description: "",
|
|
180
195
|
errorMessage: ""
|
|
181
196
|
}
|
|
@@ -183,13 +198,13 @@ const j = (t, n) => {
|
|
|
183
198
|
{
|
|
184
199
|
status: 200,
|
|
185
200
|
contentType: "application/json",
|
|
186
|
-
signature:
|
|
201
|
+
signature: e,
|
|
187
202
|
description: "",
|
|
188
203
|
errorMessage: ""
|
|
189
204
|
}
|
|
190
205
|
];
|
|
191
206
|
};
|
|
192
207
|
export {
|
|
193
|
-
|
|
208
|
+
O as parseEndpoint
|
|
194
209
|
};
|
|
195
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\tconst hookNodes = getHookNodes(node)\n\n\t// API documentation\n\ttry {\n\t\tconst entries = 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 = parseRequestParams(hookNodes.usePathParams, 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(hookNodes.useQueryParams, '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(hookNodes.useHeaderParams, '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(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 = parseRequestObjectInput(hookNodes.useRequestBody, '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\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","hookNodes","getHookNodes","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","endpointNode","result","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
|
+
{"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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"}
|