moonflower 1.0.2 → 1.1.1
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/.github/workflows/publish.yml +70 -0
- package/.releaserc.json +16 -0
- package/dist/openapi/analyzerModule/parseEndpoint.cjs +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.cjs.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.mjs +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.mjs.map +1 -1
- package/package.json +11 -3
- package/src/openapi/analyzerModule/parseEndpoint.ts +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Publish Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
name: Lint & Test
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout code
|
|
18
|
+
uses: actions/checkout@v5
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v6
|
|
22
|
+
with:
|
|
23
|
+
node-version: 24.x
|
|
24
|
+
cache: 'yarn'
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: yarn install
|
|
28
|
+
|
|
29
|
+
- name: Check types
|
|
30
|
+
run: yarn tsc
|
|
31
|
+
|
|
32
|
+
- name: Run linter
|
|
33
|
+
run: yarn lint
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: yarn test
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
name: Publish to NPM
|
|
40
|
+
needs: test
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
43
|
+
permissions:
|
|
44
|
+
contents: write
|
|
45
|
+
id-token: write
|
|
46
|
+
issues: write
|
|
47
|
+
pull-requests: write
|
|
48
|
+
|
|
49
|
+
steps:
|
|
50
|
+
- name: Checkout code
|
|
51
|
+
uses: actions/checkout@v5
|
|
52
|
+
with:
|
|
53
|
+
fetch-depth: 0
|
|
54
|
+
|
|
55
|
+
- name: Setup Node.js
|
|
56
|
+
uses: actions/setup-node@v6
|
|
57
|
+
with:
|
|
58
|
+
node-version: 24.x
|
|
59
|
+
registry-url: 'https://registry.npmjs.org'
|
|
60
|
+
cache: 'yarn'
|
|
61
|
+
|
|
62
|
+
- name: Install dependencies
|
|
63
|
+
run: yarn install
|
|
64
|
+
|
|
65
|
+
- name: Semantic Release
|
|
66
|
+
uses: cycjimmy/semantic-release-action@v5
|
|
67
|
+
with:
|
|
68
|
+
semantic_version: 25
|
|
69
|
+
env:
|
|
70
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/.releaserc.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"branches": ["main"],
|
|
3
|
+
"plugins": [
|
|
4
|
+
"@semantic-release/commit-analyzer",
|
|
5
|
+
"@semantic-release/release-notes-generator",
|
|
6
|
+
[
|
|
7
|
+
"@semantic-release/npm",
|
|
8
|
+
{
|
|
9
|
+
"npmPublish": true,
|
|
10
|
+
"provenance": true
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"@semantic-release/git",
|
|
14
|
+
"@semantic-release/github"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("ts-morph"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("ts-morph"),c=require("../../utils/logger.cjs"),d=require("./nodeParsers.cjs"),h=(t,o)=>{const s=t.getFirstDescendantByKind(a.SyntaxKind.PropertyAccessExpression).getText().split(".")[1].toUpperCase(),r=s==="DEL"?"DELETE":s,i=t.getFirstDescendantByKind(a.SyntaxKind.StringLiteral).getText()??"",l=i.substring(1,i.length-1),n={method:r,path:l,sourceFilePath:o,requestPathParams:[],requestQuery:[],requestHeaders:[],rawBody:void 0,objectBody:[],responses:[],name:void 0,summary:void 0,description:void 0,tags:void 0};try{f(t).forEach(u=>{n[u.identifier]=u.value})}catch(e){c.Logger.error("Error",e)}try{n.requestPathParams=x(t,l)}catch(e){c.Logger.error("Error",e)}try{n.requestQuery=g(t,"useQueryParams")}catch(e){c.Logger.error("Error",e)}try{n.requestHeaders=g(t,"useHeaderParams")}catch(e){c.Logger.error("Error",e)}try{const e=K(t);e&&(n.rawBody=e)}catch(e){c.Logger.error("Error",e)}try{n.objectBody=g(t,"useRequestBody")}catch(e){c.Logger.error("Error",e)}try{n.responses=E(t)}catch(e){c.Logger.error("Error",e)}return n},p=(t,o)=>t.getDescendantsOfKind(a.SyntaxKind.CallExpression).filter(i=>i.getFirstChildByKind(a.SyntaxKind.Identifier)?.getText()===o)[0]??null,f=t=>{const o=p(t,"useApiEndpoint");if(!o)return[];const s=o.getFirstChildByKind(a.SyntaxKind.SyntaxList),r=d.findNodeImplementation(s.getLastChild());if(!r.isKind(a.SyntaxKind.ObjectLiteralExpression))throw new Error("Non-literal type used in useApiEndpoint");const i=r.asKind(a.SyntaxKind.ObjectLiteralExpression);return d.getValuesOfObjectLiteral(i).filter(n=>n.value!==null)},x=(t,o)=>{const s=p(t,"usePathParams");if(!s)return[];const r=s.getFirstChildByKind(a.SyntaxKind.SyntaxList),i=d.findNodeImplementation(r.getLastChild());if(!i.isKind(a.SyntaxKind.ObjectLiteralExpression))throw new Error("Non-literal type used in usePathParams");const l=o.split("/").filter(e=>e.startsWith(":")).map(e=>({name:e.substring(1).replace(/\?/,""),optional:e.includes("?")})),n=i.asKind(a.SyntaxKind.ObjectLiteralExpression);return d.getShapeOfValidatorLiteral(n).filter(e=>e.shape!==null).map(e=>({identifier:e.identifier,signature:e.shape,optional:l.some(u=>u.name===e.identifier&&u.optional),description:e.description,errorMessage:e.errorMessage}))},K=t=>{const o=p(t,"useRequestRawBody");if(!o)return null;const s=o.getFirstChildByKind(a.SyntaxKind.SyntaxList),r=d.findNodeImplementation(s.getLastChild(i=>!i.isKind(a.SyntaxKind.CommaToken)));return{signature:d.getValidatorPropertyShape(r),optional:d.getValidatorPropertyOptionality(r),description:d.getValidatorPropertyStringValue(r,"description"),errorMessage:d.getValidatorPropertyStringValue(r,"errorMessage")}},g=(t,o)=>{const s=p(t,o);if(!s)return[];const r=s.getFirstChildByKind(a.SyntaxKind.SyntaxList),i=d.findNodeImplementation(r.getLastChild());if(!i.isKind(a.SyntaxKind.ObjectLiteralExpression))throw new Error(`Non-literal type used in ${o}`);const l=i.asKind(a.SyntaxKind.ObjectLiteralExpression);return d.getShapeOfValidatorLiteral(l).filter(n=>n.shape!==null).map(n=>({identifier:n.identifier,signature:n.shape,optional:n.optional,description:n.description,errorMessage:n.errorMessage}))},E=t=>{const s=t.getFirstChildByKind(a.SyntaxKind.CallExpression).getFirstChildByKind(a.SyntaxKind.SyntaxList).getFirstChildByKind(a.SyntaxKind.ArrowFunction).getReturnType(),r=s.getText().startsWith("Promise")?s.getTypeArguments()[0]:s,i=d.getProperTypeShape(r,t);return y(i)},y=t=>{if(typeof t=="string")return[{status:t==="void"||t==="null"?204:200,contentType:"text/plain",signature:t,description:"",errorMessage:""}];if(t[0].role==="union_entry"||t[0].role==="literal_string")return y(t[0].shape);if(t[0].role==="property"&&t[0].identifier==="_isUseReturnValue"){const o=(()=>{const r=t.find(i=>i.role==="property"&&i.identifier==="status")?.shape;if(!r||typeof r=="string"||typeof r[0].shape!="string")throw new Error("Invalid useReturnValue hook");return parseInt(r[0].shape)})(),s=(()=>{const r=t.find(i=>i.role==="property"&&i.identifier==="contentType")?.shape;if(!r||typeof r=="string"||typeof r[0].shape!="string")throw new Error("Invalid useReturnValue hook");return r[0].shape})();return[{status:o,contentType:s,signature:t,description:"",errorMessage:""}]}return t[0].role==="union"?typeof t[0].shape=="string"?[{status:t[0].shape==="void"||t[0].shape==="null"?204:200,contentType:"application/json",signature:t[0].shape,description:"",errorMessage:""}]:t[0].shape.flatMap(o=>y([o])):t[0].role==="buffer"?[{status:200,contentType:"application/octet-stream",signature:t,description:"",errorMessage:""}]:[{status:200,contentType:"application/json",signature:t,description:"",errorMessage:""}]};exports.parseEndpoint=h;
|
|
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 { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n} from './nodeParsers'\nimport { Logger } from '../../utils/logger'\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 endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)!.getText() ?? ''\n\tconst endpointPath = endpointText.substring(1, endpointText.length - 1)\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","endpointText","endpointPath","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} 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 endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)!.getText() ?? ''\n\tconst endpointPath = endpointText.substring(1, endpointText.length - 1)\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","endpointText","endpointPath","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 +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;
|
|
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;AAWvC,eAAO,MAAM,aAAa,SAAU,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,MAAM,iBAqHxE,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SyntaxKind as a } from "ts-morph";
|
|
2
|
-
import { findNodeImplementation as u, getValuesOfObjectLiteral as E, getShapeOfValidatorLiteral as y, getValidatorPropertyStringValue as f, getValidatorPropertyOptionality as m, getValidatorPropertyShape as x, getProperTypeShape as L } from "./nodeParsers.mjs";
|
|
3
2
|
import { Logger as c } from "../../utils/logger.mjs";
|
|
3
|
+
import { findNodeImplementation as u, getValuesOfObjectLiteral as E, getShapeOfValidatorLiteral as y, getValidatorPropertyStringValue as f, getValidatorPropertyOptionality as m, getValidatorPropertyShape as x, getProperTypeShape as L } from "./nodeParsers.mjs";
|
|
4
4
|
const j = (t, n) => {
|
|
5
5
|
const o = t.getFirstDescendantByKind(a.PropertyAccessExpression).getText().split(".")[1].toUpperCase(), r = o === "DEL" ? "DELETE" : o, i = t.getFirstDescendantByKind(a.StringLiteral).getText() ?? "", l = i.substring(1, i.length - 1), s = {
|
|
6
6
|
method: r,
|
|
@@ -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 { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n} from './nodeParsers'\nimport { Logger } from '../../utils/logger'\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 endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)!.getText() ?? ''\n\tconst endpointPath = endpointText.substring(1, endpointText.length - 1)\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","endpointText","endpointPath","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":";;;AAea,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,IAAeL,EAAK,yBAAyBG,EAAW,aAAa,EAAG,aAAa,IACrFG,IAAeD,EAAa,UAAU,GAAGA,EAAa,SAAS,CAAC,GAEhEE,IAA6B;AAAA,IAClC,QAAQH;AAAA,IACR,MAAME;AAAA,IACN,gBAAAL;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,GAAMM,CAAY;AAAA,WAC9DI,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,GAAqBM,MAA4D;AACtG,QAAAc,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,IAAiBpB,EACrB,MAAM,GAAG,EACT,OAAO,CAACqB,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} 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 endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)!.getText() ?? ''\n\tconst endpointPath = endpointText.substring(1, endpointText.length - 1)\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","endpointText","endpointPath","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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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moonflower",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "tenebrie",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/tenebrie/moonflower",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Tenebrie/moonflower"
|
|
11
|
+
},
|
|
8
12
|
"main": "./dist/index.cjs",
|
|
9
13
|
"module": "./dist/index.mjs",
|
|
10
14
|
"types": "./dist/index.d.ts",
|
|
@@ -105,13 +109,17 @@
|
|
|
105
109
|
"require": "./dist/validators/ParamWrappers.cjs"
|
|
106
110
|
}
|
|
107
111
|
},
|
|
108
|
-
"bin":
|
|
112
|
+
"bin": {
|
|
113
|
+
"moonflower": "cli/entry.cjs"
|
|
114
|
+
},
|
|
109
115
|
"scripts": {
|
|
110
116
|
"prepublish": "vite build",
|
|
111
117
|
"build": "vite build",
|
|
112
118
|
"lint": "eslint src/",
|
|
119
|
+
"tsc": "tsc --noEmit",
|
|
113
120
|
"lint-fix": "eslint src/ --fix",
|
|
114
|
-
"test": "vitest",
|
|
121
|
+
"test": "vitest run",
|
|
122
|
+
"test-watch": "vitest",
|
|
115
123
|
"test-coverage": "vitest --coverage"
|
|
116
124
|
},
|
|
117
125
|
"dependencies": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Node, SyntaxKind, ts } from 'ts-morph'
|
|
2
2
|
|
|
3
3
|
import { ApiEndpointDocs } from '../../hooks/useApiEndpoint'
|
|
4
|
+
import { Logger } from '../../utils/logger'
|
|
4
5
|
import { EndpointData } from '../types'
|
|
5
6
|
import {
|
|
6
7
|
findNodeImplementation,
|
|
@@ -11,7 +12,6 @@ import {
|
|
|
11
12
|
getValidatorPropertyStringValue,
|
|
12
13
|
getValuesOfObjectLiteral,
|
|
13
14
|
} from './nodeParsers'
|
|
14
|
-
import { Logger } from '../../utils/logger'
|
|
15
15
|
|
|
16
16
|
export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
17
17
|
const parsedEndpointMethod = node
|