@voxgig/sdkgen 1.2.1 → 1.3.2

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 (345) hide show
  1. package/bin/voxgig-sdkgen +2 -2
  2. package/dist/action/action.d.ts +3 -1
  3. package/dist/action/action.js +26 -10
  4. package/dist/action/action.js.map +1 -1
  5. package/dist/action/feature.js +9 -8
  6. package/dist/action/feature.js.map +1 -1
  7. package/dist/action/target.d.ts +7 -1
  8. package/dist/action/target.js +22 -13
  9. package/dist/action/target.js.map +1 -1
  10. package/dist/cmp/Changelog.d.ts +2 -0
  11. package/dist/cmp/Changelog.js +30 -0
  12. package/dist/cmp/Changelog.js.map +1 -0
  13. package/dist/cmp/Deploy.d.ts +2 -0
  14. package/dist/cmp/Deploy.js +227 -0
  15. package/dist/cmp/Deploy.js.map +1 -0
  16. package/dist/cmp/FeatureHook.js +5 -6
  17. package/dist/cmp/FeatureHook.js.map +1 -1
  18. package/dist/cmp/License.d.ts +2 -0
  19. package/dist/cmp/License.js +44 -0
  20. package/dist/cmp/License.js.map +1 -0
  21. package/dist/cmp/Readme.js +2 -0
  22. package/dist/cmp/Readme.js.map +1 -1
  23. package/dist/cmp/ReadmeErrors.d.ts +2 -0
  24. package/dist/cmp/ReadmeErrors.js +210 -0
  25. package/dist/cmp/ReadmeErrors.js.map +1 -0
  26. package/dist/cmp/ReadmeExplanation.js +213 -223
  27. package/dist/cmp/ReadmeExplanation.js.map +1 -1
  28. package/dist/cmp/ReadmeModel.js +6 -1
  29. package/dist/cmp/ReadmeModel.js.map +1 -1
  30. package/dist/cmp/ReadmeTop.js +389 -82
  31. package/dist/cmp/ReadmeTop.js.map +1 -1
  32. package/dist/cmp/Security.d.ts +2 -0
  33. package/dist/cmp/Security.js +36 -0
  34. package/dist/cmp/Security.js.map +1 -0
  35. package/dist/helpers/canonType.d.ts +7 -0
  36. package/dist/helpers/canonType.js +74 -0
  37. package/dist/helpers/canonType.js.map +1 -0
  38. package/dist/helpers/collectDeps.d.ts +3 -2
  39. package/dist/helpers/collectDeps.js.map +1 -1
  40. package/dist/helpers/naming.d.ts +3 -0
  41. package/dist/helpers/naming.js +51 -0
  42. package/dist/helpers/naming.js.map +1 -0
  43. package/dist/helpers/opExample.d.ts +13 -0
  44. package/dist/helpers/opExample.js +149 -0
  45. package/dist/helpers/opExample.js.map +1 -0
  46. package/dist/helpers/opShape.d.ts +18 -0
  47. package/dist/helpers/opShape.js +225 -0
  48. package/dist/helpers/opShape.js.map +1 -0
  49. package/dist/helpers/packageMeta.d.ts +27 -0
  50. package/dist/helpers/packageMeta.js +224 -0
  51. package/dist/helpers/packageMeta.js.map +1 -0
  52. package/dist/sdkgen.d.ts +12 -2
  53. package/dist/sdkgen.js +60 -20
  54. package/dist/sdkgen.js.map +1 -1
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/dist/types.d.ts +65 -2
  57. package/dist/types.js.map +1 -1
  58. package/dist/utility.d.ts +2 -1
  59. package/dist/utility.js +39 -11
  60. package/dist/utility.js.map +1 -1
  61. package/model/sdkgen.aontu +137 -0
  62. package/package.json +11 -5
  63. package/project/.sdk/model/feature/feature-index.aontu +5 -0
  64. package/project/.sdk/model/target/go-cli.aontu +47 -0
  65. package/project/.sdk/model/target/go-mcp.aontu +41 -0
  66. package/project/.sdk/model/target/go.aontu +28 -0
  67. package/project/.sdk/model/target/{js.jsonic → js.aontu} +13 -0
  68. package/project/.sdk/model/target/{lua.jsonic → lua.aontu} +13 -0
  69. package/project/.sdk/model/target/{php.jsonic → php.aontu} +13 -0
  70. package/project/.sdk/model/target/{py.jsonic → py.aontu} +13 -0
  71. package/project/.sdk/model/target/{rb.jsonic → rb.aontu} +13 -0
  72. package/project/.sdk/model/target/{ts.jsonic → ts.aontu} +13 -0
  73. package/project/.sdk/src/cmp/go/Config_go.ts +3 -2
  74. package/project/.sdk/src/cmp/go/EntityOperation_go.ts +1 -0
  75. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +197 -0
  76. package/project/.sdk/src/cmp/go/Entity_go.ts +2 -1
  77. package/project/.sdk/src/cmp/go/MainEntity_go.ts +6 -0
  78. package/project/.sdk/src/cmp/go/Main_go.ts +23 -3
  79. package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
  80. package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +48 -10
  81. package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +688 -0
  82. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
  83. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +52 -8
  84. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +11 -6
  85. package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +40 -1
  86. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +67 -17
  87. package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +4 -3
  88. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +146 -116
  89. package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +87 -21
  90. package/project/.sdk/src/cmp/go/ReadmeTopHowto_go.ts +4 -0
  91. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +75 -16
  92. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +35 -5
  93. package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
  94. package/project/.sdk/src/cmp/go/Test_go.ts +5 -1
  95. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +21 -0
  96. package/project/.sdk/src/cmp/go/fragment/EntityCreateOp.fragment.go +11 -0
  97. package/project/.sdk/src/cmp/go/fragment/EntityListOp.fragment.go +11 -0
  98. package/project/.sdk/src/cmp/go/fragment/EntityLoadOp.fragment.go +11 -0
  99. package/project/.sdk/src/cmp/go/fragment/EntityRemoveOp.fragment.go +11 -0
  100. package/project/.sdk/src/cmp/go/fragment/EntityUpdateOp.fragment.go +11 -0
  101. package/project/.sdk/src/cmp/go/utility_go.ts +70 -0
  102. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +195 -0
  103. package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +106 -0
  104. package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +132 -0
  105. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +184 -0
  106. package/project/.sdk/src/cmp/go-mcp/fragment/main.fragment.go +68 -0
  107. package/project/.sdk/src/cmp/go-mcp/fragment/tools.fragment.go +114 -0
  108. package/project/.sdk/src/cmp/js/Config_js.ts +3 -6
  109. package/project/.sdk/src/cmp/js/EntityTypes_js.ts +111 -0
  110. package/project/.sdk/src/cmp/js/MainEntity_js.ts +1 -0
  111. package/project/.sdk/src/cmp/js/Main_js.ts +3 -0
  112. package/project/.sdk/src/cmp/js/Package_js.ts +16 -7
  113. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +33 -10
  114. package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +2 -2
  115. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +52 -11
  116. package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +39 -1
  117. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +50 -18
  118. package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +4 -3
  119. package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +70 -20
  120. package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +50 -16
  121. package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +3 -0
  122. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +45 -19
  123. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +35 -3
  124. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +5 -0
  125. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +5 -0
  126. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +5 -0
  127. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +5 -0
  128. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +5 -0
  129. package/project/.sdk/src/cmp/js/utility_js.ts +57 -0
  130. package/project/.sdk/src/cmp/lua/Config_lua.ts +3 -2
  131. package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +113 -0
  132. package/project/.sdk/src/cmp/lua/MainEntity_lua.ts +8 -0
  133. package/project/.sdk/src/cmp/lua/Main_lua.ts +4 -0
  134. package/project/.sdk/src/cmp/lua/Package_lua.ts +23 -4
  135. package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +50 -13
  136. package/project/.sdk/src/cmp/lua/ReadmeExamplesTest_lua.ts +293 -0
  137. package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +46 -8
  138. package/project/.sdk/src/cmp/lua/ReadmeInstall_lua.ts +19 -3
  139. package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +38 -1
  140. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +51 -16
  141. package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +4 -3
  142. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +156 -21
  143. package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +71 -23
  144. package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +46 -9
  145. package/project/.sdk/src/cmp/lua/ReadmeTopTest_lua.ts +43 -5
  146. package/project/.sdk/src/cmp/lua/Test_lua.ts +4 -0
  147. package/project/.sdk/src/cmp/lua/fragment/EntityCreateOp.fragment.lua +4 -0
  148. package/project/.sdk/src/cmp/lua/fragment/EntityListOp.fragment.lua +4 -0
  149. package/project/.sdk/src/cmp/lua/fragment/EntityLoadOp.fragment.lua +4 -0
  150. package/project/.sdk/src/cmp/lua/fragment/EntityRemoveOp.fragment.lua +4 -0
  151. package/project/.sdk/src/cmp/lua/fragment/EntityUpdateOp.fragment.lua +4 -0
  152. package/project/.sdk/src/cmp/php/Config_php.ts +3 -2
  153. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +142 -0
  154. package/project/.sdk/src/cmp/php/MainEntity_php.ts +18 -1
  155. package/project/.sdk/src/cmp/php/Main_php.ts +4 -0
  156. package/project/.sdk/src/cmp/php/Package_php.ts +18 -7
  157. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +46 -14
  158. package/project/.sdk/src/cmp/php/ReadmeExamplesTest_php.ts +401 -0
  159. package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +56 -13
  160. package/project/.sdk/src/cmp/php/ReadmeInstall_php.ts +15 -3
  161. package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +40 -1
  162. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +26 -8
  163. package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +4 -3
  164. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +159 -25
  165. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +90 -45
  166. package/project/.sdk/src/cmp/php/ReadmeTopHowto_php.ts +1 -1
  167. package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +43 -11
  168. package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +52 -11
  169. package/project/.sdk/src/cmp/php/TestDirect_php.ts +9 -9
  170. package/project/.sdk/src/cmp/php/TestEntity_php.ts +6 -12
  171. package/project/.sdk/src/cmp/php/Test_php.ts +4 -0
  172. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +13 -1
  173. package/project/.sdk/src/cmp/php/fragment/EntityCreateOp.fragment.php +10 -1
  174. package/project/.sdk/src/cmp/php/fragment/EntityListOp.fragment.php +10 -1
  175. package/project/.sdk/src/cmp/php/fragment/EntityLoadOp.fragment.php +10 -1
  176. package/project/.sdk/src/cmp/php/fragment/EntityRemoveOp.fragment.php +10 -1
  177. package/project/.sdk/src/cmp/php/fragment/EntityUpdateOp.fragment.php +10 -1
  178. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +22 -14
  179. package/project/.sdk/src/cmp/py/Config_py.ts +3 -2
  180. package/project/.sdk/src/cmp/py/EntityTypes_py.ts +184 -0
  181. package/project/.sdk/src/cmp/py/Entity_py.ts +27 -0
  182. package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -1
  183. package/project/.sdk/src/cmp/py/Main_py.ts +35 -0
  184. package/project/.sdk/src/cmp/py/Package_py.ts +24 -3
  185. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +48 -14
  186. package/project/.sdk/src/cmp/py/ReadmeExamplesTest_py.ts +626 -0
  187. package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +53 -14
  188. package/project/.sdk/src/cmp/py/ReadmeInstall_py.ts +19 -3
  189. package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +48 -1
  190. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +28 -10
  191. package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +4 -3
  192. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +150 -27
  193. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +86 -40
  194. package/project/.sdk/src/cmp/py/ReadmeTopHowto_py.ts +1 -1
  195. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +45 -11
  196. package/project/.sdk/src/cmp/py/ReadmeTopTest_py.ts +43 -5
  197. package/project/.sdk/src/cmp/py/TestDirect_py.ts +7 -9
  198. package/project/.sdk/src/cmp/py/TestEntity_py.ts +6 -14
  199. package/project/.sdk/src/cmp/py/Test_py.ts +4 -0
  200. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +5 -2
  201. package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +1 -1
  202. package/project/.sdk/src/cmp/py/fragment/EntityListOp.fragment.py +5 -1
  203. package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +6 -1
  204. package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +6 -1
  205. package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +1 -1
  206. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +17 -10
  207. package/project/.sdk/src/cmp/rb/Config_rb.ts +3 -2
  208. package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +136 -0
  209. package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +1 -0
  210. package/project/.sdk/src/cmp/rb/Main_rb.ts +4 -0
  211. package/project/.sdk/src/cmp/rb/Package_rb.ts +34 -7
  212. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +47 -13
  213. package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +289 -0
  214. package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +72 -21
  215. package/project/.sdk/src/cmp/rb/ReadmeInstall_rb.ts +16 -4
  216. package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +40 -1
  217. package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +29 -12
  218. package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +4 -3
  219. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +163 -25
  220. package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +85 -40
  221. package/project/.sdk/src/cmp/rb/ReadmeTopHowto_rb.ts +1 -1
  222. package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +45 -11
  223. package/project/.sdk/src/cmp/rb/ReadmeTopTest_rb.ts +54 -11
  224. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +9 -9
  225. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +6 -12
  226. package/project/.sdk/src/cmp/rb/Test_rb.ts +4 -0
  227. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +2 -0
  228. package/project/.sdk/src/cmp/rb/fragment/EntityCreateOp.fragment.rb +5 -0
  229. package/project/.sdk/src/cmp/rb/fragment/EntityListOp.fragment.rb +20 -2
  230. package/project/.sdk/src/cmp/rb/fragment/EntityLoadOp.fragment.rb +8 -1
  231. package/project/.sdk/src/cmp/rb/fragment/EntityRemoveOp.fragment.rb +6 -1
  232. package/project/.sdk/src/cmp/rb/fragment/EntityUpdateOp.fragment.rb +5 -0
  233. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +24 -8
  234. package/project/.sdk/src/cmp/ts/Config_ts.ts +3 -6
  235. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +105 -0
  236. package/project/.sdk/src/cmp/ts/Entity_ts.ts +17 -1
  237. package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +1 -0
  238. package/project/.sdk/src/cmp/ts/Main_ts.ts +6 -0
  239. package/project/.sdk/src/cmp/ts/Package_ts.ts +14 -7
  240. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +32 -10
  241. package/project/.sdk/src/cmp/ts/ReadmeExampleTest_ts.ts +81 -0
  242. package/project/.sdk/src/cmp/ts/ReadmeExamplesTest_ts.ts +446 -0
  243. package/project/.sdk/src/cmp/ts/ReadmeExplanation_ts.ts +2 -2
  244. package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +57 -11
  245. package/project/.sdk/src/cmp/ts/ReadmeInstall_ts.ts +19 -6
  246. package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +39 -1
  247. package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +50 -18
  248. package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +4 -3
  249. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +141 -48
  250. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +50 -16
  251. package/project/.sdk/src/cmp/ts/ReadmeTopHowto_ts.ts +3 -0
  252. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +58 -19
  253. package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +35 -3
  254. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +2 -2
  255. package/project/.sdk/src/cmp/ts/Test_ts.ts +5 -0
  256. package/project/.sdk/src/cmp/ts/fragment/Entity.fragment.ts +3 -1
  257. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +10 -5
  258. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +4 -2
  259. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +4 -2
  260. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +4 -2
  261. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +4 -2
  262. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +4 -2
  263. package/project/.sdk/src/cmp/ts/utility_ts.ts +59 -0
  264. package/project/.sdk/tm/go/LICENSE +1 -1
  265. package/project/.sdk/tm/go/Makefile +36 -1
  266. package/project/.sdk/tm/go/VERSION +1 -0
  267. package/project/.sdk/tm/go/core/context.go +12 -7
  268. package/project/.sdk/tm/go-cli/src/feature/README.md +6 -0
  269. package/project/.sdk/tm/go-cli/src/feature/base/.gitkeep +0 -0
  270. package/project/.sdk/tm/go-cli/src/feature/log/.gitkeep +0 -0
  271. package/project/.sdk/tm/go-cli/src/feature/test/.gitkeep +0 -0
  272. package/project/.sdk/tm/go-mcp/src/feature/README.md +6 -0
  273. package/project/.sdk/tm/go-mcp/src/feature/base/.gitkeep +0 -0
  274. package/project/.sdk/tm/go-mcp/src/feature/log/.gitkeep +0 -0
  275. package/project/.sdk/tm/go-mcp/src/feature/test/.gitkeep +0 -0
  276. package/project/.sdk/tm/js/LICENSE +1 -1
  277. package/project/.sdk/tm/js/Makefile +41 -0
  278. package/project/.sdk/tm/lua/LICENSE +1 -1
  279. package/project/.sdk/tm/lua/Makefile +40 -1
  280. package/project/.sdk/tm/lua/core/context.lua +13 -8
  281. package/project/.sdk/tm/php/LICENSE +1 -1
  282. package/project/.sdk/tm/php/Makefile +31 -1
  283. package/project/.sdk/tm/php/VERSION +1 -0
  284. package/project/.sdk/tm/php/core/Context.php +12 -6
  285. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +13 -4
  286. package/project/.sdk/tm/php/utility/Done.php +2 -2
  287. package/project/.sdk/tm/php/utility/MakeError.php +3 -3
  288. package/project/.sdk/tm/py/LICENSE +1 -1
  289. package/project/.sdk/tm/py/Makefile +34 -1
  290. package/project/.sdk/tm/py/core/context.py +12 -7
  291. package/project/.sdk/tm/py/test/test_primary_utility.py +15 -4
  292. package/project/.sdk/tm/py/test/test_struct_utility.py +1 -1
  293. package/project/.sdk/tm/py/utility/done.py +3 -1
  294. package/project/.sdk/tm/py/utility/make_error.py +2 -2
  295. package/project/.sdk/tm/rb/LICENSE +1 -1
  296. package/project/.sdk/tm/rb/Makefile +36 -2
  297. package/project/.sdk/tm/rb/core/context.rb +8 -3
  298. package/project/.sdk/tm/rb/test/primary_utility_test.rb +2 -2
  299. package/project/.sdk/tm/rb/utility/done.rb +3 -1
  300. package/project/.sdk/tm/rb/utility/make_error.rb +5 -2
  301. package/project/.sdk/tm/ts/LICENSE +1 -1
  302. package/project/.sdk/tm/ts/Makefile +42 -0
  303. package/project/.sdk/tm/ts/src/Context.ts +8 -3
  304. package/src/action/action.ts +30 -11
  305. package/src/action/feature.ts +12 -14
  306. package/src/action/target.ts +28 -17
  307. package/src/cmp/Changelog.ts +34 -0
  308. package/src/cmp/Deploy.ts +258 -0
  309. package/src/cmp/FeatureHook.ts +6 -8
  310. package/src/cmp/License.ts +49 -0
  311. package/src/cmp/Readme.ts +2 -0
  312. package/src/cmp/ReadmeErrors.ts +257 -0
  313. package/src/cmp/ReadmeExplanation.ts +250 -230
  314. package/src/cmp/ReadmeModel.ts +7 -2
  315. package/src/cmp/ReadmeTop.ts +411 -95
  316. package/src/cmp/Security.ts +41 -0
  317. package/src/helpers/canonType.ts +89 -0
  318. package/src/helpers/collectDeps.ts +5 -3
  319. package/src/helpers/naming.ts +59 -0
  320. package/src/helpers/opExample.ts +170 -0
  321. package/src/helpers/opShape.ts +274 -0
  322. package/src/helpers/packageMeta.ts +236 -0
  323. package/src/sdkgen.ts +91 -23
  324. package/src/tsconfig.json +1 -0
  325. package/src/types.ts +85 -2
  326. package/src/utility.ts +45 -11
  327. package/README.md +0 -2
  328. package/dist/action/lang.d.ts +0 -2
  329. package/dist/action/lang.js +0 -68
  330. package/dist/action/lang.js.map +0 -1
  331. package/dist/cmp/Hook.d.ts +0 -2
  332. package/dist/cmp/Hook.js +0 -10
  333. package/dist/cmp/Hook.js.map +0 -1
  334. package/dist/cmp/Top.d.ts +0 -2
  335. package/dist/cmp/Top.js +0 -23
  336. package/dist/cmp/Top.js.map +0 -1
  337. package/dist/prepare-openapi.d.ts +0 -2
  338. package/dist/prepare-openapi.js +0 -37
  339. package/dist/prepare-openapi.js.map +0 -1
  340. package/model/sdkgen.jsonic +0 -74
  341. package/project/.sdk/model/feature/feature-index.jsonic +0 -5
  342. package/project/.sdk/model/target/go.jsonic +0 -22
  343. package/project/.sdk/tm/go/utility/struct/go.mod +0 -3
  344. /package/project/.sdk/model/feature/{log.jsonic → log.aontu} +0 -0
  345. /package/project/.sdk/model/feature/{test.jsonic → test.aontu} +0 -0
@@ -1,11 +1,13 @@
1
1
 
2
- import { cmp, each, Content } from '@voxgig/sdkgen'
2
+ import { cmp, each, Content, canonToType, entityIdField, opRequestShape, safeVarName } from '@voxgig/sdkgen'
3
3
 
4
4
  import {
5
5
  KIT,
6
6
  getModelPath,
7
7
  } from '@voxgig/apidef'
8
8
 
9
+ import { exampleValue } from './utility_ts'
10
+
9
11
 
10
12
  // Operation method spelling differs between Go and other languages — Go
11
13
  // uses PascalCase methods with explicit ctrl arg, others use lowercase
@@ -41,6 +43,10 @@ const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
41
43
  publishedEntities.map((entity: any) => {
42
44
  const opnames = Object.keys(entity.op || {})
43
45
  const fields = entity.fields || []
46
+ // Model-driven id key: null when this entity has no id-like field.
47
+ const idF = entityIdField(entity)
48
+ // Variable-safe lowercase name (a `Delete` entity must not bind `delete`).
49
+ const eVar = safeVarName(entity.name, target.name)
44
50
 
45
51
  Content(`
46
52
  ### ${entity.Name}
@@ -53,7 +59,7 @@ const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
53
59
  `)
54
60
  }
55
61
 
56
- Content(`Create an instance: \`const ${entity.name} = client.${entity.Name}()\`
62
+ Content(`Create an instance: \`const ${eVar} = client.${entity.Name}()\`
57
63
 
58
64
  `)
59
65
 
@@ -84,7 +90,7 @@ const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
84
90
 
85
91
  each(fields, (field: any) => {
86
92
  const desc = field.short || ''
87
- Content(`| \`${field.name}\` | \`${field.type || 'any'}\` | ${desc} |
93
+ Content(`| \`${field.name}\` | \`${canonToType(field.type, target.name)}\` | ${desc} |
88
94
  `)
89
95
  })
90
96
 
@@ -93,10 +99,22 @@ const ReadmeEntity = cmp(function ReadmeEntity(props: any) {
93
99
  }
94
100
 
95
101
  if (opnames.includes('load')) {
102
+ // The id key plus every REQUIRED match key (parent path params like
103
+ // page_id) — the same shape that generates <Name>LoadMatch, so the
104
+ // example always type-checks.
105
+ const loadItems = opRequestShape(entity, 'load').items
106
+ .filter((it: any) => !it.optional || it.name === idF)
107
+ .sort((a: any, b: any) =>
108
+ (a.name === idF ? 0 : 1) - (b.name === idF ? 0 : 1))
109
+ const loadArg = 0 < loadItems.length
110
+ ? `{ ${loadItems.map((it: any) =>
111
+ `${it.name}: ${exampleValue(entity, entity.op && entity.op.load, it.name,
112
+ it.name === idF ? entity.name + '_id' : it.name)}`).join(', ')} }`
113
+ : ''
96
114
  Content(`#### Example: Load
97
115
 
98
116
  \`\`\`ts
99
- const ${entity.name} = await client.${entity.Name}().load({ id: '${entity.name}_id' })
117
+ const ${eVar} = await client.${entity.Name}().load(${loadArg})
100
118
  \`\`\`
101
119
 
102
120
  `)
@@ -106,23 +124,27 @@ const ${entity.name} = await client.${entity.Name}().load({ id: '${entity.name}_
106
124
  Content(`#### Example: List
107
125
 
108
126
  \`\`\`ts
109
- const ${entity.name}s = await client.${entity.Name}().list()
127
+ const ${eVar}s = await client.${entity.Name}().list()
110
128
  \`\`\`
111
129
 
112
130
  `)
113
131
  }
114
132
 
115
133
  if (opnames.includes('create')) {
134
+ // Members come from the SAME shape that generates <Name>CreateData:
135
+ // every required member must appear (the /* type */ placeholders also
136
+ // mark the block as an illustration for the doc gates); an
137
+ // all-optional create renders an empty — still assignable — literal.
138
+ const createItems = opRequestShape(entity, 'create').items
139
+ .filter((it: any) => !it.optional)
116
140
  Content(`#### Example: Create
117
141
 
118
142
  \`\`\`ts
119
- const ${entity.name} = await client.${entity.Name}().create({
143
+ const ${eVar} = await client.${entity.Name}().create({
120
144
  `)
121
- each(fields, (field: any) => {
122
- if ('id' !== field.name && field.req) {
123
- Content(` ${field.name}: /* ${field.type || 'value'} */,
145
+ createItems.map((it: any) => {
146
+ Content(` ${it.name}: /* ${canonToType(it.type, target.name)} */,
124
147
  `)
125
- }
126
148
  })
127
149
  Content(`})
128
150
  \`\`\`
@@ -0,0 +1,81 @@
1
+
2
+ import { cmp, Content, File } from '@voxgig/sdkgen'
3
+
4
+
5
+ // Generates ts/test/ReadmeExample.test.ts — a test that reads the
6
+ // repo's top-level README.md at runtime, extracts the first TS code
7
+ // block under "## Quickstart", transforms `new <Name>SDK(...)`
8
+ // to `<Name>SDK.test()` so it runs offline, evaluates the rest, and
9
+ // asserts no error. Catches drift between the README quickstart and
10
+ // the real SDK API.
11
+ const ReadmeExampleTest = cmp(function ReadmeExampleTest(props: any) {
12
+ const { ctx$: { model } } = props
13
+ const Name = model.const.Name
14
+
15
+ File({ name: 'ReadmeExample.test.ts' }, () => {
16
+ Content(`// Verifies the README's lead-language quickstart still runs.
17
+
18
+ import { describe, it } from 'node:test'
19
+ import assert from 'node:assert'
20
+ import * as Fs from 'node:fs'
21
+ import * as Path from 'node:path'
22
+
23
+ import { ${Name}SDK } from '..'
24
+
25
+
26
+ function findFirstTsBlock(md: string, sectionHeading: string): string | null {
27
+ const escapedHeading = sectionHeading.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&')
28
+ const re = new RegExp('##\\\\s+' + escapedHeading + '[\\\\s\\\\S]*?\`\`\`ts\\\\n([\\\\s\\\\S]*?)\`\`\`')
29
+ const m = md.match(re)
30
+ return m ? m[1] : null
31
+ }
32
+
33
+
34
+ function transformForTestMode(code: string, name: string): string {
35
+ // Strip import lines — symbols come from the test's outer scope.
36
+ let out = code.replace(/^\\s*import\\s+[^;\\n]+;?\\s*$/gm, '')
37
+ // Swap real client construction for test mode (no network, no auth).
38
+ out = out.replace(new RegExp('new\\\\s+' + name + 'SDK\\\\([^)]*\\\\)', 'g'), name + 'SDK.test()')
39
+ return out
40
+ }
41
+
42
+
43
+ describe('README example', () => {
44
+ it('lead-language quickstart runs in test mode', async () => {
45
+ const readmePath = Path.join(__dirname, '..', '..', 'README.md')
46
+ const md = Fs.readFileSync(readmePath, 'utf8')
47
+
48
+ const block = findFirstTsBlock(md, 'Quickstart')
49
+ assert(block, 'No TypeScript code block found under "## Quickstart" in README.md')
50
+
51
+ const code = transformForTestMode(block, '${Name}')
52
+
53
+ // Run the (transformed) example. Async, so wrap in AsyncFunction.
54
+ const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
55
+ const silentConsole = { log: () => {}, error: () => {}, warn: () => {} }
56
+ const runner = new AsyncFunction('${Name}SDK', 'console', code)
57
+
58
+ // The example should at least parse and have a valid call shape
59
+ // (every method exists on the SDK and accepts the args shown). A
60
+ // "Not found" / 404 from test mode means the SDK accepted the call
61
+ // but there's no fixture for that match — that's a test-data gap,
62
+ // not a README bug, so it's OK. Everything else (TypeError,
63
+ // ReferenceError, SyntaxError) means the README example is out of
64
+ // sync with the real SDK API and the test should fail.
65
+ try {
66
+ await runner(${Name}SDK, silentConsole)
67
+ } catch (err: any) {
68
+ const msg = String(err?.message ?? err)
69
+ if (/\\b(404|Not found)\\b/i.test(msg)) return
70
+ throw err
71
+ }
72
+ })
73
+ })
74
+ `)
75
+ })
76
+ })
77
+
78
+
79
+ export {
80
+ ReadmeExampleTest
81
+ }
@@ -0,0 +1,446 @@
1
+
2
+ import { cmp, Content, File } from '@voxgig/sdkgen'
3
+
4
+ import {
5
+ KIT,
6
+ getModelPath,
7
+ } from '@voxgig/apidef'
8
+
9
+
10
+ // Generates ts/test/readme_examples.test.ts — a COMPLETENESS GATE that
11
+ // guarantees every fenced \`\`\`ts code example across all THREE docs (the
12
+ // repo root README.md, this target's per-language README.md, and its
13
+ // REFERENCE.md) is unit-tested. Every block from every doc is:
14
+ //
15
+ // (1) TYPE-CHECKED against the real SDK types with the repo's local
16
+ // \`tsc --noEmit\`. To stay robust against tsc suppressing all semantic
17
+ // diagnostics program-wide whenever one file has a syntax error, blocks
18
+ // are compiled one-file-per-block in a fixpoint: compile the batch, drop
19
+ // the ones that error, recompile the rest, until a pass is clean — so a
20
+ // real type bug can never hide behind a neighbouring illustration's
21
+ // syntax error.
22
+ // (2) EXECUTED, if RUNNABLE (constructs \`new <Sdk>SDK\` / \`<Sdk>SDK.test\`
23
+ // or drives \`client.\`), by rewriting it to a seeded test-mode client
24
+ // and running it offline. A programming error (undefined method, wrong
25
+ // arity, bad symbol) fails; only a 404 / "Not found" domain error for an
26
+ // unseeded id is tolerated. This now runs for ALL THREE docs (previously
27
+ // only the root README executed).
28
+ // (3) PARTITIONED into exactly one of { executed, typechecked-only,
29
+ // illustration } with the counts asserted to sum to the total. A block
30
+ // that does NOT type-check is only allowed if it matches the NARROW
31
+ // illustration allowlist (bare method-signature \`?:\`, \`/* placeholder */\`
32
+ // value, or a type-SHAPE block). Any other non-type-checking block FAILS
33
+ // the test, quoting the block — it is NEVER silently skipped. A per-doc
34
+ // summary line makes the coverage visible in the test output.
35
+ const ReadmeExamplesTest = cmp(function ReadmeExamplesTest(props: any) {
36
+ const { ctx$: { model } } = props
37
+ const Name = model.const.Name
38
+
39
+ // Seed a fixture for every active entity so list()/load() resolve
40
+ // offline in test mode with no network. Keyed by the entity's model
41
+ // name (the same key the test-mode transport looks up).
42
+ const entity = getModelPath(model, `main.${KIT}.entity`)
43
+ const seedEntities: Record<string, any> = {}
44
+ Object.values(entity).forEach((e: any) => {
45
+ if (e && false !== e.active && 'string' === typeof e.name) {
46
+ seedEntities[e.name] = { test01: { id: 'test01' } }
47
+ }
48
+ })
49
+ const seedLiteral = JSON.stringify({ entity: seedEntities })
50
+
51
+ File({ name: 'readme_examples.test.ts' }, () => {
52
+ Content(`// Completeness gate over every TypeScript example in this SDK's docs.
53
+ //
54
+ // Covers all THREE documentation files — the repo root README.md, this
55
+ // target's README.md, and its REFERENCE.md. Every fenced \`\`\`ts block in
56
+ // every one is put through the same pipeline:
57
+ //
58
+ // (1) TYPE-CHECK — every block is compiled with the repo's local
59
+ // \`tsc --noEmit\` against the real SDK types. A block that misuses the
60
+ // SDK types (e.g. \`.data\` on a \`list()\` array, or a string id where a
61
+ // number is required) is a compile error.
62
+ // (2) EXECUTE — every RUNNABLE block (one that constructs the SDK or
63
+ // drives \`client.\`) is rewritten to seeded test mode, transpiled to
64
+ // JS, and run offline. A programming error (undefined method,
65
+ // wrong-arg-count, bad symbol) fails the test; only an expected domain
66
+ // error (a 404 / "Not found" for an unseeded id) is tolerated.
67
+ // (3) COMPLETENESS — every block is partitioned into exactly one of
68
+ // { executed, typechecked-only, illustration } and the counts must sum
69
+ // to the total. A block that does NOT type-check is allowed ONLY if it
70
+ // matches the NARROW illustration allowlist (a bare method signature
71
+ // \`?:\`, a \`/* placeholder */\` value, or a type-SHAPE block). Any other
72
+ // non-type-checking block FAILS the test, quoting the block — it is
73
+ // never silently skipped.
74
+ //
75
+ // Generated by @voxgig/sdkgen — do not edit by hand.
76
+
77
+ import { describe, it } from 'node:test'
78
+ import assert from 'node:assert'
79
+ import * as Fs from 'node:fs'
80
+ import * as Path from 'node:path'
81
+ import { createRequire } from 'node:module'
82
+ import { spawnSync } from 'node:child_process'
83
+
84
+ import { ${Name}SDK } from '..'
85
+
86
+
87
+ const SDK_NAME = '${Name}SDK'
88
+
89
+ // A fixture for every entity, so list()/load() resolve offline with no
90
+ // network. Snippet client construction is rewritten to seed this.
91
+ const TEST_SEED = ${seedLiteral}
92
+ const SEED_ARG = JSON.stringify(TEST_SEED)
93
+ const SEEDED_CTOR = SDK_NAME + '.test(' + SEED_ARG + ')'
94
+
95
+
96
+ // The three docs this gate covers, resolved relative to dist-test/.
97
+ const DOCS: Array<{ label: string; key: string; path: string }> = [
98
+ { label: 'root README.md', key: 'root_readme', path: Path.join(__dirname, '..', '..', 'README.md') },
99
+ { label: 'ts/README.md', key: 'lang_readme', path: Path.join(__dirname, '..', 'README.md') },
100
+ { label: 'ts/REFERENCE.md', key: 'reference', path: Path.join(__dirname, '..', 'REFERENCE.md') },
101
+ ]
102
+
103
+
104
+ // Pull out the body of every \`\`\`ts fenced code block.
105
+ function extractTsBlocks(md: string): string[] {
106
+ const blocks: string[] = []
107
+ const re = /\`\`\`ts\\n([\\s\\S]*?)\`\`\`/g
108
+ let m: RegExpExecArray | null
109
+ while ((m = re.exec(md)) !== null) {
110
+ blocks.push(m[1])
111
+ }
112
+ return blocks
113
+ }
114
+
115
+
116
+ // Snippet import lines reference the published package name, which is not
117
+ // resolvable from inside the repo; the SDK symbol is supplied by the one
118
+ // module-level import we emit / inject instead.
119
+ function stripImports(code: string): string {
120
+ return code.replace(/^\\s*import\\s+[^\\n]*$/gm, '')
121
+ }
122
+
123
+
124
+ // A block is an ILLUSTRATION shape — documentation, not runnable code — if
125
+ // it matches this NARROW allowlist. These are the ONLY shapes a
126
+ // non-type-checking block is allowed to be; anything else that fails to
127
+ // type-check is a real bug and fails the gate. Three shapes:
128
+ // 1. a bare method / constructor signature with a typed-parameter
129
+ // signature ("?:", e.g. \`options?: { base?: string }\`);
130
+ // 2. a placeholder-comment value ("/*", e.g. \`field: /* string */\`);
131
+ // 3. a type-SHAPE block that lists fields as \`name: TypeKeyword\` with the
132
+ // type standing alone as the value — e.g. the DirectResult / FetchDef
133
+ // shape \`{ ok: boolean; status: number; ... }\`. Those bare keywords
134
+ // are undeclared VALUES (TS2693 "only refers to a type"). Matched
135
+ // only at the START of a line, so a genuine annotation inside runnable
136
+ // code (e.g. \`(ctx: any) => ...\`) is NOT matched.
137
+ const SHAPE_ILLUSTRATION =
138
+ /^\\s*[A-Za-z_$][\\w$]*\\??\\s*:\\s*(?:boolean|number|string|object|any|unknown|never|void|symbol|bigint|Record<|Partial<|Array<|Map<|Set<)/m
139
+ function isIllustrationShape(code: string): boolean {
140
+ if (code.includes('?:')) {
141
+ return true
142
+ }
143
+ if (code.includes('/*')) {
144
+ return true
145
+ }
146
+ if (SHAPE_ILLUSTRATION.test(code)) {
147
+ return true
148
+ }
149
+ return false
150
+ }
151
+
152
+
153
+ // A block is RUNNABLE if it constructs the SDK (\`new <Sdk>SDK\` /
154
+ // \`<Sdk>SDK.test\`) or drives a \`client.\` — those are the blocks the execute
155
+ // gate rewrites to seeded test mode and runs.
156
+ function isRunnable(code: string): boolean {
157
+ return (
158
+ /new\\s+${Name}SDK\\b/.test(code) ||
159
+ /\\b${Name}SDK\\.test\\b/.test(code) ||
160
+ /\\bclient\\s*\\./.test(code)
161
+ )
162
+ }
163
+
164
+
165
+ // Wrap ONE block as a self-contained temp module: the block goes in its own
166
+ // scope inside an async function with a shared seeded \`client\`.
167
+ function buildSnippetModule(block: string): string {
168
+ const inner = stripImports(block).split('\\n').map((l) => ' ' + l).join('\\n')
169
+ return [
170
+ "import { " + SDK_NAME + " } from '..'",
171
+ '',
172
+ 'async function __ex() {',
173
+ // Shared client for snippets that reference \`client\` without constructing
174
+ // one (e.g. the direct() example).
175
+ ' const client = ' + SDK_NAME + '.test()',
176
+ ' void client',
177
+ ' {',
178
+ inner,
179
+ ' }',
180
+ '}',
181
+ 'void __ex',
182
+ '',
183
+ ].join('\\n')
184
+ }
185
+
186
+
187
+ // Compile a batch of blocks in ONE tsc pass — one temp file per block, so
188
+ // each is an isolated program entry — and return which snippet indices
189
+ // errored. NOTE: tsc suppresses ALL semantic diagnostics program-wide as
190
+ // soon as any file has a SYNTAX error, so a single batch cannot be trusted;
191
+ // \`typeCheckBlocks\` drives this in a fixpoint that removes erroring blocks
192
+ // and recompiles the rest until a pass is clean.
193
+ function compileBatch(indices: number[], blocks: string[], key: string): {
194
+ errored: Set<number>; raw: string; unattributed: boolean
195
+ } {
196
+ const tsDir = Path.join(__dirname, '..')
197
+ const testDir = Path.join(tsDir, 'test')
198
+ // Leading dot: TypeScript wildcard includes skip dot-files, so these temp
199
+ // files are never swept into the normal build.
200
+ const files: string[] = []
201
+
202
+ try {
203
+ for (const i of indices) {
204
+ const f = Path.join(testDir, '.examples_' + key + '_snippet' + i + '.gen.ts')
205
+ Fs.writeFileSync(f, buildSnippetModule(blocks[i]), 'utf8')
206
+ files.push(f)
207
+ }
208
+
209
+ const requireFrom = createRequire(__filename)
210
+ const tsc = requireFrom.resolve('typescript/bin/tsc')
211
+
212
+ const res = spawnSync(process.execPath, [
213
+ tsc,
214
+ '--noEmit',
215
+ '--strict',
216
+ '--pretty', 'false',
217
+ '--target', 'ES2022',
218
+ '--module', 'nodenext',
219
+ '--moduleResolution', 'nodenext',
220
+ '--esModuleInterop',
221
+ '--resolveJsonModule',
222
+ '--skipLibCheck',
223
+ '--types', 'node',
224
+ ...files,
225
+ ], { cwd: tsDir, encoding: 'utf8' })
226
+
227
+ const raw = ((res.stdout || '') + (res.stderr || '')).trim()
228
+ const errored = new Set<number>()
229
+ let unattributed = false
230
+
231
+ if (0 !== res.status) {
232
+ for (const line of raw.split('\\n')) {
233
+ const m = /_snippet(\\d+)\\.gen\\.ts\\(\\d+,\\d+\\):\\s*error/.exec(line)
234
+ if (null == m) {
235
+ // A genuine error diagnostic not attributable to a snippet file
236
+ // (e.g. inside the SDK itself) is an anomaly.
237
+ if (/:\\s*error\\s+TS\\d+/.test(line)) {
238
+ unattributed = true
239
+ }
240
+ continue
241
+ }
242
+ errored.add(parseInt(m[1], 10))
243
+ }
244
+ }
245
+
246
+ return { errored, raw, unattributed }
247
+ } finally {
248
+ for (const f of files) {
249
+ Fs.rmSync(f, { force: true })
250
+ }
251
+ }
252
+ }
253
+
254
+
255
+ // Determine, robustly, which of a doc's blocks fail to type-check. Because
256
+ // one syntax error suppresses semantic diagnostics for the whole batch, we
257
+ // iterate: compile the still-unresolved blocks, record the ones that
258
+ // errored, drop them, and recompile the rest — until a pass reports no
259
+ // errors. Each erroring pass strictly shrinks the working set, so this
260
+ // terminates. \`globalError\` flags an unattributable tsc error, surfaced
261
+ // verbatim by the caller.
262
+ function typeCheckBlocks(blocks: string[], key: string): {
263
+ failing: Set<number>; raw: string; globalError: boolean
264
+ } {
265
+ const failing = new Set<number>()
266
+ const raws: string[] = []
267
+ let globalError = false
268
+ let remaining = blocks.map((_b, i) => i)
269
+
270
+ // Guard: at most one pass per block plus a final clean pass.
271
+ for (let pass = 0; pass <= blocks.length && 0 < remaining.length; pass++) {
272
+ const { errored, raw, unattributed } = compileBatch(remaining, blocks, key)
273
+ raws.push(raw)
274
+ if (unattributed) {
275
+ globalError = true
276
+ }
277
+ if (0 === errored.size) {
278
+ break
279
+ }
280
+ for (const i of errored) {
281
+ failing.add(i)
282
+ }
283
+ remaining = remaining.filter((i) => !errored.has(i))
284
+ }
285
+
286
+ return { failing, raw: raws.filter(Boolean).join('\\n'), globalError }
287
+ }
288
+
289
+
290
+ // Turn a documented snippet into an offline-runnable one: strip imports,
291
+ // rewrite real client construction (\`new <Sdk>SDK(...)\` and any
292
+ // \`<Sdk>SDK.test(...)\`) to a seeded test-mode client, and give snippets
293
+ // that reference \`client\` without constructing one a shared seeded client.
294
+ function rewriteForRun(code: string): string {
295
+ let out = stripImports(code)
296
+ out = out.replace(/new\\s+${Name}SDK\\s*\\([^)]*\\)/g, () => SEEDED_CTOR)
297
+ out = out.replace(/${Name}SDK\\.test\\s*\\([^)]*\\)/g, () => SEEDED_CTOR)
298
+ if (/\\bclient\\b/.test(out) && !/\\b(?:const|let|var)\\s+client\\b/.test(out)) {
299
+ out = 'const client = ' + SEEDED_CTOR + '\\n' + out
300
+ }
301
+ return out
302
+ }
303
+
304
+
305
+ // Run every runnable, non-illustration block from a doc offline in seeded
306
+ // test mode. Returns a list of failure descriptions (empty === all passed).
307
+ async function executeBlocks(blocks: string[]): Promise<string[]> {
308
+ const requireFrom = createRequire(__filename)
309
+ const ts = requireFrom('typescript')
310
+
311
+ const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
312
+ const silentConsole = { log() {}, error() {}, warn() {}, info() {} }
313
+
314
+ const failures: string[] = []
315
+
316
+ for (let i = 0; i < blocks.length; i++) {
317
+ // Illustration shapes are documentation, not runnable code.
318
+ if (!isRunnable(blocks[i]) || isIllustrationShape(blocks[i])) {
319
+ continue
320
+ }
321
+
322
+ const src = rewriteForRun(blocks[i])
323
+ if ('' === src.trim()) {
324
+ continue
325
+ }
326
+
327
+ // Compile the snippet to JS (strips type annotations) so it runs under
328
+ // node exactly as a real caller would.
329
+ const js = ts.transpileModule(src, {
330
+ compilerOptions: {
331
+ target: ts.ScriptTarget.ES2020,
332
+ module: ts.ModuleKind.ESNext,
333
+ },
334
+ }).outputText
335
+
336
+ let runner: any
337
+ try {
338
+ runner = new AsyncFunction(SDK_NAME, 'console', js)
339
+ } catch (err: any) {
340
+ failures.push('snippet ' + i + ' failed to compile as runnable JS: ' +
341
+ String((err && err.message) || err))
342
+ continue
343
+ }
344
+
345
+ try {
346
+ await runner(${Name}SDK, silentConsole)
347
+ } catch (err: any) {
348
+ const msg = String((err && err.message) || err)
349
+ // Tolerate the one expected domain error: no fixture seeded for the
350
+ // requested id (a 404 / "Not found" from test mode). A programming
351
+ // error (undefined method/symbol, wrong arg count) is a real doc bug
352
+ // and is NOT tolerated.
353
+ if (/\\b(?:404|not found)\\b/i.test(msg)) {
354
+ continue
355
+ }
356
+ failures.push('snippet ' + i + ' threw at runtime: ' + msg)
357
+ }
358
+ }
359
+
360
+ return failures
361
+ }
362
+
363
+
364
+ function indentBlock(code: string): string {
365
+ return code.replace(/^/gm, ' ').replace(/\\s+$/, '')
366
+ }
367
+
368
+
369
+ describe('README examples', () => {
370
+ for (const doc of DOCS) {
371
+ it(doc.label + ' — every example type-checks or is a known illustration', () => {
372
+ // A target without this doc has nothing to check.
373
+ if (!Fs.existsSync(doc.path)) {
374
+ return
375
+ }
376
+ const md = Fs.readFileSync(doc.path, 'utf8')
377
+ const blocks = extractTsBlocks(md)
378
+ assert(blocks.length > 0, 'No TypeScript code blocks found in ' + doc.label)
379
+
380
+ const { failing, raw, globalError } = typeCheckBlocks(blocks, doc.key)
381
+ assert(!globalError,
382
+ 'tsc reported an error outside any snippet in ' + doc.label +
383
+ ' — the harness could not attribute it:\\n\\n' + raw + '\\n')
384
+
385
+ let executed = 0
386
+ let typecheckedOnly = 0
387
+ let illustration = 0
388
+ const unrecognized: string[] = []
389
+
390
+ blocks.forEach((b, i) => {
391
+ const typechecks = !failing.has(i)
392
+ const shape = isIllustrationShape(b)
393
+ const runnable = isRunnable(b) && !shape
394
+
395
+ if (!typechecks && shape) {
396
+ illustration++
397
+ } else if (!typechecks && !shape) {
398
+ unrecognized.push(' snippet ' + i + ':\\n' + indentBlock(b))
399
+ } else if (typechecks && runnable) {
400
+ executed++
401
+ } else {
402
+ typecheckedOnly++
403
+ }
404
+ })
405
+
406
+ // Emit the coverage summary FIRST so it is always visible, even when
407
+ // an assertion below fails.
408
+ console.log('README examples [' + doc.label + ']: total=' + blocks.length +
409
+ ' executed=' + executed + ' typechecked=' + typecheckedOnly +
410
+ ' illustration=' + illustration)
411
+
412
+ assert.strictEqual(unrecognized.length, 0,
413
+ 'These ' + doc.label + ' \`\`\`ts blocks neither type-check nor match the ' +
414
+ 'illustration allowlist. Fix the snippet (or the SDK), or — if it is ' +
415
+ 'genuinely illustrative — reshape it to the allowlist:\\n\\n' +
416
+ unrecognized.join('\\n\\n') + '\\n\\ntsc output:\\n' + raw + '\\n')
417
+
418
+ assert.strictEqual(blocks.length, executed + typecheckedOnly + illustration,
419
+ 'completeness partition mismatch for ' + doc.label + ': ' + blocks.length +
420
+ ' total != ' + executed + ' executed + ' + typecheckedOnly +
421
+ ' typechecked + ' + illustration + ' illustration')
422
+ })
423
+
424
+ it(doc.label + ' — every runnable example executes in test mode', async () => {
425
+ if (!Fs.existsSync(doc.path)) {
426
+ return
427
+ }
428
+ const md = Fs.readFileSync(doc.path, 'utf8')
429
+ const blocks = extractTsBlocks(md)
430
+ assert(blocks.length > 0, 'No TypeScript code blocks found in ' + doc.label)
431
+
432
+ const failures = await executeBlocks(blocks)
433
+ assert.strictEqual(failures.length, 0,
434
+ doc.label + ' runnable TypeScript snippets failed to run in test mode:\\n\\n' +
435
+ failures.join('\\n') + '\\n')
436
+ })
437
+ }
438
+ })
439
+ `)
440
+ })
441
+ })
442
+
443
+
444
+ export {
445
+ ReadmeExamplesTest
446
+ }
@@ -1,5 +1,5 @@
1
1
 
2
- import { cmp, Content } from '@voxgig/sdkgen'
2
+ import { cmp, Content, packageName } from '@voxgig/sdkgen'
3
3
 
4
4
 
5
5
  const ReadmeExplanation = cmp(function ReadmeExplanation(props: any) {
@@ -21,7 +21,7 @@ ${model.name}/
21
21
  Import the SDK from the package root:
22
22
 
23
23
  \`\`\`ts
24
- import { ${model.Name}SDK } from '${model.name}'
24
+ import { ${model.Name}SDK } from '${packageName(model, target.name)}'
25
25
  \`\`\`
26
26
 
27
27
  `)