@autoview/cli 0.1.0

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.
Files changed (297) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +407 -0
  3. package/lib/AutoViewAgent.d.ts +109 -0
  4. package/lib/AutoViewAgent.js +123 -0
  5. package/lib/AutoViewAgent.js.map +1 -0
  6. package/lib/agent/emitMcpServer.d.ts +15 -0
  7. package/lib/agent/emitMcpServer.js +157 -0
  8. package/lib/agent/emitMcpServer.js.map +1 -0
  9. package/lib/agent/emitReport.d.ts +14 -0
  10. package/lib/agent/emitReport.js +85 -0
  11. package/lib/agent/emitReport.js.map +1 -0
  12. package/lib/agent/toolSurface.d.ts +130 -0
  13. package/lib/agent/toolSurface.js +342 -0
  14. package/lib/agent/toolSurface.js.map +1 -0
  15. package/lib/agent/verifyAgentTasks.d.ts +87 -0
  16. package/lib/agent/verifyAgentTasks.js +126 -0
  17. package/lib/agent/verifyAgentTasks.js.map +1 -0
  18. package/lib/cli/main.d.ts +2 -0
  19. package/lib/cli/main.js +295 -0
  20. package/lib/cli/main.js.map +1 -0
  21. package/lib/compiler/AutoViewInterfaceCompiler.d.ts +27 -0
  22. package/lib/compiler/AutoViewInterfaceCompiler.js +68 -0
  23. package/lib/compiler/AutoViewInterfaceCompiler.js.map +1 -0
  24. package/lib/constants/AutoViewFrontendTemplate.d.ts +1 -0
  25. package/lib/constants/AutoViewFrontendTemplate.js +46 -0
  26. package/lib/constants/AutoViewFrontendTemplate.js.map +1 -0
  27. package/lib/constants/AutoViewSystemPromptConstant.d.ts +5 -0
  28. package/lib/constants/AutoViewSystemPromptConstant.js +4 -0
  29. package/lib/constants/AutoViewSystemPromptConstant.js.map +1 -0
  30. package/lib/context/IAutoViewAgentContext.d.ts +60 -0
  31. package/lib/context/IAutoViewAgentContext.js +3 -0
  32. package/lib/context/IAutoViewAgentContext.js.map +1 -0
  33. package/lib/fromSwagger.d.ts +53 -0
  34. package/lib/fromSwagger.js +513 -0
  35. package/lib/fromSwagger.js.map +1 -0
  36. package/lib/generateDeterministic.d.ts +26 -0
  37. package/lib/generateDeterministic.js +75 -0
  38. package/lib/generateDeterministic.js.map +1 -0
  39. package/lib/index.d.ts +15 -0
  40. package/lib/index.js +41 -0
  41. package/lib/index.js.map +1 -0
  42. package/lib/orchestrate/orchestrateAutoView.d.ts +17 -0
  43. package/lib/orchestrate/orchestrateAutoView.js +491 -0
  44. package/lib/orchestrate/orchestrateAutoView.js.map +1 -0
  45. package/lib/orchestrate/orchestrateAutoViewProductPlan.d.ts +37 -0
  46. package/lib/orchestrate/orchestrateAutoViewProductPlan.js +109 -0
  47. package/lib/orchestrate/orchestrateAutoViewProductPlan.js.map +1 -0
  48. package/lib/orchestrate/orchestrateAutoViewRender.d.ts +133 -0
  49. package/lib/orchestrate/orchestrateAutoViewRender.js +943 -0
  50. package/lib/orchestrate/orchestrateAutoViewRender.js.map +1 -0
  51. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.d.ts +24 -0
  52. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js +92 -0
  53. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js.map +1 -0
  54. package/lib/orchestrate/orchestrateAutoViewReview.d.ts +48 -0
  55. package/lib/orchestrate/orchestrateAutoViewReview.js +328 -0
  56. package/lib/orchestrate/orchestrateAutoViewReview.js.map +1 -0
  57. package/lib/orchestrate/orchestrateAutoViewScaffold.d.ts +45 -0
  58. package/lib/orchestrate/orchestrateAutoViewScaffold.js +586 -0
  59. package/lib/orchestrate/orchestrateAutoViewScaffold.js.map +1 -0
  60. package/lib/orchestrate/orchestrateAutoViewSdkStudy.d.ts +26 -0
  61. package/lib/orchestrate/orchestrateAutoViewSdkStudy.js +85 -0
  62. package/lib/orchestrate/orchestrateAutoViewSdkStudy.js.map +1 -0
  63. package/lib/orchestrate/structures/IAutoViewProductPlan.d.ts +96 -0
  64. package/lib/orchestrate/structures/IAutoViewProductPlan.js +3 -0
  65. package/lib/orchestrate/structures/IAutoViewProductPlan.js.map +1 -0
  66. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.d.ts +38 -0
  67. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js +3 -0
  68. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js.map +1 -0
  69. package/lib/orchestrate/structures/IAutoViewRenderApplication.d.ts +38 -0
  70. package/lib/orchestrate/structures/IAutoViewRenderApplication.js +3 -0
  71. package/lib/orchestrate/structures/IAutoViewRenderApplication.js.map +1 -0
  72. package/lib/orchestrate/structures/IAutoViewReviewApplication.d.ts +40 -0
  73. package/lib/orchestrate/structures/IAutoViewReviewApplication.js +3 -0
  74. package/lib/orchestrate/structures/IAutoViewReviewApplication.js.map +1 -0
  75. package/lib/orchestrate/structures/IAutoViewSdkMap.d.ts +63 -0
  76. package/lib/orchestrate/structures/IAutoViewSdkMap.js +3 -0
  77. package/lib/orchestrate/structures/IAutoViewSdkMap.js.map +1 -0
  78. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.d.ts +37 -0
  79. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js +3 -0
  80. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js.map +1 -0
  81. package/lib/orchestrate/utils/HistoryMessage.d.ts +10 -0
  82. package/lib/orchestrate/utils/HistoryMessage.js +25 -0
  83. package/lib/orchestrate/utils/HistoryMessage.js.map +1 -0
  84. package/lib/orchestrate/utils/auditFrontendRuntime.d.ts +53 -0
  85. package/lib/orchestrate/utils/auditFrontendRuntime.js +362 -0
  86. package/lib/orchestrate/utils/auditFrontendRuntime.js.map +1 -0
  87. package/lib/orchestrate/utils/buildDeterministicPlan.d.ts +4 -0
  88. package/lib/orchestrate/utils/buildDeterministicPlan.js +233 -0
  89. package/lib/orchestrate/utils/buildDeterministicPlan.js.map +1 -0
  90. package/lib/orchestrate/utils/buildDeterministicSdkMap.d.ts +22 -0
  91. package/lib/orchestrate/utils/buildDeterministicSdkMap.js +154 -0
  92. package/lib/orchestrate/utils/buildDeterministicSdkMap.js.map +1 -0
  93. package/lib/orchestrate/utils/cacheNodeModules.d.ts +31 -0
  94. package/lib/orchestrate/utils/cacheNodeModules.js +134 -0
  95. package/lib/orchestrate/utils/cacheNodeModules.js.map +1 -0
  96. package/lib/orchestrate/utils/describeEndpointPropsShape.d.ts +37 -0
  97. package/lib/orchestrate/utils/describeEndpointPropsShape.js +192 -0
  98. package/lib/orchestrate/utils/describeEndpointPropsShape.js.map +1 -0
  99. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.d.ts +22 -0
  100. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js +29 -0
  101. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js.map +1 -0
  102. package/lib/orchestrate/utils/describeEndpointResponseShape.d.ts +19 -0
  103. package/lib/orchestrate/utils/describeEndpointResponseShape.js +30 -0
  104. package/lib/orchestrate/utils/describeEndpointResponseShape.js.map +1 -0
  105. package/lib/orchestrate/utils/executeCachedBatch.d.ts +22 -0
  106. package/lib/orchestrate/utils/executeCachedBatch.js +64 -0
  107. package/lib/orchestrate/utils/executeCachedBatch.js.map +1 -0
  108. package/lib/orchestrate/utils/loadShoppingFixture.d.ts +33 -0
  109. package/lib/orchestrate/utils/loadShoppingFixture.js +17 -0
  110. package/lib/orchestrate/utils/loadShoppingFixture.js.map +1 -0
  111. package/lib/orchestrate/utils/normalizeProductPlanPaths.d.ts +24 -0
  112. package/lib/orchestrate/utils/normalizeProductPlanPaths.js +77 -0
  113. package/lib/orchestrate/utils/normalizeProductPlanPaths.js.map +1 -0
  114. package/lib/orchestrate/utils/renderJsonSchema.d.ts +23 -0
  115. package/lib/orchestrate/utils/renderJsonSchema.js +122 -0
  116. package/lib/orchestrate/utils/renderJsonSchema.js.map +1 -0
  117. package/lib/orchestrate/utils/renderResourcePage.d.ts +36 -0
  118. package/lib/orchestrate/utils/renderResourcePage.js +1415 -0
  119. package/lib/orchestrate/utils/renderResourcePage.js.map +1 -0
  120. package/lib/orchestrate/utils/validateFrontendTypecheck.d.ts +109 -0
  121. package/lib/orchestrate/utils/validateFrontendTypecheck.js +274 -0
  122. package/lib/orchestrate/utils/validateFrontendTypecheck.js.map +1 -0
  123. package/lib/preview/renderPreview.d.ts +22 -0
  124. package/lib/preview/renderPreview.js +198 -0
  125. package/lib/preview/renderPreview.js.map +1 -0
  126. package/lib/typings/compiler.d.ts +39 -0
  127. package/lib/typings/compiler.js +3 -0
  128. package/lib/typings/compiler.js.map +1 -0
  129. package/lib/typings/events.d.ts +106 -0
  130. package/lib/typings/events.js +3 -0
  131. package/lib/typings/events.js.map +1 -0
  132. package/lib/typings/index.d.ts +10 -0
  133. package/lib/typings/index.js +27 -0
  134. package/lib/typings/index.js.map +1 -0
  135. package/lib/typings/misc.d.ts +78 -0
  136. package/lib/typings/misc.js +3 -0
  137. package/lib/typings/misc.js.map +1 -0
  138. package/lib/utils/ArrayUtil.d.ts +8 -0
  139. package/lib/utils/ArrayUtil.js +30 -0
  140. package/lib/utils/ArrayUtil.js.map +1 -0
  141. package/lib/utils/StringUtil.d.ts +11 -0
  142. package/lib/utils/StringUtil.js +28 -0
  143. package/lib/utils/StringUtil.js.map +1 -0
  144. package/lib/utils/classifyEndpoints.d.ts +62 -0
  145. package/lib/utils/classifyEndpoints.js +216 -0
  146. package/lib/utils/classifyEndpoints.js.map +1 -0
  147. package/lib/utils/endpointFilter.d.ts +26 -0
  148. package/lib/utils/endpointFilter.js +0 -0
  149. package/lib/utils/endpointFilter.js.map +1 -0
  150. package/lib/utils/extractFields.d.ts +85 -0
  151. package/lib/utils/extractFields.js +231 -0
  152. package/lib/utils/extractFields.js.map +1 -0
  153. package/lib/utils/index.d.ts +13 -0
  154. package/lib/utils/index.js +30 -0
  155. package/lib/utils/index.js.map +1 -0
  156. package/lib/utils/normalizeForNestia.d.ts +34 -0
  157. package/lib/utils/normalizeForNestia.js +133 -0
  158. package/lib/utils/normalizeForNestia.js.map +1 -0
  159. package/lib/utils/resourcePlan.d.ts +39 -0
  160. package/lib/utils/resourcePlan.js +95 -0
  161. package/lib/utils/resourcePlan.js.map +1 -0
  162. package/lib/utils/sliceDocument.d.ts +17 -0
  163. package/lib/utils/sliceDocument.js +114 -0
  164. package/lib/utils/sliceDocument.js.map +1 -0
  165. package/lib/utils/toEndpoints.d.ts +90 -0
  166. package/lib/utils/toEndpoints.js +227 -0
  167. package/lib/utils/toEndpoints.js.map +1 -0
  168. package/lib/verify/runWorkflows.d.ts +25 -0
  169. package/lib/verify/runWorkflows.js +366 -0
  170. package/lib/verify/runWorkflows.js.map +1 -0
  171. package/lib/verify/workflows.d.ts +53 -0
  172. package/lib/verify/workflows.js +107 -0
  173. package/lib/verify/workflows.js.map +1 -0
  174. package/package.json +82 -0
  175. package/prompts/AUTOVIEW_RENDER.md +398 -0
  176. package/prompts/AUTOVIEW_REVIEW.md +60 -0
  177. package/prompts/AUTOVIEW_SDK_STUDY.md +89 -0
  178. package/src/AutoViewAgent.ts +222 -0
  179. package/src/agent/emitMcpServer.integration.test.ts +168 -0
  180. package/src/agent/emitMcpServer.test.ts +51 -0
  181. package/src/agent/emitMcpServer.ts +178 -0
  182. package/src/agent/emitReport.ts +117 -0
  183. package/src/agent/toolSurface.test.ts +243 -0
  184. package/src/agent/toolSurface.ts +501 -0
  185. package/src/agent/verifyAgentTasks.test.ts +106 -0
  186. package/src/agent/verifyAgentTasks.ts +171 -0
  187. package/src/cli/main.ts +363 -0
  188. package/src/compiler/AutoViewInterfaceCompiler.ts +69 -0
  189. package/src/constants/AutoViewFrontendTemplate.ts +42 -0
  190. package/src/constants/AutoViewSystemPromptConstant.ts +6 -0
  191. package/src/context/IAutoViewAgentContext.ts +84 -0
  192. package/src/fromSwagger.test.ts +269 -0
  193. package/src/fromSwagger.ts +500 -0
  194. package/src/generateDeterministic.test.ts +39 -0
  195. package/src/generateDeterministic.ts +77 -0
  196. package/src/index.ts +30 -0
  197. package/src/orchestrate/orchestrateAutoView.ts +590 -0
  198. package/src/orchestrate/orchestrateAutoViewProductPlan.ts +121 -0
  199. package/src/orchestrate/orchestrateAutoViewRender.ts +1117 -0
  200. package/src/orchestrate/orchestrateAutoViewRenderDeterministic.ts +101 -0
  201. package/src/orchestrate/orchestrateAutoViewReview.ts +272 -0
  202. package/src/orchestrate/orchestrateAutoViewScaffold.ts +627 -0
  203. package/src/orchestrate/orchestrateAutoViewSdkStudy.ts +90 -0
  204. package/src/orchestrate/renderNavTs.test.ts +74 -0
  205. package/src/orchestrate/structures/IAutoViewProductPlan.ts +119 -0
  206. package/src/orchestrate/structures/IAutoViewProductPlanApplication.ts +41 -0
  207. package/src/orchestrate/structures/IAutoViewRenderApplication.ts +40 -0
  208. package/src/orchestrate/structures/IAutoViewReviewApplication.ts +42 -0
  209. package/src/orchestrate/structures/IAutoViewSdkMap.ts +72 -0
  210. package/src/orchestrate/structures/IAutoViewSdkStudyApplication.ts +40 -0
  211. package/src/orchestrate/utils/HistoryMessage.ts +41 -0
  212. package/src/orchestrate/utils/auditFrontendRuntime.test.ts +18 -0
  213. package/src/orchestrate/utils/auditFrontendRuntime.ts +454 -0
  214. package/src/orchestrate/utils/buildDeterministicPlan.test.ts +170 -0
  215. package/src/orchestrate/utils/buildDeterministicPlan.ts +289 -0
  216. package/src/orchestrate/utils/buildDeterministicSdkMap.test.ts +90 -0
  217. package/src/orchestrate/utils/buildDeterministicSdkMap.ts +169 -0
  218. package/src/orchestrate/utils/cacheNodeModules.ts +136 -0
  219. package/src/orchestrate/utils/describeEndpointPropsShape.test.ts +86 -0
  220. package/src/orchestrate/utils/describeEndpointPropsShape.ts +202 -0
  221. package/src/orchestrate/utils/describeEndpointRequestBodyShape.test.ts +87 -0
  222. package/src/orchestrate/utils/describeEndpointRequestBodyShape.ts +31 -0
  223. package/src/orchestrate/utils/describeEndpointResponseShape.test.ts +70 -0
  224. package/src/orchestrate/utils/describeEndpointResponseShape.ts +32 -0
  225. package/src/orchestrate/utils/executeCachedBatch.ts +59 -0
  226. package/src/orchestrate/utils/loadShoppingFixture.ts +52 -0
  227. package/src/orchestrate/utils/normalizeProductPlanPaths.ts +92 -0
  228. package/src/orchestrate/utils/renderJsonSchema.test.ts +162 -0
  229. package/src/orchestrate/utils/renderJsonSchema.ts +133 -0
  230. package/src/orchestrate/utils/renderResourcePage.test.ts +468 -0
  231. package/src/orchestrate/utils/renderResourcePage.ts +1624 -0
  232. package/src/orchestrate/utils/validateFrontendTypecheck.test.ts +32 -0
  233. package/src/orchestrate/utils/validateFrontendTypecheck.ts +335 -0
  234. package/src/preview/renderPreview.ts +273 -0
  235. package/src/typings/compiler.ts +47 -0
  236. package/src/typings/events.ts +155 -0
  237. package/src/typings/index.ts +10 -0
  238. package/src/typings/misc.ts +93 -0
  239. package/src/utils/ArrayUtil.ts +16 -0
  240. package/src/utils/StringUtil.ts +29 -0
  241. package/src/utils/classifyEndpoints.test.ts +86 -0
  242. package/src/utils/classifyEndpoints.ts +291 -0
  243. package/src/utils/endpointFilter.test.ts +50 -0
  244. package/src/utils/endpointFilter.ts +0 -0
  245. package/src/utils/extractFields.test.ts +82 -0
  246. package/src/utils/extractFields.ts +306 -0
  247. package/src/utils/index.ts +13 -0
  248. package/src/utils/normalizeForNestia.test.ts +93 -0
  249. package/src/utils/normalizeForNestia.ts +139 -0
  250. package/src/utils/resourcePlan.test.ts +104 -0
  251. package/src/utils/resourcePlan.ts +180 -0
  252. package/src/utils/sliceDocument.test.ts +85 -0
  253. package/src/utils/sliceDocument.ts +119 -0
  254. package/src/utils/toEndpoints.test.ts +251 -0
  255. package/src/utils/toEndpoints.ts +343 -0
  256. package/src/verify/runWorkflows.ts +403 -0
  257. package/src/verify/workflows.test.ts +117 -0
  258. package/src/verify/workflows.ts +154 -0
  259. package/template/CLAUDE.md +140 -0
  260. package/template/Dockerfile +31 -0
  261. package/template/PROMPT.md +80 -0
  262. package/template/SANDBOX.md +70 -0
  263. package/template/app/api/health/route.ts +10 -0
  264. package/template/app/globals.css +97 -0
  265. package/template/app/layout.tsx +30 -0
  266. package/template/app/page.tsx +19 -0
  267. package/template/components/AppShell.tsx +114 -0
  268. package/template/components/auto/CatalogGrid.tsx +159 -0
  269. package/template/components/auto/ConfirmButton.tsx +67 -0
  270. package/template/components/auto/EmbeddedCollection.tsx +144 -0
  271. package/template/components/auto/ResourceDashboard.tsx +104 -0
  272. package/template/components/auto/ResourceDetail.tsx +93 -0
  273. package/template/components/auto/ResourceForm.tsx +235 -0
  274. package/template/components/auto/ResourceIcon.tsx +88 -0
  275. package/template/components/auto/ResourceLanding.tsx +155 -0
  276. package/template/components/auto/ResourceTable.tsx +223 -0
  277. package/template/components/auto/formatValue.tsx +186 -0
  278. package/template/components/auto/types.ts +42 -0
  279. package/template/components/ui/badge.tsx +40 -0
  280. package/template/components/ui/button.tsx +57 -0
  281. package/template/components/ui/card.tsx +86 -0
  282. package/template/components/ui/dialog.tsx +119 -0
  283. package/template/components/ui/input.tsx +23 -0
  284. package/template/components/ui/label.tsx +24 -0
  285. package/template/components/ui/pagination.tsx +117 -0
  286. package/template/components/ui/select.tsx +92 -0
  287. package/template/components/ui/sheet.tsx +135 -0
  288. package/template/components/ui/skeleton.tsx +15 -0
  289. package/template/components/ui/table.tsx +120 -0
  290. package/template/components/ui/tabs.tsx +55 -0
  291. package/template/lib/utils.ts +35 -0
  292. package/template/next.config.mjs +52 -0
  293. package/template/package.json +46 -0
  294. package/template/postcss.config.js +6 -0
  295. package/template/scripts/start-shopping-backend.sh +56 -0
  296. package/template/tailwind.config.ts +96 -0
  297. package/template/tsconfig.json +29 -0
@@ -0,0 +1,86 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { describeEndpointPropsShape } from "./describeEndpointPropsShape";
4
+
5
+ const stub = (
6
+ overrides: Partial<IAutoViewEndpoint>,
7
+ ): IAutoViewEndpoint => ({
8
+ method: "patch",
9
+ path: "/things",
10
+ specification: "",
11
+ description: "",
12
+ authorizationType: null,
13
+ parameters: [],
14
+ requestBody: null,
15
+ responseBody: null,
16
+ authorizationActor: null,
17
+ name: "index",
18
+ prerequisites: [],
19
+ accessor: ["things", "index"],
20
+ ...overrides,
21
+ });
22
+
23
+ describe("describeEndpointPropsShape", () => {
24
+ it("returns `{}` when there are no path params and no body", () => {
25
+ expect(describeEndpointPropsShape(stub({}))).toBe("{}");
26
+ });
27
+
28
+ it("emits a single path parameter", () => {
29
+ expect(
30
+ describeEndpointPropsShape(
31
+ stub({
32
+ method: "get",
33
+ name: "at",
34
+ parameters: [
35
+ { name: "id", description: "", schema: { type: "string" } },
36
+ ],
37
+ }),
38
+ ),
39
+ ).toBe("{ id: string }");
40
+ });
41
+
42
+ it("wraps the body type under `body` when no path params exist", () => {
43
+ expect(
44
+ describeEndpointPropsShape(
45
+ stub({
46
+ requestBody: { description: "", typeName: "IShoppingSale.IRequest" },
47
+ }),
48
+ ),
49
+ ).toBe("{ body: IShoppingSale.IRequest }");
50
+ });
51
+
52
+ it("combines multiple path params with the body wrapper", () => {
53
+ expect(
54
+ describeEndpointPropsShape(
55
+ stub({
56
+ method: "post",
57
+ name: "create",
58
+ parameters: [
59
+ { name: "saleId", description: "", schema: { type: "string" } },
60
+ { name: "reviewId", description: "", schema: { type: "string" } },
61
+ ],
62
+ requestBody: {
63
+ description: "",
64
+ typeName: "IShoppingSaleReviewComment.ICreate",
65
+ },
66
+ }),
67
+ ),
68
+ ).toBe(
69
+ "{ saleId: string; reviewId: string; body: IShoppingSaleReviewComment.ICreate }",
70
+ );
71
+ });
72
+
73
+ it("maps integer/number param schemas to `number`", () => {
74
+ expect(
75
+ describeEndpointPropsShape(
76
+ stub({
77
+ method: "get",
78
+ name: "at",
79
+ parameters: [
80
+ { name: "index", description: "", schema: { type: "integer" } },
81
+ ],
82
+ }),
83
+ ),
84
+ ).toBe("{ index: number }");
85
+ });
86
+ });
@@ -0,0 +1,202 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { IAutoViewEndpoint } from "../../utils";
3
+
4
+ /**
5
+ * Derive the Nestia `(connection, props)` call shape for a single AutoBE
6
+ * operation as a one-line TypeScript signature string. Used by the Render phase
7
+ * to spoon-feed the LLM the exact `props` object shape it has to pass —
8
+ * otherwise the model routinely flattens body fields into the top level of
9
+ * `props`, which makes the simulator return a masked 400 and the page renders
10
+ * the empty state.
11
+ *
12
+ * Examples (matching the live shopping SDK):
13
+ *
14
+ * - `at` on `/sales/:id` → `{ id: string }`
15
+ * - `index` on `/sales` (PATCH) → `{ body: IShoppingSale.IRequest }`
16
+ * - `create` on `/sales/:saleId/reviews` → `{ saleId: string; body:
17
+ * IShoppingSaleReview.ICreate }`
18
+ *
19
+ * Pure. Does not mutate the operation.
20
+ */
21
+ export function describeEndpointPropsShape(
22
+ op: IAutoViewEndpoint,
23
+ ): string {
24
+ const fields: string[] = [];
25
+ for (const param of op.parameters) {
26
+ fields.push(`${param.name}: ${renderParamType(param.schema)}`);
27
+ }
28
+ // Query endpoints carry their query object under `props.query`. Omitting it
29
+ // here is exactly why the Render LLM passed `undefined` as props for
30
+ // findByStatus / login and broke typecheck — the props shape never told it a
31
+ // query existed.
32
+ if (op.query != null) {
33
+ fields.push(`query: ${renderQueryShape(op.query)}`);
34
+ }
35
+ if (op.requestBody !== null) {
36
+ fields.push(`body: ${op.requestBody.typeName}`);
37
+ }
38
+ if (fields.length === 0) return "{}";
39
+ return `{ ${fields.join("; ")} }`;
40
+ }
41
+
42
+ /** Render a query schema: a named component (nestia emits `*.GetQuery`) or an
43
+ * inline object. The Render phase imports the named SDK type either way. */
44
+ function renderQueryShape(query: OpenApi.IJsonSchema): string {
45
+ if ("$ref" in query && typeof query.$ref === "string") {
46
+ return query.$ref.split("/").pop()!;
47
+ }
48
+ if ("properties" in query && query.properties) {
49
+ const required = new Set(query.required ?? []);
50
+ const fields = Object.entries(query.properties).map(([name, prop]) => {
51
+ const optional = required.has(name) ? "" : "?";
52
+ const type = "type" in prop ? String(prop.type) : "unknown";
53
+ return `${name}${optional}: ${type}`;
54
+ });
55
+ return fields.length > 0 ? `{ ${fields.join("; ")} }` : "{}";
56
+ }
57
+ return "Record<string, unknown>";
58
+ }
59
+
60
+ /**
61
+ * Inspect the document's component schemas and return a brief, machine-friendly
62
+ * line describing the operation's request body — what type it is, which fields
63
+ * are required, and a sample literal the LLM can copy verbatim into the page
64
+ * when no domain-specific filter applies.
65
+ *
66
+ * Returns an empty string when the operation has no request body, or when the
67
+ * referenced schema cannot be resolved (the prompt is then unchanged for that
68
+ * endpoint, no harm done).
69
+ *
70
+ * Format:
71
+ *
72
+ * body: IShoppingSale.IRequest — required: [page, limit]; example: { "page": 1, "limit": 24 }
73
+ *
74
+ * Pure. Does not mutate the document.
75
+ */
76
+ export function describeRequestBodyHint(
77
+ op: IAutoViewEndpoint,
78
+ doc: OpenApi.IDocument,
79
+ ): string {
80
+ if (op.requestBody === null) return "";
81
+ const schema = (doc.components?.schemas ?? {})[op.requestBody.typeName];
82
+ if (schema === undefined) return `body: ${op.requestBody.typeName}`;
83
+ const required = collectRequired(schema, doc);
84
+ const example = sampleLiteral(schema, doc, required);
85
+ const requiredPart =
86
+ required.length > 0
87
+ ? ` — required: [${required.join(", ")}]`
88
+ : " — (no required fields)";
89
+ const examplePart = example !== null ? `; example: ${example}` : "";
90
+ return `body: ${op.requestBody.typeName}${requiredPart}${examplePart}`;
91
+ }
92
+
93
+ function renderParamType(schema: OpenApi.IJsonSchema): string {
94
+ if (!("type" in schema)) return "string";
95
+ switch (schema.type) {
96
+ case "integer":
97
+ case "number":
98
+ return "number";
99
+ case "boolean":
100
+ return "boolean";
101
+ default:
102
+ return "string";
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Pull the `required[]` list out of an object schema, resolving a single level
108
+ * of `$ref` indirection when the type name points at a nested component.
109
+ * Returns an empty array for non-object schemas so callers can uniformly print
110
+ * "(no required fields)".
111
+ */
112
+ function collectRequired(
113
+ schema: OpenApi.IJsonSchema,
114
+ doc: OpenApi.IDocument,
115
+ ): string[] {
116
+ const resolved = resolveSchema(schema, doc);
117
+ if (resolved === null) return [];
118
+ if (!("type" in resolved) || resolved.type !== "object") return [];
119
+ return resolved.required ?? [];
120
+ }
121
+
122
+ /**
123
+ * Best-effort literal that satisfies the schema's required fields. Used to give
124
+ * the LLM a concrete `{ "body": ... }` starting point instead of a bare type
125
+ * name. We do not try to be exhaustive — just enough to clear the typia
126
+ * validation gate (page/limit numbers, empty arrays for collections, null for
127
+ * nullable refs, etc.).
128
+ */
129
+ function sampleLiteral(
130
+ schema: OpenApi.IJsonSchema,
131
+ doc: OpenApi.IDocument,
132
+ required: string[],
133
+ ): string | null {
134
+ const resolved = resolveSchema(schema, doc);
135
+ if (resolved === null) return null;
136
+ if (!("type" in resolved) || resolved.type !== "object") return null;
137
+ const obj = resolved as OpenApi.IJsonSchema.IObject;
138
+ const entries: string[] = [];
139
+ for (const field of required) {
140
+ const childSchema = (obj.properties ?? {})[field];
141
+ if (childSchema === undefined) continue;
142
+ entries.push(
143
+ `${JSON.stringify(field)}: ${sampleValue(childSchema, doc, field)}`,
144
+ );
145
+ }
146
+ return `{ ${entries.join(", ")} }`;
147
+ }
148
+
149
+ function sampleValue(
150
+ schema: OpenApi.IJsonSchema,
151
+ doc: OpenApi.IDocument,
152
+ fieldHint: string,
153
+ ): string {
154
+ const resolved = resolveSchema(schema, doc) ?? schema;
155
+ if ("const" in resolved) {
156
+ return JSON.stringify(
157
+ (resolved as OpenApi.IJsonSchema.IConstant).const,
158
+ );
159
+ }
160
+ if ("oneOf" in resolved) {
161
+ const branches = resolved.oneOf;
162
+ if (branches.length > 0) return sampleValue(branches[0]!, doc, fieldHint);
163
+ return "null";
164
+ }
165
+ if (!("type" in resolved)) return "null";
166
+ switch (resolved.type) {
167
+ case "boolean":
168
+ return "false";
169
+ case "integer":
170
+ case "number":
171
+ if (fieldHint === "page" || fieldHint === "current") return "1";
172
+ if (fieldHint === "limit") return "24";
173
+ return "0";
174
+ case "string":
175
+ return '""';
176
+ case "array":
177
+ return "[]";
178
+ case "object":
179
+ return "{}";
180
+ case "null":
181
+ return "null";
182
+ }
183
+ return "null";
184
+ }
185
+
186
+ /**
187
+ * Follow a single layer of `$ref` indirection so callers can ask for an object
188
+ * schema by type name (the request-body `typeName`) and receive the resolved
189
+ * component back. Returns `null` when the ref does not point at a known
190
+ * component.
191
+ */
192
+ function resolveSchema(
193
+ schema: OpenApi.IJsonSchema,
194
+ doc: OpenApi.IDocument,
195
+ ): OpenApi.IJsonSchema | null {
196
+ if ("$ref" in schema && typeof schema.$ref === "string") {
197
+ const name = schema.$ref.replace(/^#\/components\/schemas\//, "");
198
+ const target = (doc.components?.schemas ?? {})[name];
199
+ return (target ?? null) as OpenApi.IJsonSchema | null;
200
+ }
201
+ return schema;
202
+ }
@@ -0,0 +1,87 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { describeEndpointRequestBodyShape } from "./describeEndpointRequestBodyShape";
5
+
6
+ const op = (
7
+ overrides: Partial<IAutoViewEndpoint>,
8
+ ): IAutoViewEndpoint => ({
9
+ method: "patch",
10
+ path: "/things",
11
+ specification: "",
12
+ description: "",
13
+ authorizationType: null,
14
+ parameters: [],
15
+ requestBody: null,
16
+ responseBody: null,
17
+ authorizationActor: null,
18
+ name: "index",
19
+ prerequisites: [],
20
+ accessor: ["things", "index"],
21
+ ...overrides,
22
+ });
23
+
24
+ const doc = (
25
+ schemas: Record<string, OpenApi.IJsonSchema>,
26
+ ): OpenApi.IDocument =>
27
+ ({
28
+ operations: [],
29
+ components: {
30
+ schemas,
31
+ securitySchemes: {},
32
+ },
33
+ }) as unknown as OpenApi.IDocument;
34
+
35
+ describe("describeEndpointRequestBodyShape", () => {
36
+ it("returns null when the operation has no request body", () => {
37
+ expect(describeEndpointRequestBodyShape(op({}), doc({}))).toBeNull();
38
+ });
39
+
40
+ it("falls back to the bare type name when the schema is missing", () => {
41
+ expect(
42
+ describeEndpointRequestBodyShape(
43
+ op({
44
+ requestBody: { description: "", typeName: "IMissing" },
45
+ }),
46
+ doc({}),
47
+ ),
48
+ ).toBe("IMissing");
49
+ });
50
+
51
+ it("expands sort grammars as arrays of literal-string unions", () => {
52
+ expect(
53
+ describeEndpointRequestBodyShape(
54
+ op({
55
+ requestBody: { description: "", typeName: "ITrashRequest" },
56
+ }),
57
+ doc({
58
+ ITrashRequest: {
59
+ type: "object",
60
+ description: "",
61
+ properties: {
62
+ page: { type: "integer", description: "" },
63
+ sort: {
64
+ type: "array",
65
+ description: "",
66
+ items: {
67
+ oneOf: [
68
+ { const: "created_at.asc", description: "" },
69
+ { const: "created_at.desc", description: "" },
70
+ ],
71
+ },
72
+ },
73
+ },
74
+ required: ["page"],
75
+ },
76
+ }),
77
+ ),
78
+ ).toBe(
79
+ [
80
+ "{",
81
+ " page: number;",
82
+ ' sort?: Array<"created_at.asc" | "created_at.desc">;',
83
+ "}",
84
+ ].join("\n"),
85
+ );
86
+ });
87
+ });
@@ -0,0 +1,31 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { IAutoViewEndpoint } from "../../utils";
3
+
4
+ import { renderNamedSchema } from "./renderJsonSchema";
5
+
6
+ /**
7
+ * Render the request body type of a single AutoBE operation as a readable,
8
+ * multi-line TypeScript-shaped string — mirror of
9
+ * {@link describeEndpointResponseShape} for the input side.
10
+ *
11
+ * The existing one-line {@link describeRequestBodyHint} surfaces the typeName,
12
+ * required keys, and a sample literal, but stops short of expanding nested
13
+ * arrays-of-union-literals (sort grammars) or other deeply-typed request DTOs —
14
+ * which is enough for the LLM to fall back on its priors and emit `sort: {
15
+ * field: ..., direction: ... }[]` against an `ITrashRequest.sort` whose real
16
+ * shape is `("created_at.asc" | "created_at.desc" | ...)[]`. Pre-rendering the
17
+ * full shape on the way in kills that whole class of defect at zero LLM cost,
18
+ * just like the response path does.
19
+ *
20
+ * Returns `null` when the operation has no request body so callers can skip the
21
+ * line entirely rather than emitting `body: void`.
22
+ *
23
+ * Pure. Does not mutate the document.
24
+ */
25
+ export function describeEndpointRequestBodyShape(
26
+ op: IAutoViewEndpoint,
27
+ doc: OpenApi.IDocument,
28
+ ): string | null {
29
+ if (op.requestBody === null) return null;
30
+ return renderNamedSchema(op.requestBody.typeName, doc);
31
+ }
@@ -0,0 +1,70 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { describeEndpointResponseShape } from "./describeEndpointResponseShape";
5
+
6
+ const op = (
7
+ overrides: Partial<IAutoViewEndpoint>,
8
+ ): IAutoViewEndpoint => ({
9
+ method: "get",
10
+ path: "/things",
11
+ specification: "",
12
+ description: "",
13
+ authorizationType: null,
14
+ parameters: [],
15
+ requestBody: null,
16
+ responseBody: null,
17
+ authorizationActor: null,
18
+ name: "at",
19
+ prerequisites: [],
20
+ accessor: ["things", "at"],
21
+ ...overrides,
22
+ });
23
+
24
+ const doc = (
25
+ schemas: Record<string, OpenApi.IJsonSchema>,
26
+ ): OpenApi.IDocument =>
27
+ ({
28
+ operations: [],
29
+ components: {
30
+ schemas,
31
+ securitySchemes: {},
32
+ },
33
+ }) as unknown as OpenApi.IDocument;
34
+
35
+ describe("describeEndpointResponseShape", () => {
36
+ it("returns `void` when the operation has no response body", () => {
37
+ expect(describeEndpointResponseShape(op({}), doc({}))).toBe("void");
38
+ });
39
+
40
+ it("falls back to the bare type name when the schema is missing", () => {
41
+ expect(
42
+ describeEndpointResponseShape(
43
+ op({
44
+ responseBody: { description: "", typeName: "IMissing" },
45
+ }),
46
+ doc({}),
47
+ ),
48
+ ).toBe("IMissing");
49
+ });
50
+
51
+ it("delegates resolved schemas to the shared renderer", () => {
52
+ expect(
53
+ describeEndpointResponseShape(
54
+ op({
55
+ responseBody: { description: "", typeName: "IFlag" },
56
+ }),
57
+ doc({
58
+ IFlag: {
59
+ type: "object",
60
+ description: "",
61
+ properties: {
62
+ value: { type: "boolean", description: "" },
63
+ },
64
+ required: ["value"],
65
+ },
66
+ }),
67
+ ),
68
+ ).toBe(["{", " value: boolean;", "}"].join("\n"));
69
+ });
70
+ });
@@ -0,0 +1,32 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { IAutoViewEndpoint } from "../../utils";
3
+
4
+ import { renderNamedSchema } from "./renderJsonSchema";
5
+
6
+ /**
7
+ * Render the response body type of a single AutoBE operation as a readable,
8
+ * multi-line TypeScript-shaped string. Used by the Render phase to spoon-feed
9
+ * the LLM the exact field names + nesting of every endpoint's return value —
10
+ * otherwise the model invents plausible-sounding properties (e.g. `auth.member`
11
+ * on `IAuthorized` when the real shape is `{ id, created_at, token }`), which
12
+ * then fails TypeScript when the user runs `npm run typecheck` against the
13
+ * generated frontend.
14
+ *
15
+ * Returns `void` when the operation has no response body, so callers can
16
+ * pass-through to `Promise<void>` in the rendered signature. Delegates the
17
+ * actual schema walk to {@link renderJsonSchema} so request and response
18
+ * descriptions stay shape-compatible.
19
+ *
20
+ * Pure. Does not mutate the document.
21
+ */
22
+ export function describeEndpointResponseShape(
23
+ op: IAutoViewEndpoint,
24
+ doc: OpenApi.IDocument,
25
+ ): string {
26
+ if (op.responseBody === null) return "void";
27
+ const shape = renderNamedSchema(op.responseBody.typeName, doc);
28
+ // A list endpoint responds with an array of the element type. Make the
29
+ // array explicit so the Render phase builds a table/list off the element
30
+ // fields, not a single-record view.
31
+ return op.responseBody.isArray ? `${shape}[]` : shape;
32
+ }
@@ -0,0 +1,59 @@
1
+ import { Pair } from "tstl";
2
+ import { v7 } from "uuid";
3
+
4
+ /**
5
+ * Executes a task list with semaphore-controlled parallelization.
6
+ *
7
+ * All tasks are dispatched immediately into a worker pool, with concurrency
8
+ * limited by `semaphore` to prevent overwhelming LLM APIs. Results are returned
9
+ * in original order. On the first task failure the remaining queue is aborted
10
+ * and the original error is rethrown.
11
+ *
12
+ * Standalone copy of `@autobe/agent`'s `executeCachedBatch` that takes the
13
+ * concurrency cap directly as a number — the autoview package does not need the
14
+ * full `AutoBeContext` shape just to read `ctx.vendor.semaphore`.
15
+ *
16
+ * @param semaphore Concurrency cap (1–N parallel tasks at any one time).
17
+ * @param taskList List of async tasks to execute, each receiving the cache key
18
+ * as its argument.
19
+ * @param promptCacheKey Optional cache key (generates a UUID if omitted) — used
20
+ * as the user-message body so the LLM provider can reuse a cached system
21
+ * prompt across calls.
22
+ */
23
+ export const executeCachedBatch = async <T>(
24
+ semaphore: number,
25
+ taskList: Task<T>[],
26
+ promptCacheKey?: string,
27
+ ): Promise<T[]> => {
28
+ if (taskList.length === 0) return [];
29
+
30
+ promptCacheKey ??= v7();
31
+
32
+ const queue: Array<Pair<Task<T>, number>> = taskList.map(
33
+ (task, index) => new Pair(task, index),
34
+ );
35
+ const results: Pair<T, number>[] = [];
36
+ let aborted: boolean = false;
37
+ let firstError: unknown = null;
38
+ await Promise.allSettled(
39
+ new Array(Math.min(semaphore, queue.length)).fill(0).map(async () => {
40
+ while (queue.length !== 0 && !aborted) {
41
+ const item: Pair<Task<T>, number> = queue.splice(0, 1)[0]!;
42
+ try {
43
+ const result: T = await item.first(promptCacheKey!);
44
+ if (!aborted) results.push(new Pair(result, item.second));
45
+ } catch (error) {
46
+ if (!aborted) {
47
+ aborted = true;
48
+ queue.length = 0;
49
+ firstError = error;
50
+ }
51
+ }
52
+ }
53
+ }),
54
+ );
55
+ if (firstError !== null) throw firstError;
56
+ return results.sort((x, y) => x.second - y.second).map((p) => p.first);
57
+ };
58
+
59
+ type Task<T> = (user: string) => Promise<T>;
@@ -0,0 +1,52 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { OpenApiConverter } from "@typia/utils";
3
+
4
+ /**
5
+ * Lazy-load `@samchon/shopping-api/swagger.json` and convert it to an
6
+ * {@link OpenApi.IDocument} so AutoView can run against a stable reference
7
+ * SDK without depending on the live `interface` phase.
8
+ *
9
+ * Also surfaces the swagger's first declared server URL — the bundled
10
+ * `@samchon/shopping-api` swagger lists `https://shopping-be.wrtn.ai` so the
11
+ * generated frontend can hit a real backend (and render real product names like
12
+ * "Apple Watch") instead of typia-random mock gibberish. The Scaffold phase
13
+ * uses this URL to seed the default `IConnection.host`.
14
+ *
15
+ * The swagger payload is ~700 KB, so the result is memoized on the first call.
16
+ * The conversion reuses the same `invertOpenApiDocument` helper the live
17
+ * interface compiler relies on, which means the rest of the AutoView pipeline
18
+ * cannot tell the document came from a fixture instead of a freshly generated
19
+ * session.
20
+ *
21
+ * The shopping-api package ships an OpenAPI 3.x document — its shape is
22
+ * structurally identical to typia's `OpenApi.IDocument`, so we cast through
23
+ * `unknown` rather than dragging in another normalization library. The
24
+ * downstream invert helper validates the relevant fields itself; an
25
+ * incompatible document would surface there.
26
+ */
27
+ export interface IShoppingFixture {
28
+ document: OpenApi.IDocument;
29
+ /**
30
+ * First entry from `swagger.servers[]`. `null` when the swagger omits
31
+ * `servers` (the SDK would then have to rely on simulate-only mocks).
32
+ */
33
+ serverUrl: string | null;
34
+ }
35
+
36
+ let cached: IShoppingFixture | null = null;
37
+
38
+ export function loadShoppingFixture(): IShoppingFixture {
39
+ if (cached !== null) return cached;
40
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
41
+ const swagger = require("@samchon/shopping-api/swagger.json") as {
42
+ servers?: ReadonlyArray<{ url?: string | null } | null> | null;
43
+ };
44
+ const document = OpenApiConverter.upgradeDocument(
45
+ swagger as unknown as Parameters<typeof OpenApiConverter.upgradeDocument>[0],
46
+ );
47
+ const serverUrl =
48
+ swagger.servers?.find((s) => typeof s?.url === "string" && s.url.length > 0)
49
+ ?.url ?? null;
50
+ cached = { document, serverUrl: serverUrl ?? null };
51
+ return cached;
52
+ }