@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,269 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { extractBackendFromSwagger, fromSwagger } from "./fromSwagger";
5
+ import { toEndpoints } from "./utils/toEndpoints";
6
+
7
+ /** Resolve the (possibly `$ref`-promoted) application/json schema of a response. */
8
+ function jsonSchemaOf(
9
+ doc: OpenApi.IDocument,
10
+ path: string,
11
+ method: "get" | "post",
12
+ status: string,
13
+ ): Record<string, unknown> {
14
+ const op = (doc.paths?.[path] as Record<string, unknown> | undefined)?.[
15
+ method
16
+ ] as { responses?: Record<string, { content?: Record<string, { schema?: unknown }> }> } | undefined;
17
+ const schema = op?.responses?.[status]?.content?.["application/json"]?.schema as
18
+ | Record<string, unknown>
19
+ | undefined;
20
+ if (schema === undefined) return {};
21
+ if (typeof schema.$ref === "string") {
22
+ const name = schema.$ref.split("/").pop()!;
23
+ return ((doc.components?.schemas ?? {})[name] ?? {}) as Record<string, unknown>;
24
+ }
25
+ return schema;
26
+ }
27
+
28
+ describe("fromSwagger — strips #/paths/ JSON-pointer allOf members (DigitalOcean)", () => {
29
+ it("keeps the data member when an allOf mixes it with unresolvable path-pointer refs", () => {
30
+ // DO's list responses are allOf:[{properties:{droplets}}, <links-ref>, <meta-ref>]
31
+ // where the refs point into another operation's inline schema. upgradeDocument
32
+ // discards the whole allOf, losing the data — stripping the path refs recovers it.
33
+ const responseSchema = {
34
+ allOf: [
35
+ { properties: { droplets: { type: "array", items: { $ref: "#/components/schemas/Droplet" } } } },
36
+ { $ref: "#/paths/~1other/get/responses/200/content/application~1json/schema/allOf/1" },
37
+ ],
38
+ };
39
+ const raw = {
40
+ openapi: "3.0.0",
41
+ info: { title: "t", version: "1" },
42
+ paths: {
43
+ "/droplets": {
44
+ get: {
45
+ operationId: "i",
46
+ responses: { 200: { description: "ok", content: { "application/json": { schema: responseSchema } } } },
47
+ },
48
+ },
49
+ },
50
+ components: {
51
+ schemas: { Droplet: { type: "object", properties: { id: { type: "integer" }, name: { type: "string" } }, required: ["id"] } },
52
+ },
53
+ };
54
+ const doc = fromSwagger(raw as never);
55
+ const e = toEndpoints(doc).find((x) => x.path === "/droplets");
56
+ expect(e).toBeDefined();
57
+ // the response survived the upgrade with its droplets array (not an empty schema)
58
+ expect(JSON.stringify(jsonSchemaOf(doc, "/droplets", "get", "200"))).toContain("droplets");
59
+ });
60
+
61
+ it("flattens an INLINE allOf in an operation response (DigitalOcean droplets)", () => {
62
+ // DO's `GET /v2/droplets` response is `allOf:[{properties:{droplets}}, {$ref:Pagination}]`
63
+ // INLINE in the operation — not a component schema, so the components-only
64
+ // flatten pass missed it. nestia then emits `Response = any` for the route,
65
+ // `typia.random<any>()` yields nothing, and the simulate-mode list renders
66
+ // empty forever. The flatten must walk the whole document.
67
+ const raw = {
68
+ openapi: "3.0.0",
69
+ info: { title: "t", version: "1" },
70
+ paths: {
71
+ "/droplets": {
72
+ get: {
73
+ operationId: "list",
74
+ responses: {
75
+ 200: {
76
+ description: "ok",
77
+ content: {
78
+ "application/json": {
79
+ schema: {
80
+ allOf: [
81
+ { properties: { droplets: { type: "array", items: { type: "object", properties: { id: { type: "integer" } } } } } },
82
+ { $ref: "#/components/schemas/Pagination" },
83
+ ],
84
+ },
85
+ },
86
+ },
87
+ },
88
+ },
89
+ },
90
+ },
91
+ },
92
+ components: {
93
+ schemas: { Pagination: { type: "object", properties: { total: { type: "integer" } } } },
94
+ },
95
+ };
96
+ const doc = fromSwagger(raw as never);
97
+ const flat = jsonSchemaOf(doc, "/droplets", "get", "200");
98
+ // the inline allOf was merged into plain properties — both members survive
99
+ expect(flat.allOf).toBeUndefined();
100
+ const props = (flat.properties ?? {}) as Record<string, unknown>;
101
+ expect(Object.keys(props).sort()).toEqual(["droplets", "total"]);
102
+ });
103
+
104
+ it("flattens an allOf nested INSIDE a property (DigitalOcean databases.connection)", () => {
105
+ const raw = {
106
+ openapi: "3.0.0",
107
+ info: { title: "t", version: "1" },
108
+ paths: {
109
+ "/databases": {
110
+ get: {
111
+ operationId: "list",
112
+ responses: {
113
+ 200: {
114
+ description: "ok",
115
+ content: {
116
+ "application/json": {
117
+ schema: {
118
+ type: "object",
119
+ properties: {
120
+ connection: { allOf: [{ type: "object", properties: { host: { type: "string" } } }, { type: "object", properties: { port: { type: "integer" } } }] },
121
+ },
122
+ },
123
+ },
124
+ },
125
+ },
126
+ },
127
+ },
128
+ },
129
+ },
130
+ components: { schemas: {} },
131
+ };
132
+ const doc = fromSwagger(raw as never);
133
+ const flat = jsonSchemaOf(doc, "/databases", "get", "200");
134
+ const connection = ((flat.properties ?? {}) as Record<string, Record<string, unknown>>)
135
+ .connection ?? {};
136
+ expect(connection.allOf).toBeUndefined();
137
+ expect(Object.keys((connection.properties ?? {}) as object).sort()).toEqual(["host", "port"]);
138
+ });
139
+
140
+ it("resolves a #/paths/ JSON-pointer $ref OUTSIDE an allOf (DigitalOcean metrics/apps)", () => {
141
+ // DO also DRYs whole schemas as `$ref: "#/paths/~1v2~1bandwidth/get/..."` at
142
+ // the schema ROOT or inside a property — not as an allOf member, so the
143
+ // allOf-stripping pass never sees it. nestia cannot chase the pointer and
144
+ // emits `Response = any`. Resolve the pointer against the document itself.
145
+ const raw = {
146
+ openapi: "3.0.0",
147
+ info: { title: "t", version: "1" },
148
+ paths: {
149
+ "/v2/bandwidth": {
150
+ get: { operationId: "bw", responses: { 200: { description: "ok", content: { "application/json": { schema: { type: "object", properties: { metrics: { type: "array", items: { type: "object", properties: { value: { type: "number" } } } } } } } } } } },
151
+ },
152
+ "/v2/cpu": {
153
+ get: { operationId: "cpu", responses: { 200: { description: "ok", content: { "application/json": { schema: { $ref: "#/paths/~1v2~1bandwidth/get/responses/200/content/application~1json/schema" } } } } } },
154
+ },
155
+ },
156
+ components: { schemas: {} },
157
+ };
158
+ const doc = fromSwagger(raw as never);
159
+ const cpu = jsonSchemaOf(doc, "/v2/cpu", "get", "200");
160
+ // the pointer was resolved to the bandwidth schema's real shape
161
+ expect(JSON.stringify(cpu)).toContain("metrics");
162
+ const e = toEndpoints(doc).find((x) => x.path === "/v2/cpu");
163
+ expect(e?.responseBody ?? e?.responseSchema).not.toBeNull();
164
+ });
165
+
166
+ it("promotes colliding inline responses so a parent list and child detail both stay typed", () => {
167
+ // nestia derives the promoted component name from the path with `{param}`
168
+ // segments dropped, so `/v2/droplets` and `/v2/droplets/{droplet_id}` both
169
+ // claim `IApiV2Droplets.GetResponse` — the loser's SDK function comes out
170
+ // `Response = any` and its simulate screen renders empty forever (38 of
171
+ // DigitalOcean's 148 SDK files). Promoting each inline OBJECT body to a
172
+ // unique named component before nestia sees it removes the collision.
173
+ const inlineObj = (props: Record<string, unknown>) => ({
174
+ type: "object",
175
+ properties: props,
176
+ });
177
+ const raw = {
178
+ openapi: "3.0.0",
179
+ info: { title: "t", version: "1" },
180
+ paths: {
181
+ "/v2/droplets": {
182
+ get: { operationId: "list", responses: { 200: { description: "ok", content: { "application/json": { schema: inlineObj({ droplets: { type: "array", items: inlineObj({ id: { type: "integer" } }) } }) } } } } },
183
+ },
184
+ "/v2/droplets/{droplet_id}": {
185
+ get: { operationId: "at", parameters: [{ name: "droplet_id", in: "path", required: true, schema: { type: "integer" } }], responses: { 200: { description: "ok", content: { "application/json": { schema: inlineObj({ droplet: inlineObj({ id: { type: "integer" } }) }) } } } } },
186
+ },
187
+ },
188
+ components: { schemas: {} },
189
+ };
190
+ const doc = fromSwagger(raw as never);
191
+ const eps = toEndpoints(doc);
192
+ const list = eps.find((e) => e.path === "/v2/droplets");
193
+ const detail = eps.find((e) => e.path === "/v2/droplets/{droplet_id}");
194
+ // BOTH carry a named response type that resolves in the document — neither
195
+ // collapsed to an untyped (any) body.
196
+ for (const e of [list, detail]) {
197
+ expect(e?.responseBody).not.toBeNull();
198
+ expect((doc.components?.schemas ?? {})[e!.responseBody!.typeName]).toBeDefined();
199
+ }
200
+ expect(list!.responseBody!.typeName).not.toBe(detail!.responseBody!.typeName);
201
+ });
202
+
203
+ it("drops a path whose {param} name is not a valid identifier (GitHub's {enterprise-team})", () => {
204
+ // nestia derives the SDK accessor from the param name and crashes on a
205
+ // hyphenated one — taking the WHOLE generation down. Drop just that path.
206
+ const raw = {
207
+ openapi: "3.0.0",
208
+ info: { title: "t", version: "1" },
209
+ paths: {
210
+ "/teams/{teamId}": { get: { operationId: "ok", parameters: [{ name: "teamId", in: "path", required: true, schema: { type: "string" } }], responses: { 200: { description: "ok" } } } },
211
+ "/teams/{enterprise-team}/members": { get: { operationId: "bad", parameters: [{ name: "enterprise-team", in: "path", required: true, schema: { type: "string" } }], responses: { 200: { description: "ok" } } } },
212
+ },
213
+ components: { schemas: {} },
214
+ };
215
+ const doc = fromSwagger(raw as never);
216
+ expect(doc.paths["/teams/{teamId}"]).toBeDefined(); // the valid one survives
217
+ expect(doc.paths["/teams/{enterprise-team}/members"]).toBeUndefined(); // the hyphen one is dropped
218
+ });
219
+ });
220
+
221
+ describe("extractBackendFromSwagger", () => {
222
+ it("returns null for non-object payloads", () => {
223
+ expect(extractBackendFromSwagger(null)).toBeNull();
224
+ expect(extractBackendFromSwagger(undefined)).toBeNull();
225
+ expect(extractBackendFromSwagger("")).toBeNull();
226
+ expect(extractBackendFromSwagger(42)).toBeNull();
227
+ });
228
+
229
+ it("returns null when servers is missing", () => {
230
+ expect(extractBackendFromSwagger({})).toBeNull();
231
+ expect(extractBackendFromSwagger({ openapi: "3.0.0" })).toBeNull();
232
+ });
233
+
234
+ it("returns null when servers is empty or not an array", () => {
235
+ expect(extractBackendFromSwagger({ servers: [] })).toBeNull();
236
+ expect(
237
+ extractBackendFromSwagger({ servers: "http://x" } as unknown),
238
+ ).toBeNull();
239
+ });
240
+
241
+ it("returns the first server with a non-empty url", () => {
242
+ expect(
243
+ extractBackendFromSwagger({
244
+ servers: [{ url: "https://api.example.com" }],
245
+ }),
246
+ ).toEqual({ host: "https://api.example.com" });
247
+ });
248
+
249
+ it("skips entries with missing or empty url and picks the next valid one", () => {
250
+ expect(
251
+ extractBackendFromSwagger({
252
+ servers: [
253
+ {},
254
+ { url: "" },
255
+ { url: 42 },
256
+ { url: "https://api.example.com" },
257
+ ],
258
+ }),
259
+ ).toEqual({ host: "https://api.example.com" });
260
+ });
261
+
262
+ it("returns null when no server has a usable url", () => {
263
+ expect(
264
+ extractBackendFromSwagger({
265
+ servers: [{}, { url: "" }, { url: null }],
266
+ }),
267
+ ).toBeNull();
268
+ });
269
+ });