moonflower 1.4.7 → 1.4.8
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.mjs +33 -32
- package/dist/openapi/analyzerModule/analyzerModule.mjs.map +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.cjs +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.cjs.map +1 -1
- package/dist/openapi/analyzerModule/nodeParsers.mjs +81 -81
- package/dist/openapi/analyzerModule/nodeParsers.mjs.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.cjs +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.cjs.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -1
- package/dist/openapi/analyzerModule/parseEndpoint.mjs +105 -95
- package/dist/openapi/analyzerModule/parseEndpoint.mjs.map +1 -1
- package/package.json +1 -1
- package/src/openapi/analyzerModule/analyzerModule.ts +1 -1
- package/src/openapi/analyzerModule/nodeParsers.ts +4 -4
- package/src/openapi/analyzerModule/parseEndpoint.ts +41 -29
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { SyntaxKind as
|
|
2
|
-
import { Logger as
|
|
3
|
-
import { resolveEndpointPath as
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
method:
|
|
7
|
-
path:
|
|
8
|
-
sourceFilePath:
|
|
1
|
+
import { SyntaxKind as a } from "ts-morph";
|
|
2
|
+
import { Logger as l } from "../../utils/logger.mjs";
|
|
3
|
+
import { resolveEndpointPath as y, findNodeImplementation as d, getValuesOfObjectLiteral as m, getShapeOfValidatorLiteral as f, getValidatorPropertyStringValue as h, getValidatorPropertyOptionality as E, getValidatorPropertyShape as P, getProperTypeShape as L } from "./nodeParsers.mjs";
|
|
4
|
+
const j = (t, n) => {
|
|
5
|
+
const r = t.getFirstDescendantByKind(a.PropertyAccessExpression).getText().split(".")[1].toUpperCase(), e = r === "DEL" ? "DELETE" : r, u = y(t) ?? "", i = {
|
|
6
|
+
method: e,
|
|
7
|
+
path: u,
|
|
8
|
+
sourceFilePath: n,
|
|
9
9
|
requestPathParams: [],
|
|
10
10
|
requestQuery: [],
|
|
11
11
|
requestHeaders: [],
|
|
@@ -16,105 +16,115 @@ const w = (t, s) => {
|
|
|
16
16
|
summary: void 0,
|
|
17
17
|
description: void 0,
|
|
18
18
|
tags: void 0
|
|
19
|
-
};
|
|
19
|
+
}, o = x(t);
|
|
20
20
|
try {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
B(o.useApiEndpoint).forEach((g) => {
|
|
22
|
+
i[g.identifier] = g.value;
|
|
23
23
|
});
|
|
24
|
-
} catch (
|
|
25
|
-
|
|
24
|
+
} catch (s) {
|
|
25
|
+
l.error("Error", s);
|
|
26
26
|
}
|
|
27
27
|
try {
|
|
28
|
-
|
|
29
|
-
} catch (
|
|
30
|
-
|
|
28
|
+
i.requestPathParams = v(o.usePathParams, u);
|
|
29
|
+
} catch (s) {
|
|
30
|
+
l.error("Error", s);
|
|
31
31
|
}
|
|
32
32
|
try {
|
|
33
|
-
|
|
34
|
-
} catch (
|
|
35
|
-
|
|
33
|
+
i.requestQuery = c(o.useQueryParams, "useQueryParams");
|
|
34
|
+
} catch (s) {
|
|
35
|
+
l.error("Error", s);
|
|
36
36
|
}
|
|
37
37
|
try {
|
|
38
|
-
|
|
39
|
-
} catch (
|
|
40
|
-
|
|
38
|
+
i.requestHeaders = c(o.useHeaderParams, "useHeaderParams");
|
|
39
|
+
} catch (s) {
|
|
40
|
+
l.error("Error", s);
|
|
41
41
|
}
|
|
42
42
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
} catch (
|
|
46
|
-
|
|
43
|
+
const s = K(o.useRequestRawBody);
|
|
44
|
+
s && (i.rawBody = s);
|
|
45
|
+
} catch (s) {
|
|
46
|
+
l.error("Error", s);
|
|
47
47
|
}
|
|
48
48
|
try {
|
|
49
|
-
|
|
50
|
-
} catch (
|
|
51
|
-
|
|
49
|
+
i.objectBody = c(o.useRequestBody, "useRequestBody");
|
|
50
|
+
} catch (s) {
|
|
51
|
+
l.error("Error", s);
|
|
52
52
|
}
|
|
53
53
|
try {
|
|
54
|
-
|
|
55
|
-
} catch (
|
|
56
|
-
|
|
54
|
+
i.responses = R(t);
|
|
55
|
+
} catch (s) {
|
|
56
|
+
l.error("Error", s);
|
|
57
|
+
}
|
|
58
|
+
return i;
|
|
59
|
+
}, x = (t) => {
|
|
60
|
+
const n = {
|
|
61
|
+
useApiEndpoint: null,
|
|
62
|
+
usePathParams: null,
|
|
63
|
+
useQueryParams: null,
|
|
64
|
+
useHeaderParams: null,
|
|
65
|
+
useRequestBody: null,
|
|
66
|
+
useRequestRawBody: null
|
|
67
|
+
};
|
|
68
|
+
for (const r of t.getDescendantsOfKind(a.CallExpression)) {
|
|
69
|
+
const e = r.getFirstChildByKind(a.Identifier)?.getText();
|
|
70
|
+
e && e in n && n[e] === null && (n[e] = r);
|
|
57
71
|
}
|
|
58
|
-
return
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
if (!s)
|
|
72
|
+
return n;
|
|
73
|
+
}, B = (t) => {
|
|
74
|
+
if (!t)
|
|
62
75
|
return [];
|
|
63
|
-
const
|
|
64
|
-
if (!r.isKind(
|
|
76
|
+
const n = t.getFirstChildByKind(a.SyntaxList), r = d(n.getLastChild());
|
|
77
|
+
if (!r.isKind(a.ObjectLiteralExpression))
|
|
65
78
|
throw new Error("Non-literal type used in useApiEndpoint");
|
|
66
|
-
const
|
|
67
|
-
return m(
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
if (!o)
|
|
79
|
+
const e = r.asKind(a.ObjectLiteralExpression);
|
|
80
|
+
return m(e).filter((i) => i.value !== null);
|
|
81
|
+
}, v = (t, n) => {
|
|
82
|
+
if (!t)
|
|
71
83
|
return [];
|
|
72
|
-
const r =
|
|
73
|
-
if (!
|
|
84
|
+
const r = t.getFirstChildByKind(a.SyntaxList), e = d(r.getLastChild());
|
|
85
|
+
if (!e.isKind(a.ObjectLiteralExpression))
|
|
74
86
|
throw new Error("Non-literal type used in usePathParams");
|
|
75
|
-
const
|
|
76
|
-
name:
|
|
77
|
-
optional:
|
|
78
|
-
})),
|
|
79
|
-
return
|
|
80
|
-
identifier:
|
|
81
|
-
signature:
|
|
82
|
-
optional:
|
|
83
|
-
description:
|
|
84
|
-
errorMessage:
|
|
87
|
+
const u = n.split("/").filter((o) => o.startsWith(":")).map((o) => ({
|
|
88
|
+
name: o.substring(1).replace(/\?/, ""),
|
|
89
|
+
optional: o.includes("?")
|
|
90
|
+
})), i = e.asKind(a.ObjectLiteralExpression);
|
|
91
|
+
return f(i).filter((o) => o.shape !== null).map((o) => ({
|
|
92
|
+
identifier: o.identifier,
|
|
93
|
+
signature: o.shape,
|
|
94
|
+
optional: u.some((s) => s.name === o.identifier && s.optional),
|
|
95
|
+
description: o.description,
|
|
96
|
+
errorMessage: o.errorMessage
|
|
85
97
|
}));
|
|
86
98
|
}, K = (t) => {
|
|
87
|
-
|
|
88
|
-
if (!s)
|
|
99
|
+
if (!t)
|
|
89
100
|
return null;
|
|
90
|
-
const
|
|
91
|
-
|
|
101
|
+
const n = t.getFirstChildByKind(a.SyntaxList), r = d(
|
|
102
|
+
n.getLastChild((e) => !e.isKind(a.CommaToken))
|
|
92
103
|
);
|
|
93
104
|
return {
|
|
94
|
-
signature:
|
|
95
|
-
optional:
|
|
96
|
-
description:
|
|
97
|
-
errorMessage:
|
|
105
|
+
signature: P(r),
|
|
106
|
+
optional: E(r),
|
|
107
|
+
description: h(r, "description"),
|
|
108
|
+
errorMessage: h(r, "errorMessage")
|
|
98
109
|
};
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
if (!o)
|
|
110
|
+
}, c = (t, n) => {
|
|
111
|
+
if (!t)
|
|
102
112
|
return [];
|
|
103
|
-
const r =
|
|
104
|
-
if (!
|
|
105
|
-
throw new Error(`Non-literal type used in ${
|
|
106
|
-
const
|
|
107
|
-
return
|
|
108
|
-
identifier:
|
|
109
|
-
signature:
|
|
110
|
-
optional:
|
|
111
|
-
description:
|
|
112
|
-
errorMessage:
|
|
113
|
+
const r = t.getFirstChildByKind(a.SyntaxList), e = d(r.getLastChild());
|
|
114
|
+
if (!e.isKind(a.ObjectLiteralExpression))
|
|
115
|
+
throw new Error(`Non-literal type used in ${n}`);
|
|
116
|
+
const u = e.asKind(a.ObjectLiteralExpression);
|
|
117
|
+
return f(u).filter((i) => i.shape !== null).map((i) => ({
|
|
118
|
+
identifier: i.identifier,
|
|
119
|
+
signature: i.shape,
|
|
120
|
+
optional: i.optional,
|
|
121
|
+
description: i.description,
|
|
122
|
+
errorMessage: i.errorMessage
|
|
113
123
|
}));
|
|
114
|
-
},
|
|
115
|
-
const
|
|
116
|
-
return
|
|
117
|
-
},
|
|
124
|
+
}, R = (t) => {
|
|
125
|
+
const r = t.getFirstChildByKind(a.CallExpression).getFirstChildByKind(a.SyntaxList).getFirstChildByKind(a.ArrowFunction).getReturnType(), e = r.getText().startsWith("Promise") ? r.getTypeArguments()[0] : r, u = L(e, t);
|
|
126
|
+
return p(u);
|
|
127
|
+
}, p = (t) => {
|
|
118
128
|
if (typeof t == "string")
|
|
119
129
|
return [
|
|
120
130
|
{
|
|
@@ -126,27 +136,27 @@ const w = (t, s) => {
|
|
|
126
136
|
}
|
|
127
137
|
];
|
|
128
138
|
if (t[0].role === "union_entry" || t[0].role === "literal_string")
|
|
129
|
-
return
|
|
139
|
+
return p(t[0].shape);
|
|
130
140
|
if (t[0].role === "property" && t[0].identifier === "_isUseReturnValue") {
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
(
|
|
141
|
+
const n = (() => {
|
|
142
|
+
const e = t.find(
|
|
143
|
+
(u) => u.role === "property" && u.identifier === "status"
|
|
134
144
|
)?.shape;
|
|
135
|
-
if (!
|
|
145
|
+
if (!e || typeof e == "string" || typeof e[0].shape != "string")
|
|
136
146
|
throw new Error("Invalid useReturnValue hook");
|
|
137
|
-
return parseInt(
|
|
138
|
-
})(),
|
|
139
|
-
const
|
|
140
|
-
(
|
|
147
|
+
return parseInt(e[0].shape);
|
|
148
|
+
})(), r = (() => {
|
|
149
|
+
const e = t.find(
|
|
150
|
+
(u) => u.role === "property" && u.identifier === "contentType"
|
|
141
151
|
)?.shape;
|
|
142
|
-
if (!
|
|
152
|
+
if (!e || typeof e == "string" || typeof e[0].shape != "string")
|
|
143
153
|
throw new Error("Invalid useReturnValue hook");
|
|
144
|
-
return
|
|
154
|
+
return e[0].shape;
|
|
145
155
|
})();
|
|
146
156
|
return [
|
|
147
157
|
{
|
|
148
|
-
status:
|
|
149
|
-
contentType:
|
|
158
|
+
status: n,
|
|
159
|
+
contentType: r,
|
|
150
160
|
signature: t,
|
|
151
161
|
description: "",
|
|
152
162
|
errorMessage: ""
|
|
@@ -161,7 +171,7 @@ const w = (t, s) => {
|
|
|
161
171
|
description: "",
|
|
162
172
|
errorMessage: ""
|
|
163
173
|
}
|
|
164
|
-
] : t[0].shape.flatMap((
|
|
174
|
+
] : t[0].shape.flatMap((n) => p([n])) : t[0].role === "buffer" ? [
|
|
165
175
|
{
|
|
166
176
|
status: 200,
|
|
167
177
|
contentType: "application/octet-stream",
|
|
@@ -180,6 +190,6 @@ const w = (t, s) => {
|
|
|
180
190
|
];
|
|
181
191
|
};
|
|
182
192
|
export {
|
|
183
|
-
|
|
193
|
+
j as parseEndpoint
|
|
184
194
|
};
|
|
185
195
|
//# sourceMappingURL=parseEndpoint.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseEndpoint.mjs","sources":["../../../src/openapi/analyzerModule/parseEndpoint.ts"],"sourcesContent":["import { Node, SyntaxKind, ts } from 'ts-morph'\n\nimport { ApiEndpointDocs } from '../../hooks/useApiEndpoint'\nimport { Logger } from '../../utils/logger'\nimport { EndpointData } from '../types'\nimport {\n\tfindNodeImplementation,\n\tgetProperTypeShape,\n\tgetShapeOfValidatorLiteral,\n\tgetValidatorPropertyOptionality,\n\tgetValidatorPropertyShape,\n\tgetValidatorPropertyStringValue,\n\tgetValuesOfObjectLiteral,\n\tresolveEndpointPath,\n} from './nodeParsers'\n\nexport const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {\n\tconst parsedEndpointMethod = node\n\t\t.getFirstDescendantByKind(SyntaxKind.PropertyAccessExpression)!\n\t\t.getText()\n\t\t.split('.')[1]\n\t\t.toUpperCase()\n\n\tconst endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod\n\n\tconst endpointPath = resolveEndpointPath(node) ?? ''\n\n\tconst endpointData: EndpointData = {\n\t\tmethod: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n\t\tpath: endpointPath,\n\t\tsourceFilePath,\n\t\trequestPathParams: [],\n\t\trequestQuery: [],\n\t\trequestHeaders: [],\n\t\trawBody: undefined,\n\t\tobjectBody: [],\n\t\tresponses: [],\n\t\tname: undefined,\n\t\tsummary: undefined,\n\t\tdescription: undefined,\n\t\ttags: undefined,\n\t}\n\n\tconst warningData: {\n\t\tsegment: string\n\t\terror: Error\n\t}[] = []\n\n\t// API documentation\n\ttry {\n\t\tconst entries = parseApiDocumentation(node)\n\t\tentries.forEach((param) => {\n\t\t\tendpointData[param.identifier] = param.value as string & string[]\n\t\t})\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'api',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request params\n\ttry {\n\t\tendpointData.requestPathParams = parseRequestParams(node, endpointPath)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'path',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request query\n\ttry {\n\t\tendpointData.requestQuery = parseRequestObjectInput(node, 'useQueryParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'query',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request headers\n\ttry {\n\t\tendpointData.requestHeaders = parseRequestObjectInput(node, 'useHeaderParams')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'headers',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Raw request body\n\ttry {\n\t\tconst parsedBody = parseRequestRawBody(node)\n\t\tif (parsedBody) {\n\t\t\tendpointData.rawBody = parsedBody\n\t\t}\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'rawBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Object request body\n\ttry {\n\t\tendpointData.objectBody = parseRequestObjectInput(node, 'useRequestBody')\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'objectBody',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\t// Request response\n\ttry {\n\t\tendpointData.responses = parseRequestResponse(node)\n\t} catch (err) {\n\t\twarningData.push({\n\t\t\tsegment: 'response',\n\t\t\terror: err as Error,\n\t\t})\n\t\tLogger.error('Error', err)\n\t}\n\n\treturn endpointData\n}\n\nconst getHookNode = (\n\tendpointNode: Node<ts.Node>,\n\thookName:\n\t\t| 'useApiEndpoint'\n\t\t| 'usePathParams'\n\t\t| 'useQueryParams'\n\t\t| 'useHeaderParams'\n\t\t| 'useRequestBody'\n\t\t| 'useRequestRawBody',\n) => {\n\tconst callExpressions = endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)\n\tconst matchingCallExpressions = callExpressions.filter((node) => {\n\t\treturn node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === hookName\n\t})\n\treturn matchingCallExpressions[0] ?? null\n}\n\nconst parseApiDocumentation = (node: Node<ts.Node>) => {\n\tconst hookNode = getHookNode(node, 'useApiEndpoint')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in useApiEndpoint')\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\n\tconst values = getValuesOfObjectLiteral(objectLiteral).filter((param) => param.value !== null)\n\treturn values as {\n\t\tidentifier: keyof ApiEndpointDocs\n\t\tvalue: (typeof values)[number]['value']\n\t}[]\n}\n\nconst parseRequestParams = (node: Node<ts.Node>, endpointPath: string): EndpointData['requestPathParams'] => {\n\tconst hookNode = getHookNode(node, 'usePathParams')\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error('Non-literal type used in usePathParams')\n\t}\n\n\tconst declaredParams = endpointPath\n\t\t.split('/')\n\t\t.filter((segment) => segment.startsWith(':'))\n\t\t.map((segment) => ({\n\t\t\tname: segment.substring(1).replace(/\\?/, ''),\n\t\t\toptional: segment.includes('?'),\n\t\t}))\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: declaredParams.some((declared) => declared.name === param.identifier && declared.optional),\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestRawBody = (node: Node<ts.Node>): NonNullable<EndpointData['rawBody']> | null => {\n\tconst hookNode = getHookNode(node, 'useRequestRawBody')\n\tif (!hookNode) {\n\t\treturn null\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(\n\t\tparamNode.getLastChild((node) => !node.isKind(SyntaxKind.CommaToken))!,\n\t)\n\n\treturn {\n\t\tsignature: getValidatorPropertyShape(valueNode),\n\t\toptional: getValidatorPropertyOptionality(valueNode),\n\t\tdescription: getValidatorPropertyStringValue(valueNode, 'description'),\n\t\terrorMessage: getValidatorPropertyStringValue(valueNode, 'errorMessage'),\n\t}\n}\n\nconst parseRequestObjectInput = (\n\tnode: Node<ts.Node>,\n\tnodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',\n): EndpointData['requestQuery'] | EndpointData['objectBody'] => {\n\tconst hookNode = getHookNode(node, nodeName)\n\tif (!hookNode) {\n\t\treturn []\n\t}\n\tconst paramNode = hookNode.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\tconst valueNode = findNodeImplementation(paramNode.getLastChild()!)\n\n\tif (!valueNode.isKind(SyntaxKind.ObjectLiteralExpression)) {\n\t\tthrow new Error(`Non-literal type used in ${nodeName}`)\n\t}\n\n\tconst objectLiteral = valueNode.asKind(SyntaxKind.ObjectLiteralExpression)!\n\treturn getShapeOfValidatorLiteral(objectLiteral)\n\t\t.filter((param) => param.shape !== null)\n\t\t.map((param) => ({\n\t\t\tidentifier: param.identifier,\n\t\t\tsignature: param.shape as string,\n\t\t\toptional: param.optional,\n\t\t\tdescription: param.description,\n\t\t\terrorMessage: param.errorMessage,\n\t\t}))\n}\n\nconst parseRequestResponse = (node: Node<ts.Node>): EndpointData['responses'] => {\n\tconst implementationNode = node\n\t\t.getFirstChildByKind(SyntaxKind.CallExpression)!\n\t\t.getFirstChildByKind(SyntaxKind.SyntaxList)!\n\t\t.getFirstChildByKind(SyntaxKind.ArrowFunction)!\n\tconst returnType = implementationNode.getReturnType()\n\n\tconst actualType = (() => {\n\t\tif (returnType.getText().startsWith('Promise')) {\n\t\t\treturn returnType.getTypeArguments()[0]\n\t\t}\n\t\treturn returnType\n\t})()\n\n\tconst responseType = getProperTypeShape(actualType, node)\n\n\treturn parseResponseTypes(responseType)\n}\n\nconst parseResponseTypes = (\n\tresponseType: ReturnType<typeof getProperTypeShape>,\n): EndpointData['responses'] => {\n\t// TODO: Add support for response descriptions and errors\n\tif (typeof responseType === 'string') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: responseType === 'void' || responseType === 'null' ? 204 : 200,\n\t\t\t\tcontentType: 'text/plain',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union_entry' || responseType[0].role === 'literal_string') {\n\t\treturn parseResponseTypes(responseType[0].shape)\n\t}\n\n\t// Response type is a useReturnValue hook\n\tif (responseType[0].role === 'property' && responseType[0].identifier === '_isUseReturnValue') {\n\t\tconst status = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'status',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn parseInt(property[0].shape)\n\t\t})()\n\t\tconst contentType = (() => {\n\t\t\tconst property = responseType.find(\n\t\t\t\t(response) => response.role === 'property' && response.identifier === 'contentType',\n\t\t\t)?.shape\n\t\t\tif (!property || typeof property === 'string' || typeof property[0].shape !== 'string') {\n\t\t\t\tthrow new Error('Invalid useReturnValue hook')\n\t\t\t}\n\t\t\treturn property[0].shape\n\t\t})()\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus,\n\t\t\t\tcontentType,\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\tif (responseType[0].role === 'union') {\n\t\tif (typeof responseType[0].shape === 'string') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tstatus: responseType[0].shape === 'void' || responseType[0].shape === 'null' ? 204 : 200,\n\t\t\t\t\tcontentType: 'application/json',\n\t\t\t\t\tsignature: responseType[0].shape,\n\t\t\t\t\tdescription: '',\n\t\t\t\t\terrorMessage: '',\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn responseType[0].shape.flatMap((unionEntry) => {\n\t\t\treturn parseResponseTypes([unionEntry])\n\t\t})\n\t}\n\n\tif (responseType[0].role === 'buffer') {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\tcontentType: 'application/octet-stream',\n\t\t\t\tsignature: responseType,\n\t\t\t\tdescription: '',\n\t\t\t\terrorMessage: '',\n\t\t\t},\n\t\t]\n\t}\n\n\treturn [\n\t\t{\n\t\t\tstatus: 200,\n\t\t\tcontentType: 'application/json',\n\t\t\tsignature: responseType,\n\t\t\tdescription: '',\n\t\t\terrorMessage: '',\n\t\t},\n\t]\n}\n"],"names":["parseEndpoint","node","sourceFilePath","parsedEndpointMethod","SyntaxKind","endpointMethod","endpointPath","resolveEndpointPath","endpointData","parseApiDocumentation","param","err","Logger","parseRequestParams","parseRequestObjectInput","parsedBody","parseRequestRawBody","parseRequestResponse","getHookNode","endpointNode","hookName","hookNode","paramNode","valueNode","findNodeImplementation","objectLiteral","getValuesOfObjectLiteral","declaredParams","segment","getShapeOfValidatorLiteral","declared","getValidatorPropertyShape","getValidatorPropertyOptionality","getValidatorPropertyStringValue","nodeName","returnType","actualType","responseType","getProperTypeShape","parseResponseTypes","status","property","response","contentType","unionEntry"],"mappings":"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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 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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"}
|
package/package.json
CHANGED
|
@@ -209,9 +209,9 @@ export const analyzeSourceFileEndpoints = (
|
|
|
209
209
|
const joinedOperations = operations.join('|')
|
|
210
210
|
|
|
211
211
|
file.routers.named.forEach((routerName) => {
|
|
212
|
+
const routerPattern = new RegExp(`${routerName}\\.(?:${joinedOperations})`)
|
|
212
213
|
file.sourceFile.forEachChild((node) => {
|
|
213
214
|
const nodeText = node.getText()
|
|
214
|
-
const routerPattern = new RegExp(`${routerName}\\.(?:${joinedOperations})`)
|
|
215
215
|
|
|
216
216
|
if (routerPattern.test(nodeText)) {
|
|
217
217
|
const endpointPath = resolveEndpointPath(node) ?? ''
|
|
@@ -829,11 +829,12 @@ const computeProperTypeShape = (type: Type, atLocation: Node, stack: Type[]): Sh
|
|
|
829
829
|
.getProperties()
|
|
830
830
|
.map((prop) => {
|
|
831
831
|
const valueDeclaration = prop.getValueDeclaration() || prop.getDeclarations()[0]!
|
|
832
|
+
const shape = getProperTypeShape(prop.getTypeAtLocation(atLocation), atLocation, nextStack)
|
|
832
833
|
if (!valueDeclaration) {
|
|
833
834
|
return {
|
|
834
835
|
role: 'property' as const,
|
|
835
836
|
identifier: prop.getName(),
|
|
836
|
-
shape
|
|
837
|
+
shape,
|
|
837
838
|
optional: false,
|
|
838
839
|
}
|
|
839
840
|
}
|
|
@@ -846,18 +847,17 @@ const computeProperTypeShape = (type: Type, atLocation: Node, stack: Type[]): Sh
|
|
|
846
847
|
return {
|
|
847
848
|
role: 'property' as const,
|
|
848
849
|
identifier: prop.getName(),
|
|
849
|
-
shape
|
|
850
|
+
shape,
|
|
850
851
|
optional: false,
|
|
851
852
|
}
|
|
852
853
|
}
|
|
853
854
|
|
|
854
855
|
const isOptional = prop.getTypeAtLocation(atLocation).isNullable()
|
|
855
856
|
|
|
856
|
-
const shape = getProperTypeShape(prop.getTypeAtLocation(atLocation), atLocation, nextStack)
|
|
857
857
|
return {
|
|
858
858
|
role: 'property' as const,
|
|
859
859
|
identifier: prop.getName(),
|
|
860
|
-
shape
|
|
860
|
+
shape,
|
|
861
861
|
optional: isOptional,
|
|
862
862
|
}
|
|
863
863
|
})
|
|
@@ -46,9 +46,11 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
46
46
|
error: Error
|
|
47
47
|
}[] = []
|
|
48
48
|
|
|
49
|
+
const hookNodes = getHookNodes(node)
|
|
50
|
+
|
|
49
51
|
// API documentation
|
|
50
52
|
try {
|
|
51
|
-
const entries = parseApiDocumentation(
|
|
53
|
+
const entries = parseApiDocumentation(hookNodes.useApiEndpoint)
|
|
52
54
|
entries.forEach((param) => {
|
|
53
55
|
endpointData[param.identifier] = param.value as string & string[]
|
|
54
56
|
})
|
|
@@ -62,7 +64,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
62
64
|
|
|
63
65
|
// Request params
|
|
64
66
|
try {
|
|
65
|
-
endpointData.requestPathParams = parseRequestParams(
|
|
67
|
+
endpointData.requestPathParams = parseRequestParams(hookNodes.usePathParams, endpointPath)
|
|
66
68
|
} catch (err) {
|
|
67
69
|
warningData.push({
|
|
68
70
|
segment: 'path',
|
|
@@ -73,7 +75,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
73
75
|
|
|
74
76
|
// Request query
|
|
75
77
|
try {
|
|
76
|
-
endpointData.requestQuery = parseRequestObjectInput(
|
|
78
|
+
endpointData.requestQuery = parseRequestObjectInput(hookNodes.useQueryParams, 'useQueryParams')
|
|
77
79
|
} catch (err) {
|
|
78
80
|
warningData.push({
|
|
79
81
|
segment: 'query',
|
|
@@ -84,7 +86,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
84
86
|
|
|
85
87
|
// Request headers
|
|
86
88
|
try {
|
|
87
|
-
endpointData.requestHeaders = parseRequestObjectInput(
|
|
89
|
+
endpointData.requestHeaders = parseRequestObjectInput(hookNodes.useHeaderParams, 'useHeaderParams')
|
|
88
90
|
} catch (err) {
|
|
89
91
|
warningData.push({
|
|
90
92
|
segment: 'headers',
|
|
@@ -95,7 +97,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
95
97
|
|
|
96
98
|
// Raw request body
|
|
97
99
|
try {
|
|
98
|
-
const parsedBody = parseRequestRawBody(
|
|
100
|
+
const parsedBody = parseRequestRawBody(hookNodes.useRequestRawBody)
|
|
99
101
|
if (parsedBody) {
|
|
100
102
|
endpointData.rawBody = parsedBody
|
|
101
103
|
}
|
|
@@ -109,7 +111,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
109
111
|
|
|
110
112
|
// Object request body
|
|
111
113
|
try {
|
|
112
|
-
endpointData.objectBody = parseRequestObjectInput(
|
|
114
|
+
endpointData.objectBody = parseRequestObjectInput(hookNodes.useRequestBody, 'useRequestBody')
|
|
113
115
|
} catch (err) {
|
|
114
116
|
warningData.push({
|
|
115
117
|
segment: 'objectBody',
|
|
@@ -132,25 +134,33 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
|
|
|
132
134
|
return endpointData
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
137
|
+
type HookName =
|
|
138
|
+
| 'useApiEndpoint'
|
|
139
|
+
| 'usePathParams'
|
|
140
|
+
| 'useQueryParams'
|
|
141
|
+
| 'useHeaderParams'
|
|
142
|
+
| 'useRequestBody'
|
|
143
|
+
| 'useRequestRawBody'
|
|
144
|
+
|
|
145
|
+
const getHookNodes = (endpointNode: Node<ts.Node>): Record<HookName, Node<ts.CallExpression> | null> => {
|
|
146
|
+
const result: Record<HookName, Node<ts.CallExpression> | null> = {
|
|
147
|
+
useApiEndpoint: null,
|
|
148
|
+
usePathParams: null,
|
|
149
|
+
useQueryParams: null,
|
|
150
|
+
useHeaderParams: null,
|
|
151
|
+
useRequestBody: null,
|
|
152
|
+
useRequestRawBody: null,
|
|
153
|
+
}
|
|
154
|
+
for (const node of endpointNode.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
155
|
+
const name = node.getFirstChildByKind(SyntaxKind.Identifier)?.getText() as HookName | undefined
|
|
156
|
+
if (name && name in result && result[name] === null) {
|
|
157
|
+
result[name] = node
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return result
|
|
150
161
|
}
|
|
151
162
|
|
|
152
|
-
const parseApiDocumentation = (
|
|
153
|
-
const hookNode = getHookNode(node, 'useApiEndpoint')
|
|
163
|
+
const parseApiDocumentation = (hookNode: Node<ts.CallExpression> | null) => {
|
|
154
164
|
if (!hookNode) {
|
|
155
165
|
return []
|
|
156
166
|
}
|
|
@@ -170,8 +180,10 @@ const parseApiDocumentation = (node: Node<ts.Node>) => {
|
|
|
170
180
|
}[]
|
|
171
181
|
}
|
|
172
182
|
|
|
173
|
-
const parseRequestParams = (
|
|
174
|
-
|
|
183
|
+
const parseRequestParams = (
|
|
184
|
+
hookNode: Node<ts.CallExpression> | null,
|
|
185
|
+
endpointPath: string,
|
|
186
|
+
): EndpointData['requestPathParams'] => {
|
|
175
187
|
if (!hookNode) {
|
|
176
188
|
return []
|
|
177
189
|
}
|
|
@@ -203,8 +215,9 @@ const parseRequestParams = (node: Node<ts.Node>, endpointPath: string): Endpoint
|
|
|
203
215
|
}))
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
const parseRequestRawBody = (
|
|
207
|
-
|
|
218
|
+
const parseRequestRawBody = (
|
|
219
|
+
hookNode: Node<ts.CallExpression> | null,
|
|
220
|
+
): NonNullable<EndpointData['rawBody']> | null => {
|
|
208
221
|
if (!hookNode) {
|
|
209
222
|
return null
|
|
210
223
|
}
|
|
@@ -222,10 +235,9 @@ const parseRequestRawBody = (node: Node<ts.Node>): NonNullable<EndpointData['raw
|
|
|
222
235
|
}
|
|
223
236
|
|
|
224
237
|
const parseRequestObjectInput = (
|
|
225
|
-
|
|
238
|
+
hookNode: Node<ts.CallExpression> | null,
|
|
226
239
|
nodeName: 'useQueryParams' | 'useHeaderParams' | 'useRequestBody',
|
|
227
240
|
): EndpointData['requestQuery'] | EndpointData['objectBody'] => {
|
|
228
|
-
const hookNode = getHookNode(node, nodeName)
|
|
229
241
|
if (!hookNode) {
|
|
230
242
|
return []
|
|
231
243
|
}
|