@voxgig/sdkgen 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/bin/voxgig-sdkgen +2 -2
  2. package/dist/action/action.d.ts +2 -1
  3. package/dist/action/action.js +15 -9
  4. package/dist/action/action.js.map +1 -1
  5. package/dist/action/feature.js +6 -3
  6. package/dist/action/feature.js.map +1 -1
  7. package/dist/action/target.d.ts +7 -1
  8. package/dist/action/target.js +13 -6
  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 +193 -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 +11 -1
  53. package/dist/sdkgen.js +57 -18
  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.js +20 -11
  59. package/dist/utility.js.map +1 -1
  60. package/model/sdkgen.aontu +137 -0
  61. package/package.json +11 -5
  62. package/project/.sdk/model/target/go-cli.jsonic +47 -0
  63. package/project/.sdk/model/target/go-mcp.jsonic +41 -0
  64. package/project/.sdk/model/target/go.jsonic +9 -3
  65. package/project/.sdk/model/target/js.jsonic +13 -0
  66. package/project/.sdk/model/target/lua.jsonic +13 -0
  67. package/project/.sdk/model/target/php.jsonic +13 -0
  68. package/project/.sdk/model/target/py.jsonic +13 -0
  69. package/project/.sdk/model/target/rb.jsonic +13 -0
  70. package/project/.sdk/model/target/ts.jsonic +13 -0
  71. package/project/.sdk/src/cmp/go/EntityOperation_go.ts +1 -0
  72. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +197 -0
  73. package/project/.sdk/src/cmp/go/Entity_go.ts +2 -1
  74. package/project/.sdk/src/cmp/go/MainEntity_go.ts +6 -0
  75. package/project/.sdk/src/cmp/go/Main_go.ts +23 -3
  76. package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
  77. package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +18 -6
  78. package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +684 -0
  79. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
  80. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +48 -8
  81. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +11 -6
  82. package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +40 -1
  83. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +63 -17
  84. package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +4 -3
  85. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +124 -115
  86. package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +28 -15
  87. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +33 -9
  88. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +35 -5
  89. package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
  90. package/project/.sdk/src/cmp/go/Test_go.ts +5 -1
  91. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +21 -0
  92. package/project/.sdk/src/cmp/go/fragment/EntityCreateOp.fragment.go +11 -0
  93. package/project/.sdk/src/cmp/go/fragment/EntityListOp.fragment.go +11 -0
  94. package/project/.sdk/src/cmp/go/fragment/EntityLoadOp.fragment.go +11 -0
  95. package/project/.sdk/src/cmp/go/fragment/EntityRemoveOp.fragment.go +11 -0
  96. package/project/.sdk/src/cmp/go/fragment/EntityUpdateOp.fragment.go +11 -0
  97. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +195 -0
  98. package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +106 -0
  99. package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +132 -0
  100. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +184 -0
  101. package/project/.sdk/src/cmp/go-mcp/fragment/main.fragment.go +68 -0
  102. package/project/.sdk/src/cmp/go-mcp/fragment/tools.fragment.go +114 -0
  103. package/project/.sdk/src/cmp/js/EntityTypes_js.ts +111 -0
  104. package/project/.sdk/src/cmp/js/MainEntity_js.ts +1 -0
  105. package/project/.sdk/src/cmp/js/Main_js.ts +3 -0
  106. package/project/.sdk/src/cmp/js/Package_js.ts +16 -7
  107. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +13 -7
  108. package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +2 -2
  109. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +52 -11
  110. package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +39 -1
  111. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +50 -18
  112. package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +4 -3
  113. package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +45 -19
  114. package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +24 -13
  115. package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +3 -0
  116. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +28 -12
  117. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +23 -3
  118. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +5 -0
  119. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +5 -0
  120. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +5 -0
  121. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +5 -0
  122. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +5 -0
  123. package/project/.sdk/src/cmp/js/utility_js.ts +57 -0
  124. package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +113 -0
  125. package/project/.sdk/src/cmp/lua/MainEntity_lua.ts +8 -0
  126. package/project/.sdk/src/cmp/lua/Main_lua.ts +4 -0
  127. package/project/.sdk/src/cmp/lua/Package_lua.ts +23 -4
  128. package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +12 -10
  129. package/project/.sdk/src/cmp/lua/ReadmeExamplesTest_lua.ts +293 -0
  130. package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +46 -8
  131. package/project/.sdk/src/cmp/lua/ReadmeInstall_lua.ts +19 -3
  132. package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +38 -1
  133. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +51 -16
  134. package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +4 -3
  135. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +79 -18
  136. package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +25 -20
  137. package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +17 -9
  138. package/project/.sdk/src/cmp/lua/ReadmeTopTest_lua.ts +32 -5
  139. package/project/.sdk/src/cmp/lua/Test_lua.ts +4 -0
  140. package/project/.sdk/src/cmp/lua/fragment/EntityCreateOp.fragment.lua +4 -0
  141. package/project/.sdk/src/cmp/lua/fragment/EntityListOp.fragment.lua +4 -0
  142. package/project/.sdk/src/cmp/lua/fragment/EntityLoadOp.fragment.lua +4 -0
  143. package/project/.sdk/src/cmp/lua/fragment/EntityRemoveOp.fragment.lua +4 -0
  144. package/project/.sdk/src/cmp/lua/fragment/EntityUpdateOp.fragment.lua +4 -0
  145. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +142 -0
  146. package/project/.sdk/src/cmp/php/MainEntity_php.ts +18 -1
  147. package/project/.sdk/src/cmp/php/Main_php.ts +4 -0
  148. package/project/.sdk/src/cmp/php/Package_php.ts +18 -7
  149. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +15 -11
  150. package/project/.sdk/src/cmp/php/ReadmeExamplesTest_php.ts +401 -0
  151. package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +56 -13
  152. package/project/.sdk/src/cmp/php/ReadmeInstall_php.ts +15 -3
  153. package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +40 -1
  154. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +26 -8
  155. package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +4 -3
  156. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +80 -22
  157. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +51 -42
  158. package/project/.sdk/src/cmp/php/ReadmeTopHowto_php.ts +1 -1
  159. package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +19 -11
  160. package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +41 -11
  161. package/project/.sdk/src/cmp/php/TestDirect_php.ts +9 -9
  162. package/project/.sdk/src/cmp/php/TestEntity_php.ts +6 -12
  163. package/project/.sdk/src/cmp/php/Test_php.ts +4 -0
  164. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +13 -1
  165. package/project/.sdk/src/cmp/php/fragment/EntityCreateOp.fragment.php +10 -1
  166. package/project/.sdk/src/cmp/php/fragment/EntityListOp.fragment.php +10 -1
  167. package/project/.sdk/src/cmp/php/fragment/EntityLoadOp.fragment.php +10 -1
  168. package/project/.sdk/src/cmp/php/fragment/EntityRemoveOp.fragment.php +10 -1
  169. package/project/.sdk/src/cmp/php/fragment/EntityUpdateOp.fragment.php +10 -1
  170. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +22 -14
  171. package/project/.sdk/src/cmp/py/EntityTypes_py.ts +184 -0
  172. package/project/.sdk/src/cmp/py/Entity_py.ts +27 -0
  173. package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -1
  174. package/project/.sdk/src/cmp/py/Main_py.ts +35 -0
  175. package/project/.sdk/src/cmp/py/Package_py.ts +24 -3
  176. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +27 -11
  177. package/project/.sdk/src/cmp/py/ReadmeExamplesTest_py.ts +626 -0
  178. package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +53 -14
  179. package/project/.sdk/src/cmp/py/ReadmeInstall_py.ts +19 -3
  180. package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +48 -1
  181. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +28 -10
  182. package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +4 -3
  183. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +73 -24
  184. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +57 -37
  185. package/project/.sdk/src/cmp/py/ReadmeTopHowto_py.ts +1 -1
  186. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +19 -11
  187. package/project/.sdk/src/cmp/py/ReadmeTopTest_py.ts +30 -5
  188. package/project/.sdk/src/cmp/py/TestDirect_py.ts +7 -9
  189. package/project/.sdk/src/cmp/py/TestEntity_py.ts +6 -14
  190. package/project/.sdk/src/cmp/py/Test_py.ts +4 -0
  191. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +5 -2
  192. package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +1 -1
  193. package/project/.sdk/src/cmp/py/fragment/EntityListOp.fragment.py +5 -1
  194. package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +6 -1
  195. package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +6 -1
  196. package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +1 -1
  197. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +17 -10
  198. package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +136 -0
  199. package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +1 -0
  200. package/project/.sdk/src/cmp/rb/Main_rb.ts +4 -0
  201. package/project/.sdk/src/cmp/rb/Package_rb.ts +34 -7
  202. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +26 -10
  203. package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +289 -0
  204. package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +72 -21
  205. package/project/.sdk/src/cmp/rb/ReadmeInstall_rb.ts +16 -4
  206. package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +40 -1
  207. package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +29 -12
  208. package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +4 -3
  209. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +85 -22
  210. package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +56 -37
  211. package/project/.sdk/src/cmp/rb/ReadmeTopHowto_rb.ts +1 -1
  212. package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +19 -11
  213. package/project/.sdk/src/cmp/rb/ReadmeTopTest_rb.ts +43 -11
  214. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +9 -9
  215. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +6 -12
  216. package/project/.sdk/src/cmp/rb/Test_rb.ts +4 -0
  217. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +2 -0
  218. package/project/.sdk/src/cmp/rb/fragment/EntityCreateOp.fragment.rb +5 -0
  219. package/project/.sdk/src/cmp/rb/fragment/EntityListOp.fragment.rb +20 -2
  220. package/project/.sdk/src/cmp/rb/fragment/EntityLoadOp.fragment.rb +8 -1
  221. package/project/.sdk/src/cmp/rb/fragment/EntityRemoveOp.fragment.rb +6 -1
  222. package/project/.sdk/src/cmp/rb/fragment/EntityUpdateOp.fragment.rb +5 -0
  223. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +24 -8
  224. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +105 -0
  225. package/project/.sdk/src/cmp/ts/Entity_ts.ts +17 -1
  226. package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +1 -0
  227. package/project/.sdk/src/cmp/ts/Main_ts.ts +6 -0
  228. package/project/.sdk/src/cmp/ts/Package_ts.ts +14 -7
  229. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +13 -7
  230. package/project/.sdk/src/cmp/ts/ReadmeExampleTest_ts.ts +81 -0
  231. package/project/.sdk/src/cmp/ts/ReadmeExamplesTest_ts.ts +446 -0
  232. package/project/.sdk/src/cmp/ts/ReadmeExplanation_ts.ts +2 -2
  233. package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +57 -11
  234. package/project/.sdk/src/cmp/ts/ReadmeInstall_ts.ts +19 -6
  235. package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +39 -1
  236. package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +50 -18
  237. package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +4 -3
  238. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +95 -40
  239. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +24 -13
  240. package/project/.sdk/src/cmp/ts/ReadmeTopHowto_ts.ts +3 -0
  241. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +44 -12
  242. package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +23 -3
  243. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +2 -2
  244. package/project/.sdk/src/cmp/ts/Test_ts.ts +5 -0
  245. package/project/.sdk/src/cmp/ts/fragment/Entity.fragment.ts +3 -1
  246. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +10 -5
  247. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +4 -2
  248. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +4 -2
  249. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +4 -2
  250. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +4 -2
  251. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +4 -2
  252. package/project/.sdk/src/cmp/ts/utility_ts.ts +59 -0
  253. package/project/.sdk/tm/go/LICENSE +1 -1
  254. package/project/.sdk/tm/go/Makefile +36 -1
  255. package/project/.sdk/tm/go/VERSION +1 -0
  256. package/project/.sdk/tm/go/core/context.go +12 -7
  257. package/project/.sdk/tm/go-cli/src/feature/README.md +6 -0
  258. package/project/.sdk/tm/go-cli/src/feature/base/.gitkeep +0 -0
  259. package/project/.sdk/tm/go-cli/src/feature/log/.gitkeep +0 -0
  260. package/project/.sdk/tm/go-cli/src/feature/test/.gitkeep +0 -0
  261. package/project/.sdk/tm/go-mcp/src/feature/README.md +6 -0
  262. package/project/.sdk/tm/go-mcp/src/feature/base/.gitkeep +0 -0
  263. package/project/.sdk/tm/go-mcp/src/feature/log/.gitkeep +0 -0
  264. package/project/.sdk/tm/go-mcp/src/feature/test/.gitkeep +0 -0
  265. package/project/.sdk/tm/js/LICENSE +1 -1
  266. package/project/.sdk/tm/js/Makefile +41 -0
  267. package/project/.sdk/tm/lua/LICENSE +1 -1
  268. package/project/.sdk/tm/lua/Makefile +40 -1
  269. package/project/.sdk/tm/lua/core/context.lua +13 -8
  270. package/project/.sdk/tm/php/LICENSE +1 -1
  271. package/project/.sdk/tm/php/Makefile +31 -1
  272. package/project/.sdk/tm/php/VERSION +1 -0
  273. package/project/.sdk/tm/php/core/Context.php +12 -6
  274. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +13 -4
  275. package/project/.sdk/tm/php/utility/Done.php +2 -2
  276. package/project/.sdk/tm/php/utility/MakeError.php +3 -3
  277. package/project/.sdk/tm/py/LICENSE +1 -1
  278. package/project/.sdk/tm/py/Makefile +34 -1
  279. package/project/.sdk/tm/py/core/context.py +12 -7
  280. package/project/.sdk/tm/py/test/test_primary_utility.py +15 -4
  281. package/project/.sdk/tm/py/utility/done.py +3 -1
  282. package/project/.sdk/tm/py/utility/make_error.py +2 -2
  283. package/project/.sdk/tm/rb/LICENSE +1 -1
  284. package/project/.sdk/tm/rb/Makefile +33 -1
  285. package/project/.sdk/tm/rb/core/context.rb +8 -3
  286. package/project/.sdk/tm/rb/test/primary_utility_test.rb +2 -2
  287. package/project/.sdk/tm/rb/utility/done.rb +3 -1
  288. package/project/.sdk/tm/rb/utility/make_error.rb +5 -2
  289. package/project/.sdk/tm/ts/LICENSE +1 -1
  290. package/project/.sdk/tm/ts/Makefile +42 -0
  291. package/project/.sdk/tm/ts/src/Context.ts +8 -3
  292. package/src/action/action.ts +17 -10
  293. package/src/action/feature.ts +8 -6
  294. package/src/action/target.ts +17 -8
  295. package/src/cmp/Changelog.ts +34 -0
  296. package/src/cmp/Deploy.ts +258 -0
  297. package/src/cmp/FeatureHook.ts +6 -8
  298. package/src/cmp/License.ts +49 -0
  299. package/src/cmp/Readme.ts +2 -0
  300. package/src/cmp/ReadmeErrors.ts +257 -0
  301. package/src/cmp/ReadmeExplanation.ts +250 -230
  302. package/src/cmp/ReadmeModel.ts +7 -2
  303. package/src/cmp/ReadmeTop.ts +411 -95
  304. package/src/cmp/Security.ts +41 -0
  305. package/src/helpers/canonType.ts +89 -0
  306. package/src/helpers/collectDeps.ts +5 -3
  307. package/src/helpers/naming.ts +59 -0
  308. package/src/helpers/opExample.ts +170 -0
  309. package/src/helpers/opShape.ts +236 -0
  310. package/src/helpers/packageMeta.ts +236 -0
  311. package/src/sdkgen.ts +87 -20
  312. package/src/tsconfig.json +1 -0
  313. package/src/types.ts +85 -2
  314. package/src/utility.ts +22 -11
  315. package/README.md +0 -2
  316. package/dist/action/lang.d.ts +0 -2
  317. package/dist/action/lang.js +0 -68
  318. package/dist/action/lang.js.map +0 -1
  319. package/dist/cmp/Hook.d.ts +0 -2
  320. package/dist/cmp/Hook.js +0 -10
  321. package/dist/cmp/Hook.js.map +0 -1
  322. package/dist/cmp/Top.d.ts +0 -2
  323. package/dist/cmp/Top.js +0 -23
  324. package/dist/cmp/Top.js.map +0 -1
  325. package/dist/prepare-openapi.d.ts +0 -2
  326. package/dist/prepare-openapi.js +0 -37
  327. package/dist/prepare-openapi.js.map +0 -1
  328. package/model/sdkgen.jsonic +0 -74
  329. package/project/.sdk/tm/go/utility/struct/go.mod +0 -3
@@ -0,0 +1,401 @@
1
+
2
+ import { cmp, File, Content } from '@voxgig/sdkgen'
3
+
4
+ import {
5
+ KIT,
6
+ getModelPath,
7
+ } from '@voxgig/apidef'
8
+
9
+
10
+ // Emits test/ReadmeExamplesTest.php — a PHPUnit COMPLETENESS GATE that
11
+ // guarantees every fenced php code example in the package docs is unit-tested.
12
+ // It reads ALL THREE docs — the root (multi-language) ../../README.md, the
13
+ // PHP-specific ../README.md, and ../REFERENCE.md — extracts every fenced php
14
+ // block (tagged by source doc + index) and enforces four properties:
15
+ //
16
+ // 1. SYNTAX — `php -l` on every block (a leading <?php is prepended when the
17
+ // snippet omits one). Every documented example must parse.
18
+ // 2. RUN — every RUNNABLE block (one that constructs the SDK, drives
19
+ // $client->, or performs an entity op) is EXECUTED offline in seeded test
20
+ // mode against the real SDK. The captured stdout+stderr is scanned for
21
+ // FATAL programming-error markers REGARDLESS of exit code, so a bug that a
22
+ // documented try/catch swallows and echoes via getMessage() is still
23
+ // caught. Only a not-found / domain error is tolerated.
24
+ // 3. COMPLETENESS — every block is partitioned into exactly one of
25
+ // {executed, syntaxchecked-nonrunnable, illustration} and the counts must
26
+ // sum to the total. "illustration" is a NARROW explicit class (a
27
+ // signature / method-table block that names the SDK class or a documented
28
+ // method but never uses a live client) — never a catch-all. A
29
+ // runnable-looking block that was NOT executed lands in neither bucket and
30
+ // FAILS the gate: no runnable example can be silently skipped.
31
+ // 4. A per-doc summary (total / executed / syntaxchecked / illustration) is
32
+ // printed to STDERR.
33
+ //
34
+ // A runnable block is rewritten so its client is a test-mode client
35
+ // (<Sdk>SDK::test) seeded with an in-memory fixture for every entity it
36
+ // references; any real constructor is rewritten and the doc's own require of
37
+ // the SDK file is stripped (we require it by absolute path). A block that only
38
+ // *uses* $client (constructed in an earlier fenced block) gets a test client
39
+ // prepended.
40
+ //
41
+ // The emitted PHP builds the ``` fence via chr(96) so this generator string
42
+ // contains no backticks of its own.
43
+ const ReadmeExamplesTest = cmp(function ReadmeExamplesTest(props: any) {
44
+ const { target } = props
45
+ const { model } = props.ctx$
46
+
47
+ const sdkbase = model.const.Name.toLowerCase() + '_sdk'
48
+ const sdkfile = sdkbase + '.php'
49
+
50
+ // Entity accessor ($client->Name()) => fixture storage key (lowercase name),
51
+ // derived from the model so fixtures seed under the key the mock expects.
52
+ const entity = getModelPath(model, `main.${KIT}.entity`) || {}
53
+ const entityLines = Object.values(entity)
54
+ .filter((e: any) => e && e.active !== false)
55
+ .map((e: any) => ` ${JSON.stringify(e.Name)} => ${JSON.stringify(e.name)},`)
56
+ .join('\n')
57
+
58
+ File({ name: 'ReadmeExamplesTest.' + target.ext }, () => {
59
+ Content(`<?php
60
+ declare(strict_types=1);
61
+
62
+ // ${model.const.Name} SDK — documentation example COMPLETENESS GATE.
63
+ //
64
+ // Guarantees every fenced php code example across ALL THREE package docs is
65
+ // unit-tested. Reads the root ../../README.md, the PHP ../README.md, and
66
+ // ../REFERENCE.md, extracts every fenced php block (tagged by source doc +
67
+ // index) and enforces:
68
+ //
69
+ // 1. SYNTAX — 'php -l' on every block (a leading <?php is prepended when the
70
+ // snippet omits one). Every documented php example must parse.
71
+ // 2. RUN — every RUNNABLE block (one that constructs the SDK, drives
72
+ // \\$client->, or performs an entity op load/list/create/update/remove) is
73
+ // EXECUTED offline in seeded test mode (${model.const.Name}SDK::test)
74
+ // against the real SDK. The captured output is scanned for a real
75
+ // PHP-level error (undefined method, wrong-arg-count, TypeError, ...)
76
+ // REGARDLESS of exit code, so a bug a documented try/catch swallows and
77
+ // echoes cannot slip through. Expected not-found domain errors are
78
+ // tolerated.
79
+ // 3. COMPLETENESS — every block is partitioned into exactly one of
80
+ // {executed, syntaxchecked-nonrunnable, illustration}; the counts must sum
81
+ // to the total. A runnable-looking block that was not executed belongs to
82
+ // no bucket and FAILS the gate.
83
+ //
84
+ // PHP is dynamically typed, so syntax + actually running every example is the
85
+ // strongest check available without a live server.
86
+
87
+ require_once __DIR__ . '/../${sdkfile}';
88
+
89
+ use PHPUnit\\Framework\\TestCase;
90
+
91
+ class ReadmeExamplesTest extends TestCase
92
+ {
93
+ private const SDK_CLASS = '${model.const.Name}SDK';
94
+
95
+ // SDK file basename (no extension) — used to strip the doc's own require of
96
+ // the SDK file from a runnable block (we require it by absolute path).
97
+ private const SDK_BASE = '${sdkbase}';
98
+
99
+ // Entity accessor (\\$client->Name()) => fixture storage key (lowercase name).
100
+ private const ENTITIES = [
101
+ ${entityLines}
102
+ ];
103
+
104
+ // Documented SDK method names — used only to recognise the NARROW
105
+ // signature/method-table "illustration" class.
106
+ private const METHODS = [
107
+ 'options_map', 'get_utility', 'prepare', 'direct',
108
+ 'data_get', 'data_set', 'match_get', 'match_set', 'make', 'get_name',
109
+ ];
110
+
111
+ // PHP-level errors that indicate a real bug in a documented example (as
112
+ // opposed to an expected not-found / domain error, which is tolerated).
113
+ private const FATAL = '/(Call to undefined method|Call to undefined function|Call to a member function|ArgumentCountError|Too few arguments|Undefined constant|Uncaught TypeError)/';
114
+
115
+ // The three documentation sources this gate covers.
116
+ private function docs(): array
117
+ {
118
+ return [
119
+ 'root README' => __DIR__ . '/../../README.md',
120
+ 'php README' => __DIR__ . '/../README.md',
121
+ 'php REFERENCE' => __DIR__ . '/../REFERENCE.md',
122
+ ];
123
+ }
124
+
125
+ /**
126
+ * Extract every fenced php block from all three docs, each tagged with its
127
+ * source doc label and its index within that doc.
128
+ */
129
+ private function phpBlocks(): array
130
+ {
131
+ $fence = str_repeat(chr(96), 3);
132
+ $pattern = '/' . $fence . 'php\\r?\\n(.*?)' . $fence . '/s';
133
+ $blocks = [];
134
+ foreach ($this->docs() as $label => $path) {
135
+ $this->assertFileExists($path, 'missing documentation source: ' . $label);
136
+ preg_match_all($pattern, file_get_contents($path), $m);
137
+ foreach ($m[1] as $i => $b) {
138
+ $blocks[] = ['doc' => $label, 'n' => $i, 'code' => $b];
139
+ }
140
+ }
141
+ return $blocks;
142
+ }
143
+
144
+ // --- classification -----------------------------------------------------
145
+
146
+ /**
147
+ * A block is RUNNABLE when it constructs the SDK, drives \\$client->, or
148
+ * performs an entity operation. Every runnable block MUST be executed.
149
+ */
150
+ private function isRunnable(string $b): bool
151
+ {
152
+ $cls = preg_quote(self::SDK_CLASS, '/');
153
+ return preg_match('/new\\s+' . $cls . '\\b/', $b) === 1
154
+ || preg_match('/' . $cls . '::test\\b/', $b) === 1
155
+ || preg_match('/\\$client\\s*->/', $b) === 1
156
+ || preg_match('/->\\s*(?:load|list|create|update|remove)\\s*\\(/', $b) === 1;
157
+ }
158
+
159
+ /**
160
+ * A block "mentions the SDK" when it references the client variable, the SDK
161
+ * class, an entity accessor, or an entity operation. A non-runnable block
162
+ * that mentions the SDK but is not a signature illustration is an uncovered
163
+ * runnable-looking block and must fail the completeness gate.
164
+ */
165
+ private function looksSdk(string $b): bool
166
+ {
167
+ if (preg_match('/\\$client\\b/', $b) === 1) {
168
+ return true;
169
+ }
170
+ if (preg_match('/\\b' . preg_quote(self::SDK_CLASS, '/') . '\\b/', $b) === 1) {
171
+ return true;
172
+ }
173
+ if (preg_match('/->\\s*(?:load|list|create|update|remove)\\b/', $b) === 1) {
174
+ return true;
175
+ }
176
+ foreach (array_keys(self::ENTITIES) as $name) {
177
+ if (preg_match('/->\\s*' . preg_quote($name, '/') . '\\s*\\(/', $b) === 1) {
178
+ return true;
179
+ }
180
+ }
181
+ return false;
182
+ }
183
+
184
+ /**
185
+ * NARROW illustration class: a non-runnable block that references the SDK
186
+ * class or a documented method NAME as a signature / method-table, and never
187
+ * uses a live client variable. This is an explicit, restricted class — not a
188
+ * catch-all — so an unexecuted block that uses \\$client cannot hide here.
189
+ */
190
+ private function isIllustration(string $b): bool
191
+ {
192
+ if ($this->isRunnable($b)) {
193
+ return false;
194
+ }
195
+ if (preg_match('/\\$client\\b/', $b) === 1) {
196
+ return false;
197
+ }
198
+ if (preg_match('/\\b' . preg_quote(self::SDK_CLASS, '/') . '\\b/', $b) === 1) {
199
+ return true;
200
+ }
201
+ foreach (self::METHODS as $meth) {
202
+ if (preg_match('/\\b' . preg_quote($meth, '/') . '\\s*\\(/', $b) === 1) {
203
+ return true;
204
+ }
205
+ }
206
+ return false;
207
+ }
208
+
209
+ /** Partition label for a block: exactly one of the four. */
210
+ private function classify(string $b): string
211
+ {
212
+ if ($this->isRunnable($b)) {
213
+ return 'executed';
214
+ }
215
+ if ($this->isIllustration($b)) {
216
+ return 'illustration';
217
+ }
218
+ if (!$this->looksSdk($b)) {
219
+ return 'syntaxchecked_nonrunnable';
220
+ }
221
+ return 'unclassified';
222
+ }
223
+
224
+ // --- tests --------------------------------------------------------------
225
+
226
+ public function test_docs_have_php_examples(): void
227
+ {
228
+ $this->assertNotEmpty($this->phpBlocks(), 'docs should contain php examples');
229
+ }
230
+
231
+ /** Every php block across all three docs must parse (php -l). */
232
+ public function test_php_snippets_have_valid_syntax(): void
233
+ {
234
+ $failures = [];
235
+ foreach ($this->phpBlocks() as $blk) {
236
+ $block = $blk['code'];
237
+ $code = preg_match('/^\\s*<\\?php/', $block) ? $block : "<?php\\n" . $block;
238
+ $tmp = tempnam(sys_get_temp_dir(), 'readme_php_') . '.php';
239
+ file_put_contents($tmp, $code);
240
+ $out = [];
241
+ $rc = 0;
242
+ exec('php -l ' . escapeshellarg($tmp) . ' 2>&1', $out, $rc);
243
+ @unlink($tmp);
244
+ if ($rc !== 0) {
245
+ $failures[] = $blk['doc'] . ' #' . $blk['n'] . ":\\n" . implode("\\n", $out) . "\\n" . $block;
246
+ }
247
+ }
248
+ $this->assertSame([], $failures, "docs php blocks with syntax errors:\\n" . implode("\\n\\n", $failures));
249
+ }
250
+
251
+ /**
252
+ * Build the SDK 'entity' fixture option for the entities a block references,
253
+ * falling back to seeding all entities when none are named.
254
+ */
255
+ private function fixturesFor(string $block): array
256
+ {
257
+ $refs = [];
258
+ foreach (self::ENTITIES as $name => $storage) {
259
+ if (preg_match('/\\$client->' . preg_quote($name, '/') . '\\b/', $block)) {
260
+ $refs[$storage] = ["test01" => ["id" => "test01"]];
261
+ }
262
+ }
263
+ if (empty($refs)) {
264
+ foreach (self::ENTITIES as $storage) {
265
+ $refs[$storage] = ["test01" => ["id" => "test01"]];
266
+ }
267
+ }
268
+ return ["entity" => $refs];
269
+ }
270
+
271
+ /**
272
+ * Rewrite a runnable block into an executable offline test-mode program: the
273
+ * doc's own require of the SDK file is stripped (we require it by absolute
274
+ * path); any real client constructor (new <Sdk>SDK / <Sdk>SDK::test) becomes
275
+ * <Sdk>SDK::test(<fixtures>); a block that only uses \\$client gets such a
276
+ * constructor prepended. (The constructor arg-list match is deliberately
277
+ * shallow — it does not span nested parens — because runnable op blocks
278
+ * never build a client inline with a closure argument.)
279
+ */
280
+ private function toRunner(string $block, string $sdk): string
281
+ {
282
+ $cls = self::SDK_CLASS;
283
+ $fixtures = var_export($this->fixturesFor($block), true);
284
+ $body = preg_replace('/^\\s*<\\?php\\s*/', '', $block);
285
+ // Drop the doc's own require of the SDK file; we require it by absolute path.
286
+ $body = preg_replace(
287
+ '/^[ \\t]*require(?:_once)?[^\\n]*' . preg_quote(self::SDK_BASE, '/') . '[^\\n]*\\r?\\n?/mi',
288
+ '',
289
+ $body
290
+ );
291
+ $ctorRe = '/(?:new\\s+' . preg_quote($cls, '/') . '|' . preg_quote($cls, '/') . '::test)(?:\\([^()]*\\))?/';
292
+ if (preg_match($ctorRe, $body)) {
293
+ $body = preg_replace_callback($ctorRe, function () use ($cls, $fixtures) {
294
+ return $cls . '::test(' . $fixtures . ')';
295
+ }, $body);
296
+ } else {
297
+ $body = '$client = ' . $cls . '::test(' . $fixtures . ");\\n" . $body;
298
+ }
299
+ return "<?php\\nrequire_once " . var_export($sdk, true) . ";\\n" . $body;
300
+ }
301
+
302
+ /**
303
+ * Every RUNNABLE block is executed offline in test mode and must not raise a
304
+ * real PHP-level error — even one an error-handling example swallows in a
305
+ * catch (Throwable) and echoes via getMessage(): the captured output is
306
+ * scanned for FATAL either way, so a programming error in a documented
307
+ * try/catch cannot slip through. Expected domain errors (e.g. "404: Not
308
+ * found") never match FATAL, so caught not-found cases stay tolerated.
309
+ */
310
+ public function test_php_examples_run_offline(): void
311
+ {
312
+ $ran = 0;
313
+ $failures = [];
314
+ $sdk = __DIR__ . '/../${sdkfile}';
315
+ foreach ($this->phpBlocks() as $blk) {
316
+ if (!$this->isRunnable($blk['code'])) {
317
+ continue;
318
+ }
319
+ $ran++;
320
+ $runner = $this->toRunner($blk['code'], $sdk);
321
+ $tmp = tempnam(sys_get_temp_dir(), 'readme_run_') . '.php';
322
+ file_put_contents($tmp, $runner);
323
+ $out = [];
324
+ $rc = 0;
325
+ exec('php ' . escapeshellarg($tmp) . ' 2>&1', $out, $rc);
326
+ @unlink($tmp);
327
+ $text = implode("\\n", $out);
328
+ if (preg_match(self::FATAL, $text) === 1) {
329
+ $failures[] = $blk['doc'] . ' #' . $blk['n'] . ' (exit ' . $rc . "):\\n" . $text . "\\n" . $blk['code'];
330
+ }
331
+ }
332
+ $this->assertGreaterThan(0, $ran, 'expected at least one runnable example to execute');
333
+ $this->assertSame([], $failures, "docs php examples raised a real error when run offline:\\n" . implode("\\n\\n", $failures));
334
+ }
335
+
336
+ /**
337
+ * COMPLETENESS GATE: every fenced php block is partitioned into exactly one
338
+ * of {executed, syntaxchecked-nonrunnable, illustration}. The three counts
339
+ * must sum to the total. A block that references the SDK but is neither
340
+ * runnable (so not executed) nor a narrow signature illustration is
341
+ * "unclassified" — a runnable-looking example that would be silently skipped
342
+ * — and fails the gate.
343
+ */
344
+ public function test_php_examples_are_completely_classified(): void
345
+ {
346
+ $blocks = $this->phpBlocks();
347
+ $buckets = [
348
+ 'executed' => [],
349
+ 'syntaxchecked_nonrunnable' => [],
350
+ 'illustration' => [],
351
+ 'unclassified' => [],
352
+ ];
353
+ $perDoc = [];
354
+ foreach ($blocks as $blk) {
355
+ $cls = $this->classify($blk['code']);
356
+ $buckets[$cls][] = $blk;
357
+ $doc = $blk['doc'];
358
+ if (!isset($perDoc[$doc])) {
359
+ $perDoc[$doc] = ['total' => 0, 'executed' => 0, 'syntaxchecked_nonrunnable' => 0, 'illustration' => 0, 'unclassified' => 0];
360
+ }
361
+ $perDoc[$doc]['total']++;
362
+ $perDoc[$doc][$cls]++;
363
+ }
364
+
365
+ $summary = "ReadmeExamplesTest — php example coverage:\\n";
366
+ foreach ($perDoc as $doc => $c) {
367
+ $summary .= sprintf(
368
+ " %-14s total=%d executed=%d syntaxchecked=%d illustration=%d%s\\n",
369
+ $doc, $c['total'], $c['executed'], $c['syntaxchecked_nonrunnable'], $c['illustration'],
370
+ $c['unclassified'] > 0 ? ' UNCLASSIFIED=' . $c['unclassified'] : ''
371
+ );
372
+ }
373
+ fwrite(STDERR, "\\n" . $summary);
374
+
375
+ $unclassified = array_map(
376
+ function ($b) { return $b['doc'] . ' #' . $b['n'] . ":\\n" . $b['code']; },
377
+ $buckets['unclassified']
378
+ );
379
+ $this->assertSame([], $unclassified,
380
+ "runnable-looking php blocks that were neither executed nor a signature illustration:\\n"
381
+ . implode("\\n\\n", $unclassified));
382
+
383
+ $total = count($blocks);
384
+ $sum = count($buckets['executed'])
385
+ + count($buckets['syntaxchecked_nonrunnable'])
386
+ + count($buckets['illustration']);
387
+ $this->assertSame($total, $sum,
388
+ "every php block must be executed, syntaxchecked-nonrunnable, or illustration.\\n" . $summary);
389
+
390
+ $this->assertGreaterThan(0, count($buckets['executed']),
391
+ 'expected at least one executed php example');
392
+ }
393
+ }
394
+ `)
395
+ })
396
+ })
397
+
398
+
399
+ export {
400
+ ReadmeExamplesTest
401
+ }
@@ -1,12 +1,50 @@
1
1
 
2
- import { cmp, Content, isAuthActive } from '@voxgig/sdkgen'
2
+ import { cmp, Content, isAuthActive, envName, canonKey, entityIdField, entityPrimaryOp, opRequestShape } from '@voxgig/sdkgen'
3
+
4
+ import { KIT, getModelPath, nom } from '@voxgig/apidef'
5
+
6
+
7
+ // A type-correct PHP literal for a field's canonical type.
8
+ function phpLit(type: any): string {
9
+ const k = canonKey(type)
10
+ if ('INTEGER' === k || 'NUMBER' === k) return '1'
11
+ if ('BOOLEAN' === k) return 'true'
12
+ if ('ARRAY' === k || 'OBJECT' === k) return '[]'
13
+ return '"example"'
14
+ }
3
15
 
4
16
 
5
17
  const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
6
18
  const { target, ctx$: { model } } = props
7
19
 
20
+ const entity = getModelPath(model, `main.${KIT}.entity`)
21
+ const exampleEntity = Object.values(entity || {}).find((e: any) => e && e.active !== false) as any
22
+ const eName = exampleEntity ? nom(exampleEntity, 'Name') : 'Entity'
23
+ // Model-driven id key: null when the entity has no id-like field.
24
+ const idF = exampleEntity ? entityIdField(exampleEntity) : null
25
+ // Drive the test-mode example off the entity's PRIMARY op — never a hardcoded
26
+ // `load` a create-only entity lacks.
27
+ const primaryOp = exampleEntity ? (entityPrimaryOp(exampleEntity) || 'load') : 'load'
28
+ const isMatchOp = 'load' === primaryOp || 'remove' === primaryOp
29
+ const seedSentence = idF
30
+ ? '. Seed fixture\ndata via the `entity` option so offline calls resolve without a live server'
31
+ : ''
32
+ const testCtor = idF
33
+ ? `${model.const.Name}SDK::test([\n "entity" => ["${eName.toLowerCase()}" => ["test01" => ["${idF}" => "test01"]]],\n])`
34
+ : `${model.const.Name}SDK::test()`
35
+ let testCallArg = ''
36
+ if (exampleEntity && isMatchOp) {
37
+ testCallArg = idF ? `["${idF}" => "test01"]` : ''
38
+ } else if (exampleEntity && ('create' === primaryOp || 'update' === primaryOp)) {
39
+ const items = opRequestShape(exampleEntity, primaryOp).items
40
+ .filter((it: any) => it.name !== idF && it.name !== 'id')
41
+ const required = items.filter((it: any) => !it.optional)
42
+ const chosen = required.length ? required : items.slice(0, 3)
43
+ testCallArg = `[${chosen.map((it: any) => `"${it.name}" => ${phpLit(it.type)}`).join(', ')}]`
44
+ }
45
+
8
46
  const apikeyEnvLine = isAuthActive(model)
9
- ? `\n${model.NAME}_APIKEY=<your-key>`
47
+ ? `\n${envName(model)}_APIKEY=<your-key>`
10
48
  : ''
11
49
 
12
50
  Content(`### Make a direct HTTP request
@@ -14,28 +52,34 @@ const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
14
52
  For endpoints not covered by entity methods:
15
53
 
16
54
  \`\`\`php
17
- [$result, $err] = $client->direct([
55
+ // direct() is the raw-HTTP escape hatch: it returns a result array
56
+ // (it does not throw). Branch on $result["ok"].
57
+ $result = $client->direct([
18
58
  "path" => "/api/resource/{id}",
19
59
  "method" => "GET",
20
60
  "params" => ["id" => "example"],
21
61
  ]);
22
- if ($err) { throw new \\Exception($err); }
23
62
 
24
63
  if ($result["ok"]) {
25
64
  echo $result["status"]; // 200
26
65
  print_r($result["data"]); // response body
66
+ } else {
67
+ // On an HTTP error status there is no err (only a transport failure sets
68
+ // it), so fall back to the status code.
69
+ $err = $result["err"] ?? null;
70
+ echo "Error: " . ($err ? $err->getMessage() : "HTTP " . $result["status"]);
27
71
  }
28
72
  \`\`\`
29
73
 
30
74
  ### Prepare a request without sending it
31
75
 
32
76
  \`\`\`php
33
- [$fetchdef, $err] = $client->prepare([
77
+ // prepare() throws on error and returns the fetch definition.
78
+ $fetchdef = $client->prepare([
34
79
  "path" => "/api/resource/{id}",
35
80
  "method" => "DELETE",
36
81
  "params" => ["id" => "example"],
37
82
  ]);
38
- if ($err) { throw new \\Exception($err); }
39
83
 
40
84
  echo $fetchdef["url"];
41
85
  echo $fetchdef["method"];
@@ -44,15 +88,14 @@ print_r($fetchdef["headers"]);
44
88
 
45
89
  ### Use test mode
46
90
 
47
- Create a mock client for unit testing — no server required:
91
+ Create a mock client for unit testing — no server required${seedSentence}:
48
92
 
49
93
  \`\`\`php
50
- $client = ${model.const.Name}SDK::test(null, null);
94
+ $client = ${testCtor};
51
95
 
52
- [$result, $err] = $client->${model.const.Name}(null)->load(
53
- ["id" => "test01"], null
54
- );
55
- // $result contains mock response data
96
+ // Entity ops return the bare mock record (throws on error).
97
+ $${eName.toLowerCase()} = $client->${eName}()->${primaryOp}(${testCallArg});
98
+ print_r($${eName.toLowerCase()});
56
99
  \`\`\`
57
100
 
58
101
  ### Use a custom fetch function
@@ -85,7 +128,7 @@ $client = new ${model.const.Name}SDK([
85
128
  Create a \`.env.local\` file at the project root:
86
129
 
87
130
  \`\`\`
88
- ${model.NAME}_TEST_LIVE=TRUE${apikeyEnvLine}
131
+ ${envName(model)}_TEST_LIVE=TRUE${apikeyEnvLine}
89
132
  \`\`\`
90
133
 
91
134
  Then run:
@@ -1,15 +1,27 @@
1
1
 
2
- import { cmp, Content } from '@voxgig/sdkgen'
2
+ import { cmp, Content, installCommand, isPublished, repoInfo } from '@voxgig/sdkgen'
3
3
 
4
4
 
5
5
  const ReadmeInstall = cmp(function ReadmeInstall(props: any) {
6
6
  const { target, ctx$ } = props
7
7
  const { model } = ctx$
8
8
 
9
- Content(`\`\`\`bash
10
- composer require voxgig/${model.name}-sdk
9
+ if (isPublished(model, target.name)) {
10
+ Content(`\`\`\`bash
11
+ ${installCommand(model, target.name)}
11
12
  \`\`\`
12
13
 
14
+ `)
15
+ return
16
+ }
17
+
18
+ // Publish pending: not yet on Packagist. Install from the git release tag.
19
+ const { releasesUrl } = repoInfo(model)
20
+ Content(`This package is not yet published to Packagist. Install it from the
21
+ GitHub release tag (\`${target.name}/vX.Y.Z\`):
22
+
23
+ - Releases: [${releasesUrl}](${releasesUrl})
24
+
13
25
  `)
14
26
  })
15
27
 
@@ -1,13 +1,52 @@
1
1
 
2
2
  import { cmp, Content } from '@voxgig/sdkgen'
3
3
 
4
+ import {
5
+ KIT,
6
+ getModelPath,
7
+ nom,
8
+ } from '@voxgig/apidef'
9
+
4
10
 
5
11
  const ReadmeIntro = cmp(function ReadmeIntro(props: any) {
6
12
  const { target, ctx$: { model } } = props
13
+ const info = (model.main && model.main.kit && model.main.kit.info) || {}
14
+ const tagline = info.tagline || ''
15
+
16
+ // Derive a representative entity (and its operations) from the model so the
17
+ // semantic-entity pitch names something real rather than a placeholder.
18
+ const entity = getModelPath(model, `main.${KIT}.entity`) || {}
19
+ const exampleEntity = Object.values(entity).find((e: any) => e && e.active !== false) as any
20
+ const eName = exampleEntity ? nom(exampleEntity, 'Name') : null
21
+ // Model-driven op list — union of the operations the active entities
22
+ // actually expose (a read-only entity has just list+load), in canonical
23
+ // order; never claim create/update/remove exist when no entity has them.
24
+ const CANON_OPS = ['list', 'load', 'create', 'update', 'remove']
25
+ const opSet = new Set<string>()
26
+ Object.values(entity || {}).forEach((e: any) => {
27
+ if (!e || e.active === false) return
28
+ Object.keys(e.op || {}).forEach((o: string) => {
29
+ if (e.op[o] && e.op[o].active !== false) opSet.add(o)
30
+ })
31
+ })
32
+ const opnames = CANON_OPS.filter((o) => opSet.has(o))
33
+ .concat([...opSet].filter((o) => !CANON_OPS.includes(o)))
34
+ const opList = (opnames.length > 0 ? opnames : ['list', 'load']).join('`/`')
35
+
36
+ const semantic = eName
37
+ ? `The SDK exposes the API as capitalised, semantic **Entities** — for example \`$client->${eName}()\` — with named operations (\`${opList}\`) instead of raw URL paths and query strings. Working with resources and verbs keeps call sites self-describing and reduces cognitive load.
38
+
39
+ `
40
+ : ''
7
41
 
8
42
  Content(`# ${model.Name} ${target.title} SDK
9
43
 
10
- The ${target.title} SDK for the ${model.Name} API. Provides an entity-oriented interface using PHP conventions.
44
+ ${tagline}
45
+
46
+ The ${target.title} SDK for the ${model.Name} API — an entity-oriented client using PHP conventions.
47
+
48
+ ${semantic}> Other languages, the CLI, and MCP server live alongside this one — see
49
+ > the [top-level README](../README.md).
11
50
 
12
51
  `)
13
52
  })
@@ -13,6 +13,23 @@ const ReadmeModel = cmp(function ReadmeModel(props: any) {
13
13
  const entity = getModelPath(model, `main.${KIT}.entity`)
14
14
  const entityList = each(entity).filter((e: any) => e.active !== false)
15
15
 
16
+ // Model-driven op rows for the shared entity interface: emit a
17
+ // load/list/create/update/remove row only for operations at least one active
18
+ // entity actually exposes (a read-only entity has just list+load) — never
19
+ // document an operation no entity has.
20
+ const opUnion = new Set<string>()
21
+ entityList.forEach((e: any) => Object.keys(e.op || {})
22
+ .forEach((o: string) => { if (e.op[o] && e.op[o].active !== false) opUnion.add(o) }))
23
+ const opRowDefs: Record<string, string> = {
24
+ load: '| `load` | `($reqmatch, $ctrl): array` | Load a single entity by match criteria. |',
25
+ list: '| `list` | `(?array $reqmatch = null, $ctrl): array` | List entities matching the criteria (call with no argument to list all). |',
26
+ create: '| `create` | `($reqdata, $ctrl): array` | Create a new entity. |',
27
+ update: '| `update` | `($reqdata, $ctrl): array` | Update an existing entity. |',
28
+ remove: '| `remove` | `($reqmatch, $ctrl): array` | Remove an entity. |',
29
+ }
30
+ const opRows = ['load', 'list', 'create', 'update', 'remove']
31
+ .filter((o) => opUnion.has(o)).map((o) => opRowDefs[o]).join('\n')
32
+
16
33
  const apikeyOptionRow = isAuthActive(model)
17
34
  ? '| `apikey` | `string` | API key for authentication. |\n'
18
35
  : ''
@@ -54,7 +71,8 @@ Creates a test-mode client with mock transport. Both arguments may be \`null\`.
54
71
  `)
55
72
 
56
73
  each(entityList, (ent: any) => {
57
- Content(`| \`${ent.Name}\` | \`($data): ${ent.Name}Entity\` | Create a ${ent.Name} entity instance. |
74
+ const article = /^[aeiou]/i.test(ent.Name) ? 'an' : 'a'
75
+ Content(`| \`${ent.Name}\` | \`($data): ${ent.Name}Entity\` | Create ${article} ${ent.Name} entity instance. |
58
76
  `)
59
77
  })
60
78
 
@@ -65,11 +83,7 @@ All entities share the same interface.
65
83
 
66
84
  | Method | Signature | Description |
67
85
  | --- | --- | --- |
68
- | \`load\` | \`($reqmatch, $ctrl): array\` | Load a single entity by match criteria. |
69
- | \`list\` | \`($reqmatch, $ctrl): array\` | List entities matching the criteria. |
70
- | \`create\` | \`($reqdata, $ctrl): array\` | Create a new entity. |
71
- | \`update\` | \`($reqdata, $ctrl): array\` | Update an existing entity. |
72
- | \`remove\` | \`($reqmatch, $ctrl): array\` | Remove an entity. |
86
+ ${opRows}
73
87
  | \`data_get\` | \`(): array\` | Get entity data. |
74
88
  | \`data_set\` | \`($data): void\` | Set entity data. |
75
89
  | \`match_get\` | \`(): array\` | Get entity match criteria. |
@@ -79,8 +93,12 @@ All entities share the same interface.
79
93
 
80
94
  ### Result shape
81
95
 
82
- Entity operations return \`[$result, $err]\`. The first value is an
83
- \`array\` with these keys:
96
+ Entity operations return the bare result data (an \`array\` for single-entity
97
+ ops, a \`list\` for \`list\`) and throw on error. Wrap calls in
98
+ \`try\`/\`catch\` to handle failures.
99
+
100
+ The \`direct()\` escape hatch never throws — it returns a result \`array\`
101
+ you branch on via \`$result["ok"]\`:
84
102
 
85
103
  | Key | Type | Description |
86
104
  | --- | --- | --- |