@voxgig/sdkgen 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/bin/voxgig-sdkgen +22 -2
  2. package/dist/action/doctor.d.ts +14 -0
  3. package/dist/action/doctor.js +296 -0
  4. package/dist/action/doctor.js.map +1 -0
  5. package/dist/action/feature.js +48 -9
  6. package/dist/action/feature.js.map +1 -1
  7. package/dist/action/target.d.ts +6 -1
  8. package/dist/action/target.js +134 -22
  9. package/dist/action/target.js.map +1 -1
  10. package/dist/cmp/Entity.js +5 -0
  11. package/dist/cmp/Entity.js.map +1 -1
  12. package/dist/cmp/Feature.js +2 -1
  13. package/dist/cmp/Feature.js.map +1 -1
  14. package/dist/cmp/Main.js +5 -1
  15. package/dist/cmp/Main.js.map +1 -1
  16. package/dist/cmp/ReadmeExplanation.js +1 -1
  17. package/dist/cmp/ReadmeExplanation.js.map +1 -1
  18. package/dist/cmp/ReadmeTop.js +16 -6
  19. package/dist/cmp/ReadmeTop.js.map +1 -1
  20. package/dist/cmp/Registered.d.ts +7 -0
  21. package/dist/cmp/Registered.js +70 -0
  22. package/dist/cmp/Registered.js.map +1 -0
  23. package/dist/cmp/Test.js +3 -1
  24. package/dist/cmp/Test.js.map +1 -1
  25. package/dist/helpers/dryrun.d.ts +10 -0
  26. package/dist/helpers/dryrun.js +35 -0
  27. package/dist/helpers/dryrun.js.map +1 -0
  28. package/dist/helpers/featureSource.d.ts +13 -0
  29. package/dist/helpers/featureSource.js +156 -0
  30. package/dist/helpers/featureSource.js.map +1 -0
  31. package/dist/helpers/naming.d.ts +9 -1
  32. package/dist/helpers/naming.js +66 -2
  33. package/dist/helpers/naming.js.map +1 -1
  34. package/dist/helpers/opExample.js +23 -3
  35. package/dist/helpers/opExample.js.map +1 -1
  36. package/dist/helpers/opShape.d.ts +11 -1
  37. package/dist/helpers/opShape.js +51 -0
  38. package/dist/helpers/opShape.js.map +1 -1
  39. package/dist/helpers/packageMeta.d.ts +8 -1
  40. package/dist/helpers/packageMeta.js +141 -10
  41. package/dist/helpers/packageMeta.js.map +1 -1
  42. package/dist/helpers/stdrep.d.ts +3 -0
  43. package/dist/helpers/stdrep.js +47 -0
  44. package/dist/helpers/stdrep.js.map +1 -0
  45. package/dist/helpers/testPolicy.d.ts +2 -0
  46. package/dist/helpers/testPolicy.js +46 -0
  47. package/dist/helpers/testPolicy.js.map +1 -0
  48. package/dist/sdkgen.d.ts +15 -6
  49. package/dist/sdkgen.js +45 -4
  50. package/dist/sdkgen.js.map +1 -1
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/model/sdkgen.aontu +125 -0
  53. package/package.json +8 -5
  54. package/project/.sdk/model/target/c.aontu +28 -3
  55. package/project/.sdk/model/target/clojure.aontu +24 -3
  56. package/project/.sdk/model/target/cpp.aontu +25 -3
  57. package/project/.sdk/model/target/csharp.aontu +25 -3
  58. package/project/.sdk/model/target/dart.aontu +15 -3
  59. package/project/.sdk/model/target/elixir.aontu +15 -3
  60. package/project/.sdk/model/target/go-cli.aontu +17 -1
  61. package/project/.sdk/model/target/go-mcp.aontu +17 -1
  62. package/project/.sdk/model/target/go.aontu +14 -4
  63. package/project/.sdk/model/target/haskell.aontu +24 -3
  64. package/project/.sdk/model/target/java.aontu +26 -3
  65. package/project/.sdk/model/target/js.aontu +15 -3
  66. package/project/.sdk/model/target/kotlin.aontu +26 -3
  67. package/project/.sdk/model/target/lean.aontu +25 -3
  68. package/project/.sdk/model/target/lua.aontu +15 -3
  69. package/project/.sdk/model/target/ocaml.aontu +24 -3
  70. package/project/.sdk/model/target/perl.aontu +15 -3
  71. package/project/.sdk/model/target/php.aontu +15 -3
  72. package/project/.sdk/model/target/py-data.aontu +16 -3
  73. package/project/.sdk/model/target/py.aontu +15 -3
  74. package/project/.sdk/model/target/rb.aontu +15 -3
  75. package/project/.sdk/model/target/rust.aontu +25 -3
  76. package/project/.sdk/model/target/scala.aontu +25 -3
  77. package/project/.sdk/model/target/swift.aontu +25 -3
  78. package/project/.sdk/model/target/ts.aontu +15 -3
  79. package/project/.sdk/model/target/zig.aontu +26 -3
  80. package/project/.sdk/src/cmp/c/Config_c.ts +10 -11
  81. package/project/.sdk/src/cmp/c/Entity_c.ts +5 -1
  82. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +23 -5
  83. package/project/.sdk/src/cmp/c/fragment/EntityCreateOp.fragment.c +9 -2
  84. package/project/.sdk/src/cmp/c/fragment/EntityListOp.fragment.c +19 -2
  85. package/project/.sdk/src/cmp/c/fragment/EntityLoadOp.fragment.c +9 -2
  86. package/project/.sdk/src/cmp/c/fragment/EntityRemoveOp.fragment.c +12 -2
  87. package/project/.sdk/src/cmp/c/fragment/EntityUpdateOp.fragment.c +9 -2
  88. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -0
  89. package/project/.sdk/src/cmp/clojure/TestEntity_clojure.ts +6 -3
  90. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -1
  91. package/project/.sdk/src/cmp/clojure/fragment/EntityCreateOp.fragment.clj +2 -2
  92. package/project/.sdk/src/cmp/clojure/fragment/EntityLoadOp.fragment.clj +2 -2
  93. package/project/.sdk/src/cmp/clojure/fragment/EntityRemoveOp.fragment.clj +12 -8
  94. package/project/.sdk/src/cmp/clojure/fragment/EntityUpdateOp.fragment.clj +2 -2
  95. package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +5 -1
  96. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +24 -11
  97. package/project/.sdk/src/cmp/cpp/fragment/EntityCreateOp.fragment.cpp +8 -2
  98. package/project/.sdk/src/cmp/cpp/fragment/EntityListOp.fragment.cpp +18 -2
  99. package/project/.sdk/src/cmp/cpp/fragment/EntityLoadOp.fragment.cpp +8 -2
  100. package/project/.sdk/src/cmp/cpp/fragment/EntityRemoveOp.fragment.cpp +11 -2
  101. package/project/.sdk/src/cmp/cpp/fragment/EntityUpdateOp.fragment.cpp +8 -2
  102. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +2 -1
  103. package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
  104. package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +6 -6
  105. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +38 -1
  106. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +42 -33
  107. package/project/.sdk/src/cmp/dart/Config_dart.ts +6 -0
  108. package/project/.sdk/src/cmp/dart/Package_dart.ts +2 -1
  109. package/project/.sdk/src/cmp/dart/ReadmeEntity_dart.ts +13 -2
  110. package/project/.sdk/src/cmp/dart/ReadmeHowto_dart.ts +2 -1
  111. package/project/.sdk/src/cmp/dart/ReadmeInstall_dart.ts +3 -3
  112. package/project/.sdk/src/cmp/dart/ReadmeModel_dart.ts +1 -1
  113. package/project/.sdk/src/cmp/dart/ReadmeQuick_dart.ts +17 -6
  114. package/project/.sdk/src/cmp/dart/ReadmeRef_dart.ts +13 -2
  115. package/project/.sdk/src/cmp/dart/ReadmeTopQuick_dart.ts +13 -2
  116. package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +3 -3
  117. package/project/.sdk/src/cmp/dart/TestEntity_dart.ts +8 -8
  118. package/project/.sdk/src/cmp/dart/fragment/EntityBase.fragment.dart +18 -1
  119. package/project/.sdk/src/cmp/dart/fragment/EntityCreateOp.fragment.dart +9 -1
  120. package/project/.sdk/src/cmp/dart/fragment/EntityLoadOp.fragment.dart +9 -1
  121. package/project/.sdk/src/cmp/dart/fragment/EntityRemoveOp.fragment.dart +15 -1
  122. package/project/.sdk/src/cmp/dart/fragment/EntityUpdateOp.fragment.dart +9 -1
  123. package/project/.sdk/src/cmp/dart/fragment/SdkError.fragment.dart +8 -0
  124. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +3 -1
  125. package/project/.sdk/src/cmp/elixir/ReadmeInstall_elixir.ts +2 -2
  126. package/project/.sdk/src/cmp/elixir/ReadmeTopQuick_elixir.ts +7 -4
  127. package/project/.sdk/src/cmp/elixir/TestEntity_elixir.ts +11 -2
  128. package/project/.sdk/src/cmp/elixir/fragment/EntityCreateOp.fragment.ex +2 -1
  129. package/project/.sdk/src/cmp/elixir/fragment/EntityListOp.fragment.ex +1 -0
  130. package/project/.sdk/src/cmp/elixir/fragment/EntityLoadOp.fragment.ex +2 -1
  131. package/project/.sdk/src/cmp/elixir/fragment/EntityRemoveOp.fragment.ex +4 -1
  132. package/project/.sdk/src/cmp/elixir/fragment/EntityUpdateOp.fragment.ex +2 -1
  133. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +38 -8
  134. package/project/.sdk/src/cmp/go/Entity_go.ts +2 -2
  135. package/project/.sdk/src/cmp/go/Main_go.ts +4 -5
  136. package/project/.sdk/src/cmp/go/Package_go.ts +8 -5
  137. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +2 -2
  138. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +2 -2
  139. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +4 -2
  140. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +2 -2
  141. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +2 -2
  142. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +2 -2
  143. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +2 -2
  144. package/project/.sdk/src/cmp/go/TestDirect_go.ts +21 -15
  145. package/project/.sdk/src/cmp/go/TestEntity_go.ts +9 -9
  146. package/project/.sdk/src/cmp/go/Test_go.ts +2 -2
  147. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +42 -1
  148. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +4 -4
  149. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +4 -4
  150. package/project/.sdk/src/cmp/haskell/Package_haskell.ts +2 -1
  151. package/project/.sdk/src/cmp/haskell/ReadmeEntity_haskell.ts +10 -5
  152. package/project/.sdk/src/cmp/haskell/ReadmeModel_haskell.ts +10 -8
  153. package/project/.sdk/src/cmp/haskell/ReadmeQuick_haskell.ts +14 -10
  154. package/project/.sdk/src/cmp/haskell/ReadmeRef_haskell.ts +21 -18
  155. package/project/.sdk/src/cmp/haskell/ReadmeTopQuick_haskell.ts +4 -4
  156. package/project/.sdk/src/cmp/haskell/Test_haskell.ts +23 -11
  157. package/project/.sdk/src/cmp/java/Package_java.ts +2 -1
  158. package/project/.sdk/src/cmp/java/ReadmeHowto_java.ts +2 -1
  159. package/project/.sdk/src/cmp/java/ReadmeInstall_java.ts +2 -2
  160. package/project/.sdk/src/cmp/java/ReadmeModel_java.ts +1 -1
  161. package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +3 -3
  162. package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
  163. package/project/.sdk/src/cmp/java/TestEntity_java.ts +6 -6
  164. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +34 -1
  165. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +12 -0
  166. package/project/.sdk/src/cmp/js/Main_js.ts +4 -1
  167. package/project/.sdk/src/cmp/js/Package_js.ts +7 -1
  168. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +13 -2
  169. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +2 -1
  170. package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +13 -2
  171. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +13 -2
  172. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +2 -1
  173. package/project/.sdk/src/cmp/js/TestDirect_js.ts +3 -3
  174. package/project/.sdk/src/cmp/js/TestEntity_js.ts +8 -8
  175. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +22 -1
  176. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +9 -1
  177. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +9 -1
  178. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +15 -1
  179. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +9 -1
  180. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +13 -0
  181. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +2 -1
  182. package/project/.sdk/src/cmp/kotlin/ReadmeHowto_kotlin.ts +2 -1
  183. package/project/.sdk/src/cmp/kotlin/ReadmeInstall_kotlin.ts +2 -2
  184. package/project/.sdk/src/cmp/kotlin/ReadmeModel_kotlin.ts +1 -1
  185. package/project/.sdk/src/cmp/kotlin/ReadmeQuick_kotlin.ts +3 -3
  186. package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
  187. package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +6 -6
  188. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +32 -1
  189. package/project/.sdk/src/cmp/lean/Package_lean.ts +3 -1
  190. package/project/.sdk/src/cmp/lean/Test_lean.ts +75 -21
  191. package/project/.sdk/src/cmp/lua/MainEntity_lua.ts +9 -4
  192. package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -3
  193. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +11 -3
  194. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +1 -1
  195. package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
  196. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +9 -9
  197. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +37 -1
  198. package/project/.sdk/src/cmp/lua/fragment/SdkError.fragment.lua +12 -0
  199. package/project/.sdk/src/cmp/ocaml/EntityOperation_ocaml.ts +30 -3
  200. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +11 -5
  201. package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +3 -1
  202. package/project/.sdk/src/cmp/ocaml/ReadmeEntity_ocaml.ts +10 -5
  203. package/project/.sdk/src/cmp/ocaml/ReadmeHowto_ocaml.ts +6 -2
  204. package/project/.sdk/src/cmp/ocaml/ReadmeModel_ocaml.ts +10 -8
  205. package/project/.sdk/src/cmp/ocaml/ReadmeQuick_ocaml.ts +14 -13
  206. package/project/.sdk/src/cmp/ocaml/ReadmeRef_ocaml.ts +20 -18
  207. package/project/.sdk/src/cmp/ocaml/ReadmeTopQuick_ocaml.ts +4 -4
  208. package/project/.sdk/src/cmp/ocaml/ReadmeTopTest_ocaml.ts +8 -2
  209. package/project/.sdk/src/cmp/ocaml/TestEntity_ocaml.ts +8 -5
  210. package/project/.sdk/src/cmp/perl/ReadmeHowto_perl.ts +2 -1
  211. package/project/.sdk/src/cmp/perl/ReadmeModel_perl.ts +1 -1
  212. package/project/.sdk/src/cmp/perl/ReadmeQuick_perl.ts +3 -3
  213. package/project/.sdk/src/cmp/perl/ReadmeTopQuick_perl.ts +1 -1
  214. package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
  215. package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +6 -6
  216. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +36 -1
  217. package/project/.sdk/src/cmp/php/MainEntity_php.ts +21 -16
  218. package/project/.sdk/src/cmp/php/Package_php.ts +2 -2
  219. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +6 -6
  220. package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +4 -3
  221. package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +2 -2
  222. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +1 -1
  223. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +12 -12
  224. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +6 -6
  225. package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +4 -4
  226. package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +2 -2
  227. package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
  228. package/project/.sdk/src/cmp/php/TestEntity_php.ts +17 -15
  229. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +20 -1
  230. package/project/.sdk/src/cmp/php/fragment/SdkError.fragment.php +11 -0
  231. package/project/.sdk/src/cmp/py/Package_py.ts +4 -3
  232. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +13 -2
  233. package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +2 -1
  234. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +1 -1
  235. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +17 -6
  236. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +14 -3
  237. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +13 -2
  238. package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
  239. package/project/.sdk/src/cmp/py/TestEntity_py.ts +9 -9
  240. package/project/.sdk/src/cmp/py/Test_py.ts +4 -1
  241. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +29 -1
  242. package/project/.sdk/src/cmp/py/fragment/SdkError.fragment.py +11 -0
  243. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +2 -1
  244. package/project/.sdk/src/cmp/rb/Package_rb.ts +4 -3
  245. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +1 -1
  246. package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +2 -1
  247. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +5 -5
  248. package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +1 -1
  249. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
  250. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +9 -9
  251. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +31 -1
  252. package/project/.sdk/src/cmp/rb/fragment/SdkError.fragment.rb +10 -1
  253. package/project/.sdk/src/cmp/rust/Entity_rust.ts +5 -1
  254. package/project/.sdk/src/cmp/rust/Main_rust.ts +21 -0
  255. package/project/.sdk/src/cmp/rust/Package_rust.ts +2 -1
  256. package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
  257. package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +12 -12
  258. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +18 -0
  259. package/project/.sdk/src/cmp/rust/fragment/EntityCreateOp.fragment.rs +8 -2
  260. package/project/.sdk/src/cmp/rust/fragment/EntityListOp.fragment.rs +20 -3
  261. package/project/.sdk/src/cmp/rust/fragment/EntityLoadOp.fragment.rs +8 -2
  262. package/project/.sdk/src/cmp/rust/fragment/EntityRemoveOp.fragment.rs +10 -2
  263. package/project/.sdk/src/cmp/rust/fragment/EntityUpdateOp.fragment.rs +8 -2
  264. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +10 -0
  265. package/project/.sdk/src/cmp/scala/ReadmeHowto_scala.ts +2 -1
  266. package/project/.sdk/src/cmp/scala/ReadmeInstall_scala.ts +3 -3
  267. package/project/.sdk/src/cmp/scala/ReadmeModel_scala.ts +1 -1
  268. package/project/.sdk/src/cmp/scala/ReadmeQuick_scala.ts +3 -3
  269. package/project/.sdk/src/cmp/scala/TestEntity_scala.ts +3 -3
  270. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +27 -1
  271. package/project/.sdk/src/cmp/swift/ReadmeHowto_swift.ts +2 -1
  272. package/project/.sdk/src/cmp/swift/ReadmeInstall_swift.ts +3 -3
  273. package/project/.sdk/src/cmp/swift/ReadmeModel_swift.ts +1 -1
  274. package/project/.sdk/src/cmp/swift/ReadmeQuick_swift.ts +3 -3
  275. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +34 -1
  276. package/project/.sdk/src/cmp/ts/EntityOperation_ts.ts +9 -1
  277. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +18 -1
  278. package/project/.sdk/src/cmp/ts/Gitignore_ts.ts +5 -2
  279. package/project/.sdk/src/cmp/ts/Main_ts.ts +4 -1
  280. package/project/.sdk/src/cmp/ts/Package_ts.ts +10 -1
  281. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +13 -2
  282. package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +2 -1
  283. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +21 -6
  284. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +52 -2
  285. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +14 -3
  286. package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +34 -2
  287. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +64 -43
  288. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +8 -8
  289. package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +2 -2
  290. package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +2 -2
  291. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +25 -1
  292. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +10 -2
  293. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +1 -1
  294. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +10 -2
  295. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +27 -3
  296. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +10 -2
  297. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +15 -0
  298. package/project/.sdk/src/cmp/zig/Entity_zig.ts +5 -1
  299. package/project/.sdk/src/cmp/zig/Package_zig.ts +3 -1
  300. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +39 -0
  301. package/project/.sdk/src/cmp/zig/fragment/EntityCreateOp.fragment.zig +2 -2
  302. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +21 -2
  303. package/project/.sdk/src/cmp/zig/fragment/EntityLoadOp.fragment.zig +2 -2
  304. package/project/.sdk/src/cmp/zig/fragment/EntityRemoveOp.fragment.zig +5 -2
  305. package/project/.sdk/src/cmp/zig/fragment/EntityUpdateOp.fragment.zig +2 -2
  306. package/project/.sdk/tm/c/VERSION +1 -1
  307. package/project/.sdk/tm/c/core/helpers.c +1 -0
  308. package/project/.sdk/tm/c/core/sdk.h +22 -6
  309. package/project/.sdk/tm/c/tests/feature_harness.h +1 -0
  310. package/project/.sdk/tm/c/tests/primary_utility_test.c +4 -1
  311. package/project/.sdk/tm/c/utility/graphql.c +1 -1
  312. package/project/.sdk/tm/c/utility/make_url.c +1 -0
  313. package/project/.sdk/tm/c/utility/param.c +1 -0
  314. package/project/.sdk/tm/clojure/VERSION +1 -1
  315. package/project/.sdk/tm/cpp/VERSION +1 -1
  316. package/project/.sdk/tm/cpp/core/types.hpp +33 -8
  317. package/project/.sdk/tm/cpp/test/pipeline_test.cpp +5 -0
  318. package/project/.sdk/tm/cpp/test/runner_support.hpp +4 -4
  319. package/project/.sdk/tm/csharp/VERSION +1 -1
  320. package/project/.sdk/tm/csharp/core/Types.cs +6 -0
  321. package/project/.sdk/tm/csharp/test/FeatureHarness.cs +396 -0
  322. package/project/.sdk/tm/csharp/test/FeatureTest.cs +7 -385
  323. package/project/.sdk/tm/csharp/test/Runner.cs +4 -4
  324. package/project/.sdk/tm/dart/lib/utility/MakeErrorUtility.dart +4 -0
  325. package/project/.sdk/tm/dart/test/utility.dart +4 -4
  326. package/project/.sdk/tm/elixir/VERSION +1 -1
  327. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +26 -0
  328. package/project/.sdk/tm/go/VERSION +1 -1
  329. package/project/.sdk/tm/go/core/types.go +6 -0
  330. package/project/.sdk/tm/go/test/feature_harness_test.go +361 -0
  331. package/project/.sdk/tm/go/test/feature_test.go +7 -350
  332. package/project/.sdk/tm/go/test/pipeline_test.go +6 -0
  333. package/project/.sdk/tm/go/test/runner_test.go +16 -4
  334. package/project/.sdk/tm/haskell/VERSION +1 -1
  335. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +28 -5
  336. package/project/.sdk/tm/haskell/src/SdkTypes.hs +14 -5
  337. package/project/.sdk/tm/java/VERSION +1 -1
  338. package/project/.sdk/tm/java/test/RunnerSupport.java +4 -4
  339. package/project/.sdk/tm/java/utility/MakeError.java +4 -0
  340. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +4 -0
  341. package/project/.sdk/tm/js/test/utility.js +3 -3
  342. package/project/.sdk/tm/kotlin/VERSION +1 -1
  343. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  344. package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +3 -3
  345. package/project/.sdk/tm/lean/Makefile +25 -0
  346. package/project/.sdk/tm/lean/VERSION +1 -1
  347. package/project/.sdk/tm/lean/src/SdkUtility.lean +11 -9
  348. package/project/.sdk/tm/lean/test/TFeature.lean +27 -14
  349. package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +5 -2
  350. package/project/.sdk/tm/lua/test/runner.lua +4 -4
  351. package/project/.sdk/tm/lua/utility/make_error.lua +4 -0
  352. package/project/.sdk/tm/ocaml/VERSION +1 -1
  353. package/project/.sdk/tm/ocaml/sdk_types.ml +14 -5
  354. package/project/.sdk/tm/ocaml/test/t_pipeline.ml +5 -2
  355. package/project/.sdk/tm/perl/t/runner.pm +4 -4
  356. package/project/.sdk/tm/php/VERSION +1 -1
  357. package/project/.sdk/tm/php/test/Runner.php +4 -4
  358. package/project/.sdk/tm/php/utility/MakeError.php +5 -0
  359. package/project/.sdk/tm/py/pkg/utility/make_error.py +4 -0
  360. package/project/.sdk/tm/py/test/runner.py +19 -4
  361. package/project/.sdk/tm/rb/test/runner.rb +4 -4
  362. package/project/.sdk/tm/rb/utility/make_error.rb +4 -0
  363. package/project/.sdk/tm/rust/VERSION +1 -1
  364. package/project/.sdk/tm/rust/core/types.rs +22 -6
  365. package/project/.sdk/tm/rust/tests/common/mod.rs +6 -6
  366. package/project/.sdk/tm/rust/tests/pipeline_test.rs +6 -0
  367. package/project/.sdk/tm/rust/utility/make_error.rs +4 -0
  368. package/project/.sdk/tm/scala/VERSION +1 -1
  369. package/project/.sdk/tm/swift/VERSION +1 -1
  370. package/project/.sdk/tm/ts/src/tsconfig.json +1 -0
  371. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +4 -0
  372. package/project/.sdk/tm/ts/test/tsconfig.json +1 -0
  373. package/project/.sdk/tm/ts/test/utility.ts +3 -3
  374. package/project/.sdk/tm/zig/VERSION +1 -1
  375. package/src/action/doctor.ts +410 -0
  376. package/src/action/feature.ts +54 -16
  377. package/src/action/target.ts +174 -25
  378. package/src/cmp/Entity.ts +7 -0
  379. package/src/cmp/Feature.ts +3 -1
  380. package/src/cmp/Main.ts +7 -1
  381. package/src/cmp/ReadmeExplanation.ts +2 -2
  382. package/src/cmp/ReadmeTop.ts +22 -9
  383. package/src/cmp/Registered.ts +100 -0
  384. package/src/cmp/Test.ts +4 -1
  385. package/src/helpers/dryrun.ts +57 -0
  386. package/src/helpers/featureSource.ts +208 -0
  387. package/src/helpers/naming.ts +73 -2
  388. package/src/helpers/opExample.ts +19 -2
  389. package/src/helpers/opShape.ts +65 -0
  390. package/src/helpers/packageMeta.ts +163 -10
  391. package/src/helpers/stdrep.ts +56 -0
  392. package/src/helpers/testPolicy.ts +52 -0
  393. package/src/sdkgen.ts +70 -4
  394. package/project/.sdk/tm/rust/feature/mod.rs +0 -24
@@ -0,0 +1,208 @@
1
+ // Locate the per-feature source inside a target's template tree.
2
+ //
3
+ // WHY THIS EXISTS
4
+ //
5
+ // `target add` is supposed to copy source for the features the model
6
+ // declares, and nothing else. It used to do that with a single hardcoded
7
+ // path assumption:
8
+ //
9
+ // Copy({ from: 'tm/<lang>', exclude: [/src\/feature/] })
10
+ // Folder({ name: 'src/feature' }, () => /* copy each model feature */)
11
+ //
12
+ // That assumption holds for exactly two targets. `ts` and `js` keep feature
13
+ // source at `src/feature/<name>/`; everyone else does something else —
14
+ // `tm/go/feature/retry_feature.go`, `tm/rust/feature/retry.rs`,
15
+ // `tm/py/pkg/feature/retry_feature.py`, `tm/dart/lib/feature/retry/...`,
16
+ // `tm/swift/Sources/ProjectNameSDK/feature/RetryFeature.swift`, and so on.
17
+ // None of those match `src/feature`, so the exclude never saw them and every
18
+ // shipped feature was copied into every project regardless of the model: 272
19
+ // stray source files across 17 targets for a project declaring no features
20
+ // at all. (For those targets `src/feature/<name>/` holds only a `.gitkeep`
21
+ // placeholder — the old gate was gating empty directories.)
22
+ //
23
+ // So instead of encoding one layout, DISCOVER it: walk the template tree,
24
+ // treat any directory named `feature` as a feature container, and map each
25
+ // entry inside it back to a feature name. That covers every layout above,
26
+ // and a target added later gets gated without anyone editing this file.
27
+ //
28
+ // The mapping is deliberately conservative. An entry only counts as feature
29
+ // source when its derived name is one the generator can actually supply
30
+ // (`availableFeatures`, read from `model/feature/*.aontu`). Everything else
31
+ // inside a feature directory — `feature_options.go`, `FeatureOptions.cs`,
32
+ // `mod.rs`, `support.rs`, `options.hpp`, `__init__.py`, `README.md`, and the
33
+ // `harness.ts` under `test/feature/` — derives a name no feature has, so it
34
+ // is left alone.
35
+
36
+ import Path from 'node:path'
37
+
38
+ import { KIT, getModelPath } from '@voxgig/apidef'
39
+
40
+
41
+ // One feature's source within a target template tree.
42
+ type FeatureSource = {
43
+ // Feature name, lowercased ('retry').
44
+ name: string
45
+
46
+ // Path relative to the target template root ('feature/retry_feature.go',
47
+ // 'lib/feature/retry'), always with forward slashes.
48
+ path: string
49
+
50
+ // True when `path` is a directory holding the whole feature.
51
+ folder: boolean
52
+ }
53
+
54
+
55
+ // Directory name that marks a feature container. Kept exact (not a substring
56
+ // match) so `utility/feature_add.go` and `test/feature_test.go` — which are
57
+ // shared machinery, not per-feature source — are never treated as features.
58
+ const FEATURE_DIR = 'feature'
59
+
60
+
61
+ // Derive the feature name an entry inside a feature directory belongs to.
62
+ // Returns the lowercased name, which the caller then checks against the
63
+ // available set.
64
+ //
65
+ // retry_feature.go -> retry (go, py, rb, lua, perl)
66
+ // RetryFeature.cs -> retry (csharp, java, kotlin, scala, swift, php)
67
+ // retry.rs -> retry (rust, c, cpp, zig, elixir)
68
+ // retry/ -> retry (ts, js, dart)
69
+ // feature_options.go -> feature_options (not a feature; `_feature` is a
70
+ // prefix here, not a suffix)
71
+ // FeatureOptions.cs -> featureoptions (ditto)
72
+ function featureOf(entry: string, folder: boolean): string {
73
+ if (folder) {
74
+ return entry.toLowerCase()
75
+ }
76
+
77
+ // Only the final extension goes; `feature.test.ts` style names keep the
78
+ // rest so they cannot collide with a bare feature name.
79
+ const stem = entry.replace(/\.[^.]+$/, '')
80
+
81
+ return stem
82
+ .replace(/_feature$/i, '')
83
+ .replace(/Feature$/, '')
84
+ .toLowerCase()
85
+ }
86
+
87
+
88
+ // Feature names this generator can supply, read from the scaffold's
89
+ // `model/feature/*.aontu`. This is the authoritative catalogue: a name not in
90
+ // it is not a feature, so nothing outside it is ever excluded.
91
+ function availableFeatures(fs: any, sdkfolder: string): string[] {
92
+ const dir = Path.join(sdkfolder, 'model', 'feature')
93
+
94
+ if (!fs.existsSync(dir)) {
95
+ return []
96
+ }
97
+
98
+ return fs.readdirSync(dir)
99
+ .filter((n: string) => n.endsWith('.aontu') && 'feature-index.aontu' !== n)
100
+ .map((n: string) => n.replace(/\.aontu$/, '').toLowerCase())
101
+ .sort()
102
+ }
103
+
104
+
105
+ // Walk a target's template tree and return every per-feature source entry.
106
+ // `tmfolder` is the target template root (`<sdk>/tm/<lang>`).
107
+ function findFeatureSources(fs: any, tmfolder: string, available: string[]): FeatureSource[] {
108
+ const known = new Set(available)
109
+ const found: FeatureSource[] = []
110
+
111
+ if (!fs.existsSync(tmfolder)) {
112
+ return found
113
+ }
114
+
115
+ // `rel` is relative to tmfolder, '' at the root.
116
+ const walk = (rel: string) => {
117
+ const abs = '' === rel ? tmfolder : Path.join(tmfolder, rel)
118
+ const entries = fs.readdirSync(abs).sort()
119
+
120
+ for (const entry of entries) {
121
+ const entryrel = '' === rel ? entry : rel + '/' + entry
122
+ const folder = fs.statSync(Path.join(tmfolder, entryrel)).isDirectory()
123
+
124
+ // Inside a feature container every entry is a candidate, and a
125
+ // candidate directory is the whole feature — do not descend into it
126
+ // looking for more.
127
+ if (FEATURE_DIR === Path.basename(rel)) {
128
+ const name = featureOf(entry, folder)
129
+ if (known.has(name)) {
130
+ found.push({ name, path: entryrel, folder })
131
+ continue
132
+ }
133
+ }
134
+
135
+ if (folder) {
136
+ walk(entryrel)
137
+ }
138
+ }
139
+ }
140
+
141
+ walk('')
142
+
143
+ return found
144
+ }
145
+
146
+
147
+ // Turn discovered sources into path patterns for a jostraca `Copy` exclude.
148
+ //
149
+ // jostraca tests each candidate against the path built up during its walk,
150
+ // which carries the enclosing node path as a prefix — so anchor on a
151
+ // segment boundary at both ends rather than on the whole string. A folder
152
+ // source matches everything beneath it; a file source matches only itself.
153
+ function featureExcludes(sources: FeatureSource[]): RegExp[] {
154
+ return sources.map((s) => new RegExp(
155
+ '(^|/)' + s.path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + (s.folder ? '/' : '$')
156
+ ))
157
+ }
158
+
159
+
160
+ // Path patterns for templates that only compile with the COMPLETE feature
161
+ // set — see `feature.fullset` in each target's model. These are the
162
+ // cross-feature test suites: one file per target that constructs every
163
+ // shipped feature type by name (`feature.NewRetryFeature`,
164
+ // `RUSTCRATE::feature::retry::RetryFeature`, ...). Trimming the feature set
165
+ // without dropping them leaves a project that will not compile.
166
+ function fullsetExcludes(paths: string[]): RegExp[] {
167
+ return (paths || []).map((p) => new RegExp(
168
+ '(^|/)' + String(p).replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '$'
169
+ ))
170
+ }
171
+
172
+
173
+ // Generate-time guard for the `src/feature/<name>/` layout (ts, js).
174
+ //
175
+ // Root renders one Feature component per ACTIVE feature, but Main then
176
+ // copies the whole `tm/<lang>` tree — which puts a deactivated feature's
177
+ // source straight back, silently undoing the filter. `target add` keeps
178
+ // deactivated features out of `tm` in the first place; this covers the case
179
+ // where a feature is switched off AFTER it was added.
180
+ //
181
+ // Only declared-but-inactive features are excluded. `base` and anything else
182
+ // the model never mentions is left alone.
183
+ function srcFeatureExcludes(model: any): RegExp[] {
184
+ const all = getModelPath(model, `main.${KIT}.feature`,
185
+ { required: false, only_active: false }) || {}
186
+ const active = getModelPath(model, `main.${KIT}.feature`,
187
+ { required: false }) || {}
188
+
189
+ return Object.keys(all)
190
+ .filter((name: string) => null == active[name])
191
+ .map((name: string) => new RegExp(
192
+ '(^|/)src/feature/' + name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '/'
193
+ ))
194
+ }
195
+
196
+
197
+ export type {
198
+ FeatureSource,
199
+ }
200
+
201
+ export {
202
+ featureOf,
203
+ availableFeatures,
204
+ findFeatureSources,
205
+ featureExcludes,
206
+ fullsetExcludes,
207
+ srcFeatureExcludes,
208
+ }
@@ -209,16 +209,85 @@ function safeVarName(name: string, lang: string): string {
209
209
  }
210
210
 
211
211
 
212
+ // Members the generated PHP SDK class already declares (see the php target's
213
+ // fragment/Main.fragment.php). An entity accessor or backing field reusing one
214
+ // is a FATAL redeclare — PHP will not parse the file, so the SDK yields zero
215
+ // working tests rather than a degraded one.
216
+ //
217
+ // PHP method names are CASE-INSENSITIVE at declaration time, hence the
218
+ // lowercased comparison: an entity `graph_ql` derives the accessor `GraphQl()`,
219
+ // the same declaration as the SDK's own `graphql()`.
220
+ //
221
+ // This lives here, not in the php component, because the ACCESSOR NAME has to
222
+ // agree across the SDK class and every doc/example component that calls it.
223
+ // It did not: MainEntity_php emitted `Test_()` for an entity named `test`
224
+ // while eight readme components emitted `Test()`, so the generated examples
225
+ // called the static test-mode constructor and died with
226
+ // "Call to undefined method <Name>SDK::load()".
227
+ const PHP_SDK_METHODS = new Set([
228
+ 'construct', '__construct', 'direct', 'get_root_ctx', 'get_utility',
229
+ 'graphql', 'op_allowed', 'op_denied', 'options_map', 'prepare',
230
+ 'raw_request', 'test',
231
+ ])
232
+
233
+ // Backing fields the generated SDK object already holds, in EVERY target that
234
+ // caches its entity accessors in `_<name>`. php spells it `$this->_utility`
235
+ // and lua `self._utility`, but it is one hazard: the accessor's cache slot
236
+ // silently aliases the SDK's own field, so `client:Utility()` hands back the
237
+ // internal utility object and every entity method on it is nil.
238
+ const SDK_FIELDS = new Set(['rootctx', 'utility', 'client', 'entctx'])
239
+
240
+
241
+ /** The PHP accessor method for an entity: `$client-><Name>()`. */
242
+ function phpEntityAccessor(Name: string): string {
243
+ return PHP_SDK_METHODS.has(String(Name).toLowerCase()) ? Name + '_' : Name
244
+ }
245
+
246
+
247
+ /**
248
+ * The backing field for an entity accessor's cache slot (`$this->_<name>`,
249
+ * `self._<name>`). Target-neutral: the colliding names are the SDK's own
250
+ * fields, which the targets share.
251
+ */
252
+ function entityCacheField(name: string): string {
253
+ return SDK_FIELDS.has(String(name).toLowerCase()) ? name + '_' : name
254
+ }
255
+
256
+
257
+ // Symbols a doc example CALLS, which a same-named example variable would
258
+ // shadow. The variable is syntactically fine; the example then fails at
259
+ // RUNTIME, which is far harder to read than a compile error:
260
+ //
261
+ // const consoles = await client.Console().list()
262
+ // for (const console of consoles) { console.log(console) }
263
+ // -> "console.log is not a function" (nexarda, an API with a Console entity)
264
+ //
265
+ // Only languages where a plain variable can capture the symbol are listed.
266
+ // php is absent on purpose: its variables carry a `$` sigil, so `$echo` can
267
+ // never shadow `echo`.
268
+ const EXAMPLE_GLOBALS: Record<string, string[]> = {
269
+ ts: ['console', 'process', 'globalThis'],
270
+ js: ['console', 'process', 'globalThis'],
271
+ py: ['print'],
272
+ rb: ['puts'],
273
+ lua: ['print'],
274
+ go: ['fmt'],
275
+ }
276
+
277
+
212
278
  // A variable name for a doc EXAMPLE entity. Doc examples bind the SDK instance
213
279
  // to `client` (e.g. `const client = ...SDK.test()`), so an entity whose
214
280
  // lowercased name is also `client` — an API with a `Client` entity — would
215
281
  // shadow it: `const client = client.Client()...` is self-referential (TS2448/
216
282
  // TS7022) and breaks the readme_examples type-check. Append `_` to keep the
217
- // example variable distinct from the SDK instance. Also applies the normal
283
+ // example variable distinct from the SDK instance. The same applies to any
284
+ // symbol the example itself calls (EXAMPLE_GLOBALS). Also applies the normal
218
285
  // language-reserved-word guard.
219
286
  function exampleVarName(name: string, lang: string): string {
220
287
  const v = safeVarName(name, lang)
221
- return 'client' === v ? v + '_' : v
288
+ if ('client' === v) return v + '_'
289
+ if ((EXAMPLE_GLOBALS[lang] || []).includes(v)) return v + '_'
290
+ return v
222
291
  }
223
292
 
224
293
 
@@ -256,6 +325,8 @@ export {
256
325
  isReservedName,
257
326
  safeVarName,
258
327
  exampleVarName,
328
+ phpEntityAccessor,
329
+ entityCacheField,
259
330
  isRbCoreConstant,
260
331
  rbSafeTypeName,
261
332
  isSwiftSdkType,
@@ -20,6 +20,8 @@ import { each } from 'jostraca'
20
20
  import { canonKey } from './canonType'
21
21
  import { opRequestShape, entityIdField } from './opShape'
22
22
 
23
+ import { phpEntityAccessor } from './naming'
24
+
23
25
 
24
26
  type ExampleLang = 'ts' | 'js' | 'py' | 'php' | 'rb' | 'lua' | 'go'
25
27
 
@@ -35,7 +37,19 @@ function litFor(lang: ExampleLang, type: any): string {
35
37
  if ('INTEGER' === k || 'NUMBER' === k) return '1'
36
38
  if ('BOOLEAN' === k) return 'py' === lang ? 'True' : ('rb' === lang ? 'true' : 'true')
37
39
  if ('ARRAY' === k) return ('lua' === lang) ? '{}' : ('go' === lang ? '[]any{}' : '[]')
38
- if ('OBJECT' === k) return ('go' === lang) ? 'map[string]any{}' : '{}'
40
+ // PHP has no `{}` literal `["data" => {}]` is a parse error, which took
41
+ // the whole generated README down for any entity with an object-typed
42
+ // writable field (dymo-api-introduction, html-creator). Arrays serve as both
43
+ // list and map, so `[]` is the empty object too. Ruby and Lua likewise want
44
+ // their own empty-hash/table spelling rather than JS's.
45
+ if ('OBJECT' === k) {
46
+ if ('go' === lang) return 'map[string]any{}'
47
+ if ('php' === lang) return '[]'
48
+ if ('rb' === lang) return '{}'
49
+ if ('lua' === lang) return '{}'
50
+ if ('py' === lang) return '{}'
51
+ return '{}'
52
+ }
39
53
  return '"example"'
40
54
  }
41
55
 
@@ -154,7 +168,10 @@ function primaryOpCall(
154
168
  if ('go' === lang) { factory = `client.${eName}(nil)`; sep = '.' }
155
169
  else if ('lua' === lang) { factory = `client:${eName}()`; sep = ':' }
156
170
  else if ('rb' === lang) { factory = `client.${eName}`; sep = '.' }
157
- else if ('php' === lang) { factory = `$client->${eName}()`; sep = '->' }
171
+ // php mangles an accessor that would collide with an SDK class member
172
+ // (see phpEntityAccessor); the example has to call the name that is
173
+ // actually declared, or it invokes the SDK's own method instead.
174
+ else if ('php' === lang) { factory = `$client->${phpEntityAccessor(eName)}()`; sep = '->' }
158
175
  else { factory = `client.${eName}()`; sep = '.' }
159
176
 
160
177
  // Argument string per op + language.
@@ -127,6 +127,68 @@ type OpShapeItem = {
127
127
  // list-by-parent-id call failing because sibling routes' ids are demanded —
128
128
  // and steers callers into passing keys that flip runtime point dispatch to
129
129
  // the wrong route.)
130
+ // The action names an op multiplexes, from its points' `select.$action`.
131
+ //
132
+ // A custom POST route like `/api/planet/{id}/terraform` is folded into the
133
+ // `create` op as an alternative point, discriminated at call time by
134
+ // `$action` in the data argument. The mechanism worked and was documented
135
+ // NOWHERE — not in the README, not in the reference — so for an API with two
136
+ // such routes, two of its six endpoints were unreachable by anyone using the
137
+ // documented interface. Generated docs list them via this helper.
138
+ function opActions(op: any): { action: string, path: string }[] {
139
+ const points: any[] = op && op.points ? each(op.points) : []
140
+
141
+ return points
142
+ .filter((pt: any) => null != (pt && pt.select && pt.select['$action']))
143
+ .map((pt: any) => ({
144
+ action: String(pt.select['$action']),
145
+ path: String(pt.orig || ''),
146
+ }))
147
+ .sort((a, b) => a.action < b.action ? -1 : a.action > b.action ? 1 : 0)
148
+ }
149
+
150
+
151
+ // True when any of the entity's ops multiplexes a custom action.
152
+ function entityActions(entity: any): { op: string, action: string, path: string }[] {
153
+ const out: { op: string, action: string, path: string }[] = []
154
+
155
+ each(entity && entity.op).forEach((op: any) => {
156
+ opActions(op).forEach((a) => out.push({ op: op.name, ...a }))
157
+ })
158
+
159
+ return out
160
+ }
161
+
162
+
163
+ // The entity's own API path — the route a reader should recognise it by.
164
+ //
165
+ // NOT `points[0]` across every op flattened. Ops iterate in sorted-key order,
166
+ // so `create` came first, and an entity whose create op folds in a custom
167
+ // action (`/api/planet/{id}/forbid`) advertised THAT as its path. The
168
+ // canonical route is the collection or record route, and never an action.
169
+ function entityPath(entity: any): string {
170
+ const ops: any = (entity && entity.op) || {}
171
+
172
+ for (const opname of ['list', 'load', 'create', 'update', 'remove']) {
173
+ const op = ops[opname]
174
+ if (null == op) {
175
+ continue
176
+ }
177
+
178
+ const points: any[] = op.points ? each(op.points) : []
179
+ const canonical = points.filter((pt: any) =>
180
+ null == (pt && pt.select && pt.select['$action']))
181
+
182
+ const pick = (0 < canonical.length ? canonical : points)[0]
183
+ if (null != pick && null != pick.orig && '' !== pick.orig) {
184
+ return String(pick.orig)
185
+ }
186
+ }
187
+
188
+ return ''
189
+ }
190
+
191
+
130
192
  function opParams(op: any): any[] {
131
193
  let points: any[] = op && op.points ? each(op.points) : []
132
194
 
@@ -533,6 +595,9 @@ export {
533
595
  entityCollection,
534
596
  opTypeName,
535
597
  opParams,
598
+ opActions,
599
+ entityActions,
600
+ entityPath,
536
601
  opRequestShape,
537
602
  entityIdField,
538
603
  entityDataIdField,
@@ -38,15 +38,42 @@ function langLabel(target: string): string {
38
38
  return LANG_LABEL[target] || target
39
39
  }
40
40
 
41
- // GitHub org (publisher slug), repo name, and the canonical repo URLs.
41
+ // Git host, org/repo path, and the canonical repo URLs.
42
+ //
43
+ // `<origin>/<slug>-sdk` is a DERIVATION, not a law. A project whose repo is
44
+ // named anything else — `voxgig-sdk/voxgig-solardemo-sdk`, say, where the slug
45
+ // is `solardemo` — used to have no way to say so, and got a `go.mod` module
46
+ // path that 404s on `go get` plus `homepage`/`repository`/`bugs` URLs pointing
47
+ // at a repo that does not exist. The only escape was renaming the slug, which
48
+ // also renames the SDK classes: a public-API break, and no help at all to a
49
+ // project that has already published.
50
+ //
51
+ // main: kit: repo: {
52
+ // path: 'voxgig-sdk/voxgig-solardemo-sdk' # overrides <origin>/<slug>-sdk
53
+ // host: 'github.com' # default
54
+ // }
42
55
  function repoInfo(model: any) {
43
56
  const slug = model.name
44
57
  const origin = model.origin || 'voxgig-sdk'
45
- const repo = `${slug}-sdk`
46
- const repoUrl = `https://github.com/${origin}/${repo}`
58
+
59
+ const declared = (model && model.main && model.main[KIT] && model.main[KIT].repo) || {}
60
+
61
+ const host = '' === (declared.host || '') ? 'github.com' : (declared.host || 'github.com')
62
+ const path = '' === (declared.path || '') ? `${origin}/${slug}-sdk` : String(declared.path)
63
+
64
+ // Last segment is the repo; everything before it is the org (which may
65
+ // itself contain slashes on hosts that allow subgroups, e.g. GitLab).
66
+ const seg = path.split('/')
67
+ const repo = seg[seg.length - 1]
68
+
69
+ const repoUrl = `https://${host}/${path}`
70
+
47
71
  return {
48
72
  slug,
49
73
  origin,
74
+ host,
75
+ // 'org/repo' — the path under the host, and the base of a go module path.
76
+ path,
50
77
  repo,
51
78
  repoUrl,
52
79
  issuesUrl: `${repoUrl}/issues`,
@@ -58,6 +85,94 @@ function repoInfo(model: any) {
58
85
  }
59
86
 
60
87
 
88
+ // The go module path for a go-family target: the declared override, else the
89
+ // repo path plus the target's subdirectory.
90
+ //
91
+ // main: kit: target: go: module: path: 'github.com/acme/legacy-sdk/go'
92
+ //
93
+ // THE ONLY implementation. Twelve go components used to re-derive
94
+ // `github.com/${origin}/${name}-sdk/go` inline, so fixing the path in one
95
+ // place fixed nothing — and `ReadmeTop`, which prints the module in the root
96
+ // README's package table, lives inside node_modules where a consumer cannot
97
+ // patch it at all.
98
+ function goModule(model: any, target: string): string {
99
+ const declared = model?.main?.[KIT]?.target?.[target]?.module?.path
100
+ if (null != declared && '' !== declared) {
101
+ return String(declared)
102
+ }
103
+
104
+ const { host, path } = repoInfo(model)
105
+ return `${host}/${path}/${target}`
106
+ }
107
+
108
+
109
+ // The SDK's OWN release version, for this target's manifest and release tag.
110
+ //
111
+ // main: kit: target: ts: publish: version: '0.0.2'
112
+ //
113
+ // Defaults to '0.0.1' (the schema default), which is what every manifest
114
+ // emitter used to HARDCODE. That is why regeneration reset a published
115
+ // version: the value lived only in the generated output, so overwriting the
116
+ // output threw it away, and a project that had shipped 0.0.2 silently got a
117
+ // 0.0.1 manifest back. Declaring it in the model makes the manifest, the
118
+ // install docs and the port's VERSION file agree, and survive.
119
+ function packageVersion(model: any, target: string): string {
120
+ const declared = model?.main?.[KIT]?.target?.[target]?.publish?.version
121
+ return null != declared && '' !== declared ? String(declared) : '0.0.1'
122
+ }
123
+
124
+
125
+ // The Go language version for a go-family target's go.mod.
126
+ //
127
+ // main: kit: target: go: module: goversion: '1.23'
128
+ //
129
+ // Defaults to 1.21, the release that introduced `log/slog` — which sdkgen's
130
+ // own `log` feature template imports. The previous hardcoded `go 1.20` meant a
131
+ // generated SDK could not compile the feature source sdkgen had just written
132
+ // into it.
133
+ function goVersion(model: any, target: string, fallback?: string): string {
134
+ const declared = model?.main?.[KIT]?.target?.[target]?.module?.goversion
135
+ if (null != declared && '' !== declared) {
136
+ return String(declared)
137
+ }
138
+ return fallback || '1.21'
139
+ }
140
+
141
+
142
+ // The root Go package IDENTIFIER — `package voxgigsolardemosdk`. Go requires
143
+ // a plain identifier here, so unlike the module path it must be concatenated
144
+ // from the slug rather than taken from the repo.
145
+ //
146
+ // main: kit: target: go: module: package: 'acmesdk'
147
+ //
148
+ // The default concatenates `<origin><slug>sdk`, which DOUBLES the org prefix
149
+ // whenever the slug already carries it: slug `voxgig-solardemo` under origin
150
+ // `voxgig-sdk` produced `package voxgigvoxgigsolardemosdk`. A slug repeating
151
+ // its org is the natural shape for a repo named `<org>-<product>`, so the
152
+ // default now drops a leading origin prefix instead of restating it.
153
+ //
154
+ // This was the last of the four things the slug derives that had no override,
155
+ // and the only one that came out wrong — see the identity note at the top of
156
+ // model/sdkgen.aontu.
157
+ function goPackageIdent(model: any, target: string): string {
158
+ const declared = model?.main?.[KIT]?.target?.[target]?.module?.package
159
+ if (null != declared && '' !== declared) {
160
+ return String(declared)
161
+ }
162
+
163
+ const ident = (s: string) => String(s || '').replace(/[^a-z0-9]/gi, '').toLowerCase()
164
+
165
+ const org = ident((model.origin || 'voxgig-sdk').replace(/-sdk$/, ''))
166
+ let slug = ident(model.name)
167
+
168
+ if ('' !== org && slug.startsWith(org)) {
169
+ slug = slug.slice(org.length)
170
+ }
171
+
172
+ return org + slug + 'sdk'
173
+ }
174
+
175
+
61
176
  // Publication state of a target's package registry, tri-state + tag-only:
62
177
  // 'tag' — no registry (the go family); resolved from the git tag.
63
178
  // 'pending' — registry declared but the package is not uploaded yet
@@ -130,6 +245,25 @@ function packageName(model: any, eco: string): string {
130
245
  const origin = model.origin || 'voxgig-sdk'
131
246
  const base = origin.endsWith('-sdk') ? slug : `${slug}-sdk`
132
247
  const npmScoped = `@${origin}/${slug}${origin.endsWith('-sdk') ? '' : '-sdk'}`
248
+
249
+ // A target may name its published package outright — the escape hatch for a
250
+ // project whose registry name is not what the slug derives, and which cannot
251
+ // rename the slug without renaming its SDK classes:
252
+ //
253
+ // main: kit: target: ts: publish: registry: package: '@acme/legacy-client'
254
+ //
255
+ // The key already existed in the schema ("registry package name ('' ->
256
+ // derived)") and was simply never read. Keyed by TARGET, so the ecosystem
257
+ // aliases ('npm', 'pypi', ...) resolve to the target that publishes to them.
258
+ const ECO_TARGET: Record<string, string> = {
259
+ npm: 'ts', pypi: 'py', gem: 'rb', luarocks: 'lua', composer: 'php',
260
+ }
261
+ const declared = model?.main?.[KIT]?.target?.[ECO_TARGET[eco] || eco]
262
+ ?.publish?.registry?.package
263
+ if (null != declared && '' !== declared) {
264
+ return String(declared)
265
+ }
266
+
133
267
  switch (eco) {
134
268
  case 'npm':
135
269
  case 'ts':
@@ -147,11 +281,11 @@ function packageName(model: any, eco: string): string {
147
281
  case 'php':
148
282
  return `${origin}/${base}`
149
283
  case 'go':
150
- return `github.com/${origin}/${slug}-sdk/go`
284
+ return goModule(model, 'go')
151
285
  case 'go-cli':
152
- return `github.com/${origin}/${slug}-sdk/go-cli`
286
+ return goModule(model, 'go-cli')
153
287
  case 'go-mcp':
154
- return `github.com/${origin}/${slug}-sdk/go-mcp`
288
+ return goModule(model, 'go-mcp')
155
289
  // The notebook/analyst package layered on `py`. Distinct PyPI name so it
156
290
  // can version and publish independently of the SDK it wraps.
157
291
  case 'py-data':
@@ -214,11 +348,25 @@ function keywords(model: any): string[] {
214
348
  return ['voxgig', 'sdk', 'generated-sdk', 'openapi', 'api-client', model.name]
215
349
  }
216
350
 
217
- // A VALID uppercase env-var base derived from the slug: 'unsolicited-advice' ->
218
- // 'UNSOLICITED_ADVICE'. Use for <NAME>_APIKEY / <NAME>_TEST_LIVE so examples are
219
- // valid identifiers (model.NAME left a hyphen in, breaking process.env.X).
351
+ // A VALID uppercase env-var token: 'unsolicited-advice' -> 'UNSOLICITED_ADVICE'.
352
+ //
353
+ // THE ONLY WAY to build an env-var name segment. There used to be three
354
+ // spellings of this in the components — `envToken(name)`,
355
+ // `nom(x, 'NAME')` (the camel form uppercased, which SWALLOWS the hyphen) and
356
+ // `x.name.toUpperCase().replace(...)` — and they agree only while the name has
357
+ // no hyphen in it. A slug like `voxgig-solardemo` produced both
358
+ // `VOXGIG_SOLARDEMO_TEST_LIVE` and `VOXGIGSOLARDEMO_TEST_LIVE` in the SAME
359
+ // generated SDK: `test/utility.ts` read one, `PlanetEntity.test.ts` the other,
360
+ // so setting either sent half the suite live and left the rest mocked — with
361
+ // the suite reporting green either way.
362
+ function envToken(name: any): string {
363
+ return String(name || '').toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '')
364
+ }
365
+
366
+
367
+ // The env-var base for this SDK: <NAME>_APIKEY, <NAME>_TEST_LIVE, ...
220
368
  function envName(model: any): string {
221
- return String(model.name || '').toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '')
369
+ return envToken(model.name)
222
370
  }
223
371
 
224
372
  export {
@@ -240,4 +388,9 @@ export {
240
388
  nonAffiliation,
241
389
  keywords,
242
390
  envName,
391
+ envToken,
392
+ goModule,
393
+ goVersion,
394
+ goPackageIdent,
395
+ packageVersion,
243
396
  }