@voxgig/sdkgen 2.0.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/bin/voxgig-sdkgen +22 -2
  2. package/dist/action/doctor.d.ts +14 -0
  3. package/dist/action/doctor.js +351 -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/ExternalTarget.d.ts +2 -0
  13. package/dist/cmp/ExternalTarget.js +104 -0
  14. package/dist/cmp/ExternalTarget.js.map +1 -0
  15. package/dist/cmp/Feature.js +2 -1
  16. package/dist/cmp/Feature.js.map +1 -1
  17. package/dist/cmp/Main.js +5 -1
  18. package/dist/cmp/Main.js.map +1 -1
  19. package/dist/cmp/ReadmeExplanation.js +1 -1
  20. package/dist/cmp/ReadmeExplanation.js.map +1 -1
  21. package/dist/cmp/ReadmeTop.js +16 -6
  22. package/dist/cmp/ReadmeTop.js.map +1 -1
  23. package/dist/cmp/Registered.d.ts +7 -0
  24. package/dist/cmp/Registered.js +70 -0
  25. package/dist/cmp/Registered.js.map +1 -0
  26. package/dist/cmp/Test.js +3 -1
  27. package/dist/cmp/Test.js.map +1 -1
  28. package/dist/helpers/dryrun.d.ts +10 -0
  29. package/dist/helpers/dryrun.js +35 -0
  30. package/dist/helpers/dryrun.js.map +1 -0
  31. package/dist/helpers/featureSource.d.ts +13 -0
  32. package/dist/helpers/featureSource.js +156 -0
  33. package/dist/helpers/featureSource.js.map +1 -0
  34. package/dist/helpers/naming.d.ts +9 -1
  35. package/dist/helpers/naming.js +66 -2
  36. package/dist/helpers/naming.js.map +1 -1
  37. package/dist/helpers/opExample.js +23 -3
  38. package/dist/helpers/opExample.js.map +1 -1
  39. package/dist/helpers/opShape.d.ts +11 -1
  40. package/dist/helpers/opShape.js +51 -0
  41. package/dist/helpers/opShape.js.map +1 -1
  42. package/dist/helpers/packageMeta.d.ts +16 -1
  43. package/dist/helpers/packageMeta.js +181 -10
  44. package/dist/helpers/packageMeta.js.map +1 -1
  45. package/dist/helpers/stdrep.d.ts +3 -0
  46. package/dist/helpers/stdrep.js +47 -0
  47. package/dist/helpers/stdrep.js.map +1 -0
  48. package/dist/helpers/testPolicy.d.ts +2 -0
  49. package/dist/helpers/testPolicy.js +46 -0
  50. package/dist/helpers/testPolicy.js.map +1 -0
  51. package/dist/sdkgen.d.ts +15 -6
  52. package/dist/sdkgen.js +273 -5
  53. package/dist/sdkgen.js.map +1 -1
  54. package/dist/tsconfig.tsbuildinfo +1 -1
  55. package/dist/types.d.ts +12 -0
  56. package/dist/utility.js +10 -1
  57. package/dist/utility.js.map +1 -1
  58. package/model/sdkgen.aontu +245 -0
  59. package/package.json +5 -3
  60. package/project/.sdk/model/target/c.aontu +28 -3
  61. package/project/.sdk/model/target/clojure.aontu +24 -3
  62. package/project/.sdk/model/target/cpp.aontu +25 -3
  63. package/project/.sdk/model/target/csharp.aontu +25 -3
  64. package/project/.sdk/model/target/dart.aontu +15 -3
  65. package/project/.sdk/model/target/elixir.aontu +15 -3
  66. package/project/.sdk/model/target/go-cli.aontu +16 -1
  67. package/project/.sdk/model/target/go-mcp.aontu +16 -1
  68. package/project/.sdk/model/target/go.aontu +14 -4
  69. package/project/.sdk/model/target/haskell.aontu +24 -3
  70. package/project/.sdk/model/target/java.aontu +25 -3
  71. package/project/.sdk/model/target/js.aontu +15 -3
  72. package/project/.sdk/model/target/kotlin.aontu +25 -3
  73. package/project/.sdk/model/target/lean.aontu +24 -3
  74. package/project/.sdk/model/target/lua.aontu +15 -3
  75. package/project/.sdk/model/target/ocaml.aontu +24 -3
  76. package/project/.sdk/model/target/perl.aontu +15 -3
  77. package/project/.sdk/model/target/php.aontu +15 -3
  78. package/project/.sdk/model/target/py-data.aontu +15 -3
  79. package/project/.sdk/model/target/py.aontu +15 -3
  80. package/project/.sdk/model/target/rb.aontu +15 -3
  81. package/project/.sdk/model/target/rust.aontu +25 -3
  82. package/project/.sdk/model/target/scala.aontu +24 -3
  83. package/project/.sdk/model/target/seneca-provider.aontu +118 -0
  84. package/project/.sdk/model/target/swift.aontu +25 -3
  85. package/project/.sdk/model/target/ts.aontu +15 -3
  86. package/project/.sdk/model/target/zig.aontu +25 -3
  87. package/project/.sdk/src/cmp/c/Config_c.ts +10 -11
  88. package/project/.sdk/src/cmp/c/Entity_c.ts +5 -1
  89. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +23 -5
  90. package/project/.sdk/src/cmp/c/fragment/EntityCreateOp.fragment.c +9 -2
  91. package/project/.sdk/src/cmp/c/fragment/EntityListOp.fragment.c +19 -2
  92. package/project/.sdk/src/cmp/c/fragment/EntityLoadOp.fragment.c +9 -2
  93. package/project/.sdk/src/cmp/c/fragment/EntityRemoveOp.fragment.c +12 -2
  94. package/project/.sdk/src/cmp/c/fragment/EntityUpdateOp.fragment.c +9 -2
  95. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -0
  96. package/project/.sdk/src/cmp/clojure/TestEntity_clojure.ts +6 -3
  97. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -1
  98. package/project/.sdk/src/cmp/clojure/fragment/EntityCreateOp.fragment.clj +2 -2
  99. package/project/.sdk/src/cmp/clojure/fragment/EntityLoadOp.fragment.clj +2 -2
  100. package/project/.sdk/src/cmp/clojure/fragment/EntityRemoveOp.fragment.clj +12 -8
  101. package/project/.sdk/src/cmp/clojure/fragment/EntityUpdateOp.fragment.clj +2 -2
  102. package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +5 -1
  103. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +12 -9
  104. package/project/.sdk/src/cmp/cpp/fragment/EntityCreateOp.fragment.cpp +8 -2
  105. package/project/.sdk/src/cmp/cpp/fragment/EntityListOp.fragment.cpp +18 -2
  106. package/project/.sdk/src/cmp/cpp/fragment/EntityLoadOp.fragment.cpp +8 -2
  107. package/project/.sdk/src/cmp/cpp/fragment/EntityRemoveOp.fragment.cpp +11 -2
  108. package/project/.sdk/src/cmp/cpp/fragment/EntityUpdateOp.fragment.cpp +8 -2
  109. package/project/.sdk/src/cmp/csharp/Package_csharp.ts +2 -1
  110. package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
  111. package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +6 -6
  112. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +38 -1
  113. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +42 -33
  114. package/project/.sdk/src/cmp/dart/Package_dart.ts +2 -1
  115. package/project/.sdk/src/cmp/dart/ReadmeEntity_dart.ts +13 -2
  116. package/project/.sdk/src/cmp/dart/ReadmeHowto_dart.ts +2 -1
  117. package/project/.sdk/src/cmp/dart/ReadmeInstall_dart.ts +3 -3
  118. package/project/.sdk/src/cmp/dart/ReadmeModel_dart.ts +1 -1
  119. package/project/.sdk/src/cmp/dart/ReadmeQuick_dart.ts +17 -6
  120. package/project/.sdk/src/cmp/dart/ReadmeRef_dart.ts +13 -2
  121. package/project/.sdk/src/cmp/dart/ReadmeTopQuick_dart.ts +13 -2
  122. package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +3 -3
  123. package/project/.sdk/src/cmp/dart/TestEntity_dart.ts +8 -8
  124. package/project/.sdk/src/cmp/dart/fragment/EntityBase.fragment.dart +18 -1
  125. package/project/.sdk/src/cmp/dart/fragment/EntityCreateOp.fragment.dart +9 -1
  126. package/project/.sdk/src/cmp/dart/fragment/EntityLoadOp.fragment.dart +9 -1
  127. package/project/.sdk/src/cmp/dart/fragment/EntityRemoveOp.fragment.dart +15 -1
  128. package/project/.sdk/src/cmp/dart/fragment/EntityUpdateOp.fragment.dart +9 -1
  129. package/project/.sdk/src/cmp/dart/fragment/SdkError.fragment.dart +8 -0
  130. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +3 -1
  131. package/project/.sdk/src/cmp/elixir/ReadmeInstall_elixir.ts +2 -2
  132. package/project/.sdk/src/cmp/elixir/TestEntity_elixir.ts +11 -2
  133. package/project/.sdk/src/cmp/elixir/fragment/EntityCreateOp.fragment.ex +2 -1
  134. package/project/.sdk/src/cmp/elixir/fragment/EntityListOp.fragment.ex +1 -0
  135. package/project/.sdk/src/cmp/elixir/fragment/EntityLoadOp.fragment.ex +2 -1
  136. package/project/.sdk/src/cmp/elixir/fragment/EntityRemoveOp.fragment.ex +4 -1
  137. package/project/.sdk/src/cmp/elixir/fragment/EntityUpdateOp.fragment.ex +2 -1
  138. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +38 -8
  139. package/project/.sdk/src/cmp/go/Entity_go.ts +2 -2
  140. package/project/.sdk/src/cmp/go/Main_go.ts +4 -5
  141. package/project/.sdk/src/cmp/go/Package_go.ts +8 -5
  142. package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +2 -2
  143. package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +2 -2
  144. package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +4 -2
  145. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +2 -2
  146. package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +2 -2
  147. package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +2 -2
  148. package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +2 -2
  149. package/project/.sdk/src/cmp/go/TestDirect_go.ts +21 -15
  150. package/project/.sdk/src/cmp/go/TestEntity_go.ts +9 -9
  151. package/project/.sdk/src/cmp/go/Test_go.ts +2 -2
  152. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +42 -1
  153. package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +4 -4
  154. package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +4 -4
  155. package/project/.sdk/src/cmp/haskell/Package_haskell.ts +2 -1
  156. package/project/.sdk/src/cmp/haskell/ReadmeEntity_haskell.ts +10 -5
  157. package/project/.sdk/src/cmp/haskell/ReadmeModel_haskell.ts +10 -8
  158. package/project/.sdk/src/cmp/haskell/ReadmeQuick_haskell.ts +14 -10
  159. package/project/.sdk/src/cmp/haskell/ReadmeRef_haskell.ts +21 -18
  160. package/project/.sdk/src/cmp/haskell/ReadmeTopQuick_haskell.ts +4 -4
  161. package/project/.sdk/src/cmp/haskell/Test_haskell.ts +23 -11
  162. package/project/.sdk/src/cmp/java/Package_java.ts +2 -1
  163. package/project/.sdk/src/cmp/java/ReadmeHowto_java.ts +2 -1
  164. package/project/.sdk/src/cmp/java/ReadmeInstall_java.ts +2 -2
  165. package/project/.sdk/src/cmp/java/ReadmeModel_java.ts +1 -1
  166. package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +3 -3
  167. package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
  168. package/project/.sdk/src/cmp/java/TestEntity_java.ts +6 -6
  169. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +34 -1
  170. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +12 -0
  171. package/project/.sdk/src/cmp/js/Main_js.ts +4 -1
  172. package/project/.sdk/src/cmp/js/Package_js.ts +7 -1
  173. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +13 -2
  174. package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +2 -1
  175. package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +13 -2
  176. package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +13 -2
  177. package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +2 -1
  178. package/project/.sdk/src/cmp/js/TestDirect_js.ts +3 -3
  179. package/project/.sdk/src/cmp/js/TestEntity_js.ts +8 -8
  180. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +22 -1
  181. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +9 -1
  182. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +9 -1
  183. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +15 -1
  184. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +9 -1
  185. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +13 -0
  186. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +2 -1
  187. package/project/.sdk/src/cmp/kotlin/ReadmeHowto_kotlin.ts +2 -1
  188. package/project/.sdk/src/cmp/kotlin/ReadmeInstall_kotlin.ts +2 -2
  189. package/project/.sdk/src/cmp/kotlin/ReadmeModel_kotlin.ts +1 -1
  190. package/project/.sdk/src/cmp/kotlin/ReadmeQuick_kotlin.ts +3 -3
  191. package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
  192. package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +6 -6
  193. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +32 -1
  194. package/project/.sdk/src/cmp/lean/Package_lean.ts +3 -1
  195. package/project/.sdk/src/cmp/lua/MainEntity_lua.ts +9 -4
  196. package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -3
  197. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +11 -3
  198. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +1 -1
  199. package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
  200. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +9 -9
  201. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +37 -1
  202. package/project/.sdk/src/cmp/lua/fragment/SdkError.fragment.lua +12 -0
  203. package/project/.sdk/src/cmp/ocaml/EntityOperation_ocaml.ts +30 -3
  204. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +11 -5
  205. package/project/.sdk/src/cmp/ocaml/Package_ocaml.ts +3 -1
  206. package/project/.sdk/src/cmp/ocaml/ReadmeEntity_ocaml.ts +10 -5
  207. package/project/.sdk/src/cmp/ocaml/ReadmeHowto_ocaml.ts +6 -2
  208. package/project/.sdk/src/cmp/ocaml/ReadmeModel_ocaml.ts +10 -8
  209. package/project/.sdk/src/cmp/ocaml/ReadmeQuick_ocaml.ts +14 -13
  210. package/project/.sdk/src/cmp/ocaml/ReadmeRef_ocaml.ts +20 -18
  211. package/project/.sdk/src/cmp/ocaml/ReadmeTopQuick_ocaml.ts +4 -4
  212. package/project/.sdk/src/cmp/ocaml/ReadmeTopTest_ocaml.ts +8 -2
  213. package/project/.sdk/src/cmp/ocaml/TestEntity_ocaml.ts +8 -5
  214. package/project/.sdk/src/cmp/perl/ReadmeHowto_perl.ts +2 -1
  215. package/project/.sdk/src/cmp/perl/ReadmeModel_perl.ts +1 -1
  216. package/project/.sdk/src/cmp/perl/ReadmeQuick_perl.ts +3 -3
  217. package/project/.sdk/src/cmp/perl/ReadmeTopQuick_perl.ts +1 -1
  218. package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
  219. package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +6 -6
  220. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +36 -1
  221. package/project/.sdk/src/cmp/php/MainEntity_php.ts +21 -16
  222. package/project/.sdk/src/cmp/php/Package_php.ts +2 -2
  223. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +6 -6
  224. package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +4 -3
  225. package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +2 -2
  226. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +1 -1
  227. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +12 -12
  228. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +6 -6
  229. package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +4 -4
  230. package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +2 -2
  231. package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
  232. package/project/.sdk/src/cmp/php/TestEntity_php.ts +17 -15
  233. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +20 -1
  234. package/project/.sdk/src/cmp/php/fragment/SdkError.fragment.php +11 -0
  235. package/project/.sdk/src/cmp/py/Package_py.ts +4 -3
  236. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +13 -2
  237. package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +2 -1
  238. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +1 -1
  239. package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +17 -6
  240. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +14 -3
  241. package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +13 -2
  242. package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
  243. package/project/.sdk/src/cmp/py/TestEntity_py.ts +9 -9
  244. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +29 -1
  245. package/project/.sdk/src/cmp/py/fragment/SdkError.fragment.py +11 -0
  246. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +2 -1
  247. package/project/.sdk/src/cmp/rb/Package_rb.ts +4 -3
  248. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +1 -1
  249. package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +2 -1
  250. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +5 -5
  251. package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +1 -1
  252. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
  253. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +9 -9
  254. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +31 -1
  255. package/project/.sdk/src/cmp/rb/fragment/SdkError.fragment.rb +10 -1
  256. package/project/.sdk/src/cmp/rust/Entity_rust.ts +5 -1
  257. package/project/.sdk/src/cmp/rust/Main_rust.ts +21 -0
  258. package/project/.sdk/src/cmp/rust/Package_rust.ts +2 -1
  259. package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
  260. package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +12 -12
  261. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +18 -0
  262. package/project/.sdk/src/cmp/rust/fragment/EntityCreateOp.fragment.rs +8 -2
  263. package/project/.sdk/src/cmp/rust/fragment/EntityListOp.fragment.rs +20 -3
  264. package/project/.sdk/src/cmp/rust/fragment/EntityLoadOp.fragment.rs +8 -2
  265. package/project/.sdk/src/cmp/rust/fragment/EntityRemoveOp.fragment.rs +10 -2
  266. package/project/.sdk/src/cmp/rust/fragment/EntityUpdateOp.fragment.rs +8 -2
  267. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +10 -0
  268. package/project/.sdk/src/cmp/scala/ReadmeHowto_scala.ts +2 -1
  269. package/project/.sdk/src/cmp/scala/ReadmeInstall_scala.ts +3 -3
  270. package/project/.sdk/src/cmp/scala/ReadmeModel_scala.ts +1 -1
  271. package/project/.sdk/src/cmp/scala/ReadmeQuick_scala.ts +3 -3
  272. package/project/.sdk/src/cmp/scala/TestEntity_scala.ts +3 -3
  273. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +27 -1
  274. package/project/.sdk/src/cmp/seneca-provider/Extras_seneca-provider.ts +3915 -0
  275. package/project/.sdk/src/cmp/seneca-provider/Main_seneca-provider.ts +960 -0
  276. package/project/.sdk/src/cmp/swift/ReadmeHowto_swift.ts +2 -1
  277. package/project/.sdk/src/cmp/swift/ReadmeInstall_swift.ts +3 -3
  278. package/project/.sdk/src/cmp/swift/ReadmeModel_swift.ts +1 -1
  279. package/project/.sdk/src/cmp/swift/ReadmeQuick_swift.ts +3 -3
  280. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +34 -1
  281. package/project/.sdk/src/cmp/ts/EntityOperation_ts.ts +9 -1
  282. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +18 -1
  283. package/project/.sdk/src/cmp/ts/Gitignore_ts.ts +5 -2
  284. package/project/.sdk/src/cmp/ts/Main_ts.ts +4 -1
  285. package/project/.sdk/src/cmp/ts/Package_ts.ts +10 -1
  286. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +13 -2
  287. package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +2 -1
  288. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +21 -6
  289. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +52 -2
  290. package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +14 -3
  291. package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +34 -2
  292. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +64 -43
  293. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +8 -8
  294. package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +2 -2
  295. package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +2 -2
  296. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +25 -1
  297. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +10 -2
  298. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +1 -1
  299. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +10 -2
  300. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +27 -3
  301. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +10 -2
  302. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +15 -0
  303. package/project/.sdk/src/cmp/zig/Entity_zig.ts +5 -1
  304. package/project/.sdk/src/cmp/zig/Package_zig.ts +3 -1
  305. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +39 -0
  306. package/project/.sdk/src/cmp/zig/fragment/EntityCreateOp.fragment.zig +2 -2
  307. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +21 -2
  308. package/project/.sdk/src/cmp/zig/fragment/EntityLoadOp.fragment.zig +2 -2
  309. package/project/.sdk/src/cmp/zig/fragment/EntityRemoveOp.fragment.zig +5 -2
  310. package/project/.sdk/src/cmp/zig/fragment/EntityUpdateOp.fragment.zig +2 -2
  311. package/project/.sdk/tm/c/VERSION +1 -1
  312. package/project/.sdk/tm/c/core/helpers.c +1 -0
  313. package/project/.sdk/tm/c/core/sdk.h +22 -6
  314. package/project/.sdk/tm/c/tests/feature_harness.h +1 -0
  315. package/project/.sdk/tm/c/tests/primary_utility_test.c +4 -1
  316. package/project/.sdk/tm/c/utility/make_url.c +1 -0
  317. package/project/.sdk/tm/c/utility/param.c +1 -0
  318. package/project/.sdk/tm/clojure/VERSION +1 -1
  319. package/project/.sdk/tm/cpp/VERSION +1 -1
  320. package/project/.sdk/tm/cpp/core/types.hpp +33 -8
  321. package/project/.sdk/tm/cpp/test/pipeline_test.cpp +5 -0
  322. package/project/.sdk/tm/cpp/test/runner_support.hpp +4 -4
  323. package/project/.sdk/tm/csharp/VERSION +1 -1
  324. package/project/.sdk/tm/csharp/core/Types.cs +6 -0
  325. package/project/.sdk/tm/csharp/test/FeatureHarness.cs +396 -0
  326. package/project/.sdk/tm/csharp/test/FeatureTest.cs +7 -385
  327. package/project/.sdk/tm/csharp/test/Runner.cs +4 -4
  328. package/project/.sdk/tm/dart/lib/utility/MakeErrorUtility.dart +4 -0
  329. package/project/.sdk/tm/dart/test/utility.dart +4 -4
  330. package/project/.sdk/tm/elixir/VERSION +1 -1
  331. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +26 -0
  332. package/project/.sdk/tm/go/VERSION +1 -1
  333. package/project/.sdk/tm/go/core/types.go +6 -0
  334. package/project/.sdk/tm/go/test/feature_harness_test.go +361 -0
  335. package/project/.sdk/tm/go/test/feature_test.go +7 -350
  336. package/project/.sdk/tm/go/test/pipeline_test.go +6 -0
  337. package/project/.sdk/tm/go/test/runner_test.go +16 -4
  338. package/project/.sdk/tm/haskell/VERSION +1 -1
  339. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +28 -5
  340. package/project/.sdk/tm/haskell/src/SdkTypes.hs +14 -5
  341. package/project/.sdk/tm/java/VERSION +1 -1
  342. package/project/.sdk/tm/java/test/RunnerSupport.java +4 -4
  343. package/project/.sdk/tm/java/utility/MakeError.java +4 -0
  344. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +4 -0
  345. package/project/.sdk/tm/js/test/utility.js +3 -3
  346. package/project/.sdk/tm/kotlin/VERSION +1 -1
  347. package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +3 -3
  348. package/project/.sdk/tm/lean/VERSION +1 -1
  349. package/project/.sdk/tm/lean/test/TFeature.lean +27 -14
  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/seneca-provider/CODE_OF_CONDUCT.md +132 -0
  370. package/project/.sdk/tm/seneca-provider/LICENSE +21 -0
  371. package/project/.sdk/tm/seneca-provider/Makefile +15 -0
  372. package/project/.sdk/tm/seneca-provider/src/tsconfig.json +18 -0
  373. package/project/.sdk/tm/seneca-provider/test/tsconfig.json +16 -0
  374. package/project/.sdk/tm/seneca-provider/tsfmt.json +3 -0
  375. package/project/.sdk/tm/swift/VERSION +1 -1
  376. package/project/.sdk/tm/ts/src/tsconfig.json +1 -0
  377. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +4 -0
  378. package/project/.sdk/tm/ts/test/tsconfig.json +1 -0
  379. package/project/.sdk/tm/ts/test/utility.ts +3 -3
  380. package/project/.sdk/tm/zig/VERSION +1 -1
  381. package/src/action/doctor.ts +475 -0
  382. package/src/action/feature.ts +54 -16
  383. package/src/action/target.ts +174 -25
  384. package/src/cmp/Entity.ts +7 -0
  385. package/src/cmp/ExternalTarget.ts +125 -0
  386. package/src/cmp/Feature.ts +3 -1
  387. package/src/cmp/Main.ts +7 -1
  388. package/src/cmp/ReadmeExplanation.ts +2 -2
  389. package/src/cmp/ReadmeTop.ts +22 -9
  390. package/src/cmp/Registered.ts +100 -0
  391. package/src/cmp/Test.ts +4 -1
  392. package/src/helpers/dryrun.ts +57 -0
  393. package/src/helpers/featureSource.ts +208 -0
  394. package/src/helpers/naming.ts +73 -2
  395. package/src/helpers/opExample.ts +19 -2
  396. package/src/helpers/opShape.ts +65 -0
  397. package/src/helpers/packageMeta.ts +211 -10
  398. package/src/helpers/stdrep.ts +56 -0
  399. package/src/helpers/testPolicy.ts +52 -0
  400. package/src/sdkgen.ts +350 -5
  401. package/src/types.ts +24 -1
  402. package/src/utility.ts +10 -1
  403. package/project/.sdk/tm/rust/feature/mod.rs +0 -24
@@ -0,0 +1,960 @@
1
+ import {
2
+ cmp, each,
3
+ File, Content, Copy, Folder,
4
+ entityCollection, entityOps, entityIdField, entityClassName,
5
+ opRequestShape, opParams, entityPath,
6
+ collectDeps, repoInfo, packageName, packageVersion, apiName, envName,
7
+ authorInfo, contributorList, isAuthActive, jsKey, jsProp,
8
+ SdkGenError,
9
+ PUBLISHER, PUBLISHER_URL,
10
+ } from '@voxgig/sdkgen'
11
+
12
+ import {
13
+ KIT,
14
+ } from '@voxgig/apidef'
15
+
16
+ import { Tests, Scripts, Workflow, Readme, Docs } from './Extras_seneca-provider'
17
+
18
+
19
+ // The `seneca-provider` target: a Seneca plugin exposing this API's entities
20
+ // as Seneca entities (`provider/<name>/<entity>`), layered on the sibling
21
+ // `ts` SDK.
22
+ //
23
+ // A consumer target in the go-cli / py-data mould — every standard phase is
24
+ // off in model/target/seneca-provider.aontu and this component emits the
25
+ // whole package. It differs from those in one way that shapes everything
26
+ // here: it generates into ITS OWN REPO (`output: path`), depends on the SDK
27
+ // as a PUBLISHED npm package rather than by path, and therefore carries a
28
+ // repo's worth of furniture rather than a subfolder's.
29
+ //
30
+ // SHAPE OF THE MAPPING
31
+ //
32
+ // Seneca's store commands are list / load / save / remove. The SDK's are
33
+ // list / load / create / update / remove. `save` is the one that is not
34
+ // one-to-one: Seneca's convention is that an entity carrying an id is an
35
+ // update and one without is a create, so `save` dispatches on `data.id`.
36
+ //
37
+ // Everything else follows from the model:
38
+ // - which cmds exist at all, from the entity's declared ops;
39
+ // - the required path params of each op, which become argument guards (a
40
+ // nested entity like `moon` under `/planet/{planet_id}/moon` cannot build
41
+ // its URL without the parent id, and an opaque 404 from a half-built URL
42
+ // is a bad error message);
43
+ // - the SDK accessor and entity class names, from the same helpers the ts
44
+ // target uses, so the two cannot drift.
45
+
46
+
47
+ // Seneca store cmd -> the SDK ops it needs. `save` needs BOTH create and
48
+ // update; it is emitted when either is present and dispatches on the id.
49
+ const CMD_OPS: Record<string, string[]> = {
50
+ list: ['list'],
51
+ load: ['load'],
52
+ save: ['create', 'update'],
53
+ remove: ['remove'],
54
+ }
55
+
56
+
57
+ // The required (non-optional) request keys of an op, id first. These are what
58
+ // the SDK needs to build the path, so they are what the provider must have
59
+ // before it calls.
60
+ function requiredKeys(ent: any, opname: string): string[] {
61
+ const idf = entityIdField(ent)
62
+ return opRequestShape(ent, opname).items
63
+ .filter((it: any) => !it.optional)
64
+ .map((it: any) => it.name)
65
+ .sort((a: string, b: string) => (a === idf ? 0 : 1) - (b === idf ? 0 : 1))
66
+ }
67
+
68
+
69
+ // The key that addresses ONE record.
70
+ //
71
+ // `entityIdField` answers whenever the model declares one, which apidef does
72
+ // for any entity carrying a field literally named `id` — and it renames an
73
+ // `<entity>_id` path param to `id` besides, which is why most APIs never reach
74
+ // the fallback.
75
+ //
76
+ // When it does NOT answer, the record key is the LAST required path param of a
77
+ // single-item op: a route addresses parents first and the record last, by
78
+ // construction. Without this the key was simply unknown, so a param named
79
+ // `code` failed the `!== idf` test in opParentKeys and was classified as a
80
+ // PARENT — `load$('SAVE20')` threw "coupon load: code is required" instead of
81
+ // loading anything, and the entity was treated as nested throughout.
82
+ function recordKey(ent: any): string {
83
+ const idf = entityIdField(ent)
84
+ if (null != idf && '' !== idf) {
85
+ return String(idf)
86
+ }
87
+
88
+ for (const opname of ['load', 'remove', 'update']) {
89
+ const op = (ent.op || {})[opname]
90
+ if (null == op) {
91
+ continue
92
+ }
93
+
94
+ const params = opParams(op).filter((p: any) => false !== p.reqd)
95
+ if (0 < params.length) {
96
+ return String((params[params.length - 1] as any).name)
97
+ }
98
+ }
99
+
100
+ return 'id'
101
+ }
102
+
103
+
104
+ // The guard function's name. Spec-derived param names are not constrained to
105
+ // identifiers — Evervault's `/payments/3ds-sessions/{3ds_session_id}` is the
106
+ // standing example — and a name is a DECLARATION here, so it cannot be
107
+ // bracket-quoted the way a property access can. Non-identifier characters are
108
+ // replaced rather than dropped, so `a-b` and `a_b` cannot collide.
109
+ function guardName(e: any, key: string): string {
110
+ return `need_${e.name}_${String(key).replace(/[^A-Za-z0-9_$]/g, '_')}`
111
+ .replace(/^need_(\d)/, 'need__$1')
112
+ }
113
+
114
+
115
+ // The parent PATH params of ONE op: `moon`'s load under
116
+ // `/planet/{planet_id}/moon/{id}` yields ['planet_id']. These are the keys a
117
+ // caller can forget, so each gets a guard.
118
+ //
119
+ // From opParams — the op's declared path params — NOT from opRequestShape.
120
+ // For create/update the latter also returns the request BODY fields, so
121
+ // reading it here generated a "planet name is required" guard for every
122
+ // writable field on every entity.
123
+ function opParentKeys(ent: any, opname: string): string[] {
124
+ const rk = recordKey(ent)
125
+ const op = (ent.op || {})[opname]
126
+
127
+ if (null == op) {
128
+ return []
129
+ }
130
+
131
+ const seen = new Set<string>()
132
+
133
+ for (const p of opParams(op)) {
134
+ const name = String((p as any).name)
135
+ if (false !== (p as any).reqd && name !== rk && name !== 'id') {
136
+ seen.add(name)
137
+ }
138
+ }
139
+
140
+ return [...seen].sort()
141
+ }
142
+
143
+
144
+ // Every parent key the entity has, across its ACTIVE ops — for the seed data
145
+ // and the docs, which describe the entity rather than one call.
146
+ //
147
+ // `entityOps` and not `Object.keys(ent.op)`: an op the model marks
148
+ // `active: false` generates no SDK method, so letting it contribute a key
149
+ // here put a mandatory guard for a parameter of a call that does not exist
150
+ // onto every cmd that does.
151
+ function parentKeys(ent: any): string[] {
152
+ const seen = new Set<string>()
153
+
154
+ for (const opname of entityOps(ent)) {
155
+ for (const key of opParentKeys(ent, opname)) {
156
+ seen.add(key)
157
+ }
158
+ }
159
+
160
+ return [...seen].sort()
161
+ }
162
+
163
+
164
+ // A model field's broad shape, for generating seed data that reads as data.
165
+ // The model carries canon strings (`\`$STRING\``), not JS types.
166
+ //
167
+ // ORDER MATTERS and the tests are substring tests, so the container kinds are
168
+ // checked FIRST: a multi-type field's sentinel is the ARRAY
169
+ // `['`$ONE`', [members...]]`, and String() flattens it to a comma-joined
170
+ // string — so a `$ONE` of string|number matched `includes('NUMBER')` and was
171
+ // seeded as a bare number. A union is not a number; it is whatever its first
172
+ // member is, and falling back to a string is the safe answer.
173
+ //
174
+ // `$ARRAY` and `$OBJECT` are in the sentinel vocabulary (see
175
+ // helpers/canonType.ts) and used to fall through to 'string', which put
176
+ // `tags: 'quick-tags'` into test/quick.js — a type-incorrect body that a
177
+ // validating server rejects.
178
+ function fieldKind(type: any): string {
179
+ if (Array.isArray(type)) {
180
+ return 'string'
181
+ }
182
+
183
+ const t = String(type || '').toUpperCase()
184
+
185
+ if (t.includes('ARRAY') || t.includes('LIST')) return 'array'
186
+ if (t.includes('OBJECT') || t.includes('MAP')) return 'object'
187
+ if (t.includes('BOOLEAN')) return 'boolean'
188
+ if (t.includes('NUMBER') || t.includes('INTEGER')) return 'number'
189
+
190
+ return 'string'
191
+ }
192
+
193
+
194
+ // Which entity a parent path param refers to: `planet_id` -> `planet`, but
195
+ // only when an entity of that name actually exists. A key that names no
196
+ // entity gets no cross-reference, and the seed falls back to a plain string.
197
+ function parentEntityOf(key: string, names: string[]): string {
198
+ const stem = key.replace(/_id$/, '')
199
+ return names.includes(stem) ? stem : ''
200
+ }
201
+
202
+
203
+ // The repo this provider is released from — NOT the SDK's. A provider is its
204
+ // own package in its own repo, so its manifest's homepage/repository must
205
+ // point there; deriving them from `main: kit: repo` sends every link in the
206
+ // published package to the SDK instead.
207
+ //
208
+ // Order: the project's `output: repo`, else the Seneca convention.
209
+ function providerRepo(model: any, lower: string): { url: string, path: string } {
210
+ const host = model?.main?.[KIT]?.repo?.host || 'github.com'
211
+ const declared = model?.main?.[KIT]?.target?.['seneca-provider']?.output?.repo
212
+ const path = null != declared && '' !== declared ?
213
+ String(declared) : `senecajs/seneca-${lower}-provider`
214
+
215
+ return { url: `https://${host}/${path}`, path }
216
+ }
217
+
218
+
219
+ // The provider's published package name: the project's pin when it has one,
220
+ // else `@seneca/<name>-provider`. packageName() cannot answer this — its
221
+ // derivations are all SDK-shaped (`@<origin>/<slug>-sdk`).
222
+ function providerPackage(model: any, lower: string): string {
223
+ const declared = model?.main?.[KIT]?.target?.['seneca-provider']
224
+ ?.publish?.registry?.package
225
+ return null != declared && '' !== declared ?
226
+ String(declared) : `@seneca/${lower}-provider`
227
+ }
228
+
229
+
230
+ const Main = cmp(function Main(props: any) {
231
+ const { target, ctx$ } = props
232
+ const { model } = ctx$
233
+
234
+ // HARD REQUIREMENT: this plugin imports the TypeScript SDK. Generating it
235
+ // without `ts` produces a package whose every import fails, so fail at
236
+ // GENERATE time with an actionable message instead.
237
+ const targets = model.main[KIT].target || {}
238
+ if (null == targets.ts) {
239
+ throw new SdkGenError(
240
+ 'seneca-provider requires the `ts` target in the same SDK: it imports ' +
241
+ 'the TypeScript SDK that `ts` generates. Add it with:\n' +
242
+ ' npm run add-target ts\n' +
243
+ 'then regenerate.')
244
+ }
245
+
246
+ const Name = model.const.Name // Solardemo
247
+ const lower = String(model.const.name) // solardemo
248
+ const ENV = envName(model) // SOLARDEMO
249
+ const sdkClass = `${Name}SDK` // SolardemoSDK
250
+ const pluginName = `${Name}Provider` // SolardemoProvider
251
+ const fileBase = `${lower}-provider` // solardemo-provider
252
+
253
+ // The SDK is a PUBLISHED dependency, not a path: this package lives in its
254
+ // own repo. Its name is whatever the ts target publishes under, pin
255
+ // included, so the two can never disagree.
256
+ const sdkPkg = packageName(model, 'npm')
257
+ const sdkVersion = packageVersion(model, 'ts')
258
+
259
+ // UNFILTERED by design — see the AGENTS.md sharp edge: entityCollection is
260
+ // the resolver every component must use (getModelPath rebuilds its container
261
+ // per call, defeating the class-name memo), and it deliberately includes
262
+ // inactive entities because the typed-model emitters need them.
263
+ //
264
+ // Which makes filtering `active` the CALLER's job, and this component was
265
+ // the one consumer target that skipped it — go-cli, go-mcp and py-data all
266
+ // re-filter. The cost: MainEntity_ts emits an accessor only for an ACTIVE
267
+ // entity, so an inactive one produced `this.shared.sdk.Ghost()` in the
268
+ // provider and an `assert.equal(typeof sdk.Ghost, 'function')` in its tests,
269
+ // against a method the SDK does not have.
270
+ const entityColl = entityCollection(model)
271
+
272
+ const activeEntities = Object.keys(entityColl).sort()
273
+ .map((key: string) => entityColl[key])
274
+ .filter((ent: any) => false !== ent.active)
275
+
276
+ // Entities this provider can serve: those with at least one op that maps to
277
+ // a Seneca store cmd. An entity with no such op would produce an empty cmd
278
+ // map, which seneca-entity treats as a store that answers nothing.
279
+ const entityNames = activeEntities.map((ent: any) => ent.name)
280
+
281
+ const entities = activeEntities
282
+ .map((ent: any) => {
283
+ const parents = parentKeys(ent)
284
+
285
+ // The parent entity PER KEY. Deriving it from `parents[0]` alone left an
286
+ // entity nested two levels deep with no cross-reference for its outer
287
+ // parents, so their seed values came out as the literal '0'.
288
+ const parentOf: Record<string, string> = {}
289
+ for (const key of parents) {
290
+ parentOf[key] = parentEntityOf(key, entityNames)
291
+ }
292
+
293
+ // The parent keys of each op SEPARATELY. The guards used to be the union
294
+ // across all ops, applied to every cmd alike, while the argument handed
295
+ // to the SDK was computed per op — so an entity whose routes are not
296
+ // uniformly nested (a flat `load`, a nested `create`) demanded a
297
+ // parameter its own call would never use.
298
+ const opParents: Record<string, string[]> = {}
299
+ for (const opname of entityOps(ent)) {
300
+ opParents[opname] = opParentKeys(ent, opname)
301
+ }
302
+
303
+ return {
304
+ ent,
305
+ name: ent.name,
306
+ // The SDK ACCESSOR on the client (`client.Moon()`), which is the
307
+ // entity's PascalCase name — NOT entityClassName, which is the
308
+ // collision-safe CLASS name the accessor constructs (`MoonEntity`).
309
+ // Calling the class name reads plausibly and fails at runtime with
310
+ // "sdk.MoonEntity is not a function". MainEntity_ts is the authority
311
+ // for this: it declares the method as `${entity.Name}()`.
312
+ acc: ent.Name,
313
+ // The entity's canonical route, used to probe the live server for
314
+ // liveness. Path params are left in place only if the route has
315
+ // them — a collection route (the `list` op's) has none, which is why
316
+ // entityPath prefers it.
317
+ path: entityPath(ent),
318
+ cls: entityClassName(ent, entityColl),
319
+ ops: entityOps(ent),
320
+ idf: entityIdField(ent),
321
+ parents,
322
+ parentOf,
323
+ opParents,
324
+ // The entity the FIRST parent key points at. Kept because the docs and
325
+ // the scripts speak about "the parent" in the singular; anything that
326
+ // must be right per key reads parentOf.
327
+ parentEntity: 0 < parents.length ? parentOf[parents[0]] : '',
328
+ // Required fields only: a seed record has to satisfy the shape the
329
+ // SDK will hand back, and optional noise makes the assertions
330
+ // harder to read.
331
+ //
332
+ // A parent path param is then FORCED IN even when the entity's own
333
+ // schema omits it or marks it optional. A path param is a routing key,
334
+ // not necessarily a response field: when the child's schema left it
335
+ // out the seeded record had no link back to its parent, and the mock's
336
+ // match found nothing — which the nested `load` test reported as a
337
+ // TypeError and the nested `list` test reported as a pass.
338
+ fields: (() => {
339
+ const req = (ent.fields || [])
340
+ .filter((f: any) => false !== f.req)
341
+ .map((f: any) => ({
342
+ name: f.name,
343
+ kind: fieldKind(f.type),
344
+ parentEntity: parentEntityOf(f.name, entityNames),
345
+ }))
346
+
347
+ const have = new Set(req.map((f: any) => f.name))
348
+
349
+ for (const key of parents) {
350
+ if (!have.has(key)) {
351
+ req.push({
352
+ name: key,
353
+ kind: 'string',
354
+ parentEntity: parentOf[key],
355
+ })
356
+ }
357
+ }
358
+
359
+ return req
360
+ })(),
361
+ }
362
+ })
363
+ .map((e: any) => ({
364
+ ...e,
365
+ cmds: Object.keys(CMD_OPS)
366
+ .filter((cmd) => CMD_OPS[cmd].some((op) => e.ops.includes(op))),
367
+ }))
368
+ .filter((e: any) => 0 < e.cmds.length)
369
+
370
+ if (0 === entities.length) {
371
+ throw new SdkGenError(
372
+ 'seneca-provider: no entity in this model declares a list/load/create/' +
373
+ 'update/remove operation, so the plugin would expose no entities at ' +
374
+ 'all. Remove the target, or add an entity with CRUD ops.')
375
+ }
376
+
377
+ const repo = providerRepo(model, lower)
378
+
379
+ // The companion test server lives in the SDK repo's `app/` and is NOT
380
+ // published, so the only way to reach it is the local checkout. The path
381
+ // back to it is the inverse of this target's own `output: path`, computed
382
+ // once by the external pass — see cmp/ExternalTarget.
383
+ const sdkrel = ctx$.sdkrelpath || '..'
384
+
385
+ // Where a live run points — and whether there is anything honest to point
386
+ // it at.
387
+ //
388
+ // NOT simply `servers[0].url`. For an OpenAPI-derived model that is the
389
+ // PRODUCTION host of a third-party API, and everything gated on it aims
390
+ // there: the `describe('live')` block, which `npm test` runs on every CI
391
+ // push on three operating systems; the `serverUp` probe in front of it; and
392
+ // test/quick.js, whose header says "start the companion server first" while
393
+ // BASE silently defaults to production and whose body is a create / update /
394
+ // remove cycle. A live suite that reaches a stranger's API from CI is not a
395
+ // live suite, it is traffic — and unauthenticated traffic at that.
396
+ //
397
+ // So a live base is taken only when it is unambiguously OURS: declared
398
+ // outright by the project, or a loopback address, which no third party can
399
+ // be behind. Anything else leaves live testing ungenerated, which is the
400
+ // honest answer for an API nobody here runs.
401
+ const live = model?.main?.[KIT]?.test?.live || {}
402
+ const servers = (model?.main?.[KIT]?.info?.servers || [])
403
+ const specBase = 0 < servers.length ? String(servers[0].url || '') : ''
404
+
405
+ const loopback = (url: string) =>
406
+ /^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])([:/]|$)/i.test(url)
407
+
408
+ const liveBase = null != live.base && '' !== live.base ? String(live.base) :
409
+ (loopback(specBase) ? specBase : '')
410
+
411
+ // Whether the SDK's own repo ships a runnable companion server under
412
+ // `app/`. NOTHING in an API definition says so — it is a property of the
413
+ // sibling project — so it cannot be inferred, and inferring it is what put
414
+ // an unconditional `git clone && cd app && npm install && npm run build`
415
+ // into every generated provider's CI.
416
+ const liveApp = true === live.app || (loopback(specBase) && '' === (live.base || ''))
417
+
418
+ const provider = {
419
+ Name, lower, ENV, sdkClass, pluginName, fileBase,
420
+ sdkPkg, sdkVersion, entities,
421
+ repoUrl: repo.url,
422
+ // The SDK's own repo, for pointing at the companion test server which is
423
+ // only distributed in source.
424
+ sdkRepoUrl: repoInfo(model).repoUrl,
425
+ api: apiName(model),
426
+ version: packageVersion(model, target.name),
427
+ sdkrel,
428
+ liveBase,
429
+ liveApp,
430
+ // The sponsor line. @seneca/maintain's `content_readme` check requires
431
+ // the publisher's name in the README, so this is load-bearing rather
432
+ // than decorative — the generated `maintain` test fails without it.
433
+ publisher: PUBLISHER,
434
+ publisherUrl: PUBLISHER_URL,
435
+ // A route with NO path params, so the probe is a plain GET. An entity
436
+ // whose every route is parameterised gives none, and then the probe
437
+ // falls back to the base URL itself.
438
+ probePath: (entities.find((e: any) =>
439
+ '' !== e.path && !e.path.includes('{')) || { path: '' }).path,
440
+ // The provider's OWN published name. Not derived from the SDK slug the
441
+ // way a language target's is — a provider is `@seneca/<name>-provider` —
442
+ // so read the project's pin directly and default to that shape.
443
+ pkgName: providerPackage(model, lower),
444
+ // Whether this API authenticates at all. Decides if the plugin plumbs a
445
+ // credential: the SDK's auth stage emits nothing for an auth-inactive
446
+ // model and strips the authorization header regardless of options, so
447
+ // plumbing one anyway produces a credential path that cannot work.
448
+ authActive: isAuthActive(model),
449
+ }
450
+
451
+ // Static furniture: LICENSE, CODE_OF_CONDUCT, Makefile, .gitignore,
452
+ // tsfmt.json and both tsconfigs. Same for every provider.
453
+ Copy({
454
+ from: 'tm/' + target.name,
455
+ replace: { ...ctx$.stdrep },
456
+ })
457
+
458
+ PackageJson({ provider })
459
+ ProviderSource({ provider })
460
+ ProviderDoc({ provider })
461
+ Tests({ provider })
462
+ Scripts({ provider })
463
+ Workflow({ provider })
464
+ Readme({ provider })
465
+ Docs({ provider })
466
+ })
467
+
468
+
469
+ // --- package.json -----------------------------------------------------------
470
+
471
+ const PackageJson = cmp(function PackageJson(props: any) {
472
+ const { provider } = props
473
+ const { model } = props.ctx$
474
+ const target = model.main[KIT].target['seneca-provider']
475
+
476
+ const deps = collectDeps(model, target.name, target.deps, props.ctx$.log)
477
+
478
+ // collectDeps returns { name, version, source, raw } — the DECLARED kind
479
+ // (prod/peer/dev) is on `raw`, not hoisted. Reading `d.kind` instead
480
+ // silently yields an empty manifest section, which is how the first cut of
481
+ // this component shipped a package.json with no seneca peers at all.
482
+ //
483
+ // `kind` is a COMMA-SEPARATED LIST, so one dependency can land in more than
484
+ // one manifest section. That is the Seneca plugin convention and not an
485
+ // embellishment: `seneca` is a PEER (the plugin must run inside the host's
486
+ // instance, never its own bundled copy) and also a DEV dependency (the test
487
+ // suite does `require('seneca')` directly, so a bare `npm install` in a
488
+ // clean checkout has to produce it). collectDeps deduplicates by package
489
+ // name and the model's dep map is keyed by name, so the same package cannot
490
+ // be declared twice — the kind has to carry the list instead.
491
+ const dep = (kind: string) => {
492
+ const out: Record<string, string> = {}
493
+ const kinds = (d: any) => String((d.raw && d.raw.kind) || '')
494
+ .split(',').map((s: string) => s.trim()).filter((s: string) => '' !== s)
495
+
496
+ for (const d of deps.filter((d: any) => kinds(d).includes(kind))) {
497
+ out[d.name] = d.version
498
+ }
499
+ return out
500
+ }
501
+
502
+ // Attribution. Model-driven, because it cannot be derived and because
503
+ // regeneration OVERWRITES the manifest: the hand-written provider this
504
+ // target was modelled on lost its author and both named contributors on the
505
+ // first regeneration, and nothing failed. Unset falls back to the publisher.
506
+ const author = authorInfo(model)
507
+ const contributors = contributorList(model)
508
+
509
+ const pkg = {
510
+ name: provider.pkgName,
511
+ version: provider.version,
512
+ main: `dist/${provider.fileBase}.js`,
513
+ type: 'commonjs',
514
+ types: `dist/${provider.fileBase}.d.ts`,
515
+ description:
516
+ `Seneca entity provider for the ${provider.api} API, using the ` +
517
+ `${provider.sdkPkg} SDK.`,
518
+ homepage: provider.repoUrl,
519
+ keywords: ['seneca', provider.lower, `${provider.lower}-provider`,
520
+ provider.publisher.toLowerCase(), 'sdk'],
521
+ author,
522
+ // Omitted entirely when the project names none, rather than emitted as an
523
+ // empty array — npm treats `"contributors": []` as a declaration that
524
+ // there are none, which is a different claim from not having said.
525
+ ...(0 < contributors.length ? { contributors } : {}),
526
+ license: 'MIT',
527
+ repository: { type: 'git', url: `git+${provider.repoUrl}.git` },
528
+ scripts: {
529
+ test: 'node --enable-source-maps --test test/**/*.test.js',
530
+ 'test-some':
531
+ 'node --enable-source-maps --test-name-pattern="$TEST_PATTERN" ' +
532
+ '--test "test/**/*.test.js"',
533
+ 'test-watch': 'node --test --watch test/**/*.test.js',
534
+ watch: 'tsc --build src test -w',
535
+ build: 'tsc --build src test',
536
+ 'test-coverage':
537
+ 'node --enable-source-maps --experimental-test-coverage --test ' +
538
+ 'test/**/*.test.js',
539
+ clean:
540
+ 'rm -rf node_modules dist dist-test .tsbuildinfo yarn.lock ' +
541
+ 'package-lock.json',
542
+ reset: 'npm run clean && npm i && npm run build && npm test',
543
+ // The Seneca release convention: tag from package.json, push, publish.
544
+ // Generated because a provider is released like every other Seneca
545
+ // plugin, and a maintainer who has to remember the incantation will
546
+ // eventually publish an untested build.
547
+ 'repo-tag':
548
+ 'REPO_VERSION=`node -e "console.log(require(\'./package\').version)"` ' +
549
+ '&& echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION ' +
550
+ '&& git push && git tag v$REPO_VERSION && git push --tags;',
551
+ 'repo-publish': 'npm run clean && npm i && npm run repo-publish-quick',
552
+ 'repo-publish-quick':
553
+ 'npm run build && npm run test && npm run repo-tag && ' +
554
+ 'npm publish --access public --registry https://registry.npmjs.org',
555
+ },
556
+ // What actually ships. Without `files`, `npm publish` packs the test
557
+ // suite and build output into the tarball.
558
+ files: ['dist', 'src/**/*.ts', 'LICENSE'],
559
+ engines: { node: '>=24' },
560
+ dependencies: {
561
+ // The SDK this plugin wraps, by its PUBLISHED name and version.
562
+ [provider.sdkPkg]: `^${provider.sdkVersion}`,
563
+ ...dep('prod'),
564
+ },
565
+ peerDependencies: dep('peer'),
566
+ devDependencies: dep('dev'),
567
+ }
568
+
569
+ File({ name: 'package.json' }, () => {
570
+ Content(JSON.stringify(pkg, null, 2) + '\n')
571
+ })
572
+ })
573
+
574
+
575
+ // --- src/<name>-provider.ts -------------------------------------------------
576
+
577
+ const ProviderSource = cmp(function ProviderSource(props: any) {
578
+ const { provider } = props
579
+
580
+ Folder({ name: 'src' }, () => {
581
+ File({ name: `${provider.fileBase}.ts` }, () => {
582
+ Content(`/* Generated by @voxgig/sdkgen. Do not edit. */
583
+
584
+ const Pkg = require('../package.json')
585
+
586
+ const { ${provider.sdkClass} } = require('${provider.sdkPkg}')
587
+
588
+ const SdkPkg = require('${provider.sdkPkg}/package.json')
589
+
590
+
591
+ type ${provider.pluginName}Options = {
592
+ // Options passed straight to the ${provider.sdkClass} constructor,
593
+ // most usefully \`base\` to point at a server.
594
+ sdk?: Record<string, any>
595
+
596
+ // Run the SDK in offline test mode (in-memory mock transport).
597
+ test?: boolean
598
+
599
+ // Test feature options, e.g. {entity: {${provider.entities[0].name}: {...}}} to
600
+ // seed the mock with data. Only used when \`test\` is true.
601
+ testopts?: Record<string, any>
602
+ }
603
+
604
+
605
+ function ${provider.pluginName}(this: any, options: ${provider.pluginName}Options) {
606
+ const seneca: any = this
607
+
608
+ const entityBuilder = this.export('provider/entityBuilder')
609
+
610
+ seneca.message('sys:provider,provider:${provider.lower},get:info', get_info)
611
+
612
+ async function get_info(this: any, _msg: any) {
613
+ return {
614
+ ok: true,
615
+ name: '${provider.lower}',
616
+ version: Pkg.version,
617
+ sdk: {
618
+ name: '${provider.sdkPkg}',
619
+ version: SdkPkg.version,
620
+ },
621
+ }
622
+ }
623
+
624
+
625
+ // Every SDK operation resolves to an SDK ENTITY rather than raw data (a
626
+ // removed record included: it comes back marked deleted, still holding what
627
+ // it held). Seneca wants plain data, which the entity hands over through
628
+ // data().
629
+ function plain(res: any) {
630
+ return null == res ? res : res.data()
631
+ }
632
+
633
+
634
+ // Seneca query directives (sort$, limit$, ...) are for the store, not the
635
+ // API, so they must not reach the SDK as match fields.
636
+ function cleanq(q: any) {
637
+ const out: any = {}
638
+ for (const k in (q || {})) {
639
+ if (!k.endsWith('$')) {
640
+ out[k] = q[k]
641
+ }
642
+ }
643
+ return out
644
+ }
645
+
646
+
647
+ // The SDK throws on any non-2xx. A 404 from a single-item read is an
648
+ // ordinary "not found" answer rather than a failure, so return null and let
649
+ // everything else propagate. SDK errors carry the HTTP status at the top
650
+ // level, so ask them rather than digging into \`result\`.
651
+ async function ornull(action: () => Promise<any>) {
652
+ try {
653
+ return await action()
654
+ }
655
+ catch (e: any) {
656
+ if (true === e?.notFound) {
657
+ return null
658
+ }
659
+ throw e
660
+ }
661
+ }
662
+
663
+ `)
664
+
665
+ // A guard per required parent key. Without it the SDK builds a
666
+ // half-formed URL and the caller gets an opaque 404 instead of being
667
+ // told what they left out.
668
+ const guarded = provider.entities.filter((e: any) => 0 < e.parents.length)
669
+ if (0 < guarded.length) {
670
+ Content(` // Nested entities cannot build their path without the parent id, so
671
+ // say which key is missing rather than letting the SDK report an opaque
672
+ // 404 on a half-built URL.
673
+ `)
674
+ each(guarded, (e: any) => {
675
+ each(e.parents, (key: any) => {
676
+ const k = String(key.val$ ?? key)
677
+ Content(` function ${guardName(e, k)}(value: any, cmd: string) {
678
+ if (null == value || '' === value) {
679
+ throw new Error(
680
+ '${provider.pkgName}: ${e.name} ' + cmd + ': ${k} is required'
681
+ )
682
+ }
683
+ return value
684
+ }
685
+
686
+
687
+ `)
688
+ })
689
+ })
690
+ }
691
+
692
+ // Seneca's own entity key is ALWAYS literally `id` — `load$('x')` sets
693
+ // `q = { id: 'x' }`, and the id of the entity it builds comes off
694
+ // `data.id`. An API that addresses a record by anything else therefore
695
+ // needs translating in both directions, or `load$` requests a record
696
+ // keyed `undefined` and every entity handed back has no id at all — one
697
+ // that cannot then be saved or removed.
698
+ const aliased = provider.entities.filter((e: any) => 'id' !== recordKey(e.ent))
699
+ each(aliased, (e: any) => {
700
+ const rk = recordKey(e.ent)
701
+ Content(` // This API keys a ${e.name} by \`${rk}\`, Seneca by \`id\`. Carry the
702
+ // API's key across so the Seneca entity has one.
703
+ function id_${e.name}(data: any) {
704
+ if (null != data && null == data.id) {
705
+ data.id = ${jsProp('data', rk)}
706
+ }
707
+ return data
708
+ }
709
+
710
+
711
+ `)
712
+ })
713
+
714
+ // The cmd map, declared up front so every action is attached to a
715
+ // shape seneca-entity can read before the actions are defined.
716
+ Content(` const entity: any = {
717
+ `)
718
+ each(provider.entities, (e: any) => {
719
+ Content(` ${e.name}: {
720
+ cmd: {
721
+ `)
722
+ each(e.cmds, (cmd: any) => {
723
+ Content(` ${String(cmd.val$ ?? cmd)}: { action: (undefined as any) },
724
+ `)
725
+ })
726
+ Content(` },
727
+ },
728
+
729
+ `)
730
+ })
731
+ Content(` }
732
+
733
+ `)
734
+
735
+ each(provider.entities, (e: any) => {
736
+ // The guard set is PER OP, not the union across the entity's ops. An
737
+ // entity whose routes are not uniformly nested — a flat `load`, a
738
+ // nested `create` — used to demand the parent id on the flat call too,
739
+ // an argument its own SDK request would then never use.
740
+ //
741
+ // `save` guards the union of create's and update's keys: one action
742
+ // serves both and dispatches at runtime, so it cannot know which set
743
+ // applies until it has the data.
744
+ const guard = (cmd: string, src: string) => {
745
+ const keys = 'save' === cmd ?
746
+ [...new Set([...(e.opParents.create || []), ...(e.opParents.update || [])])].sort() :
747
+ (e.opParents[cmd] || [])
748
+
749
+ return keys
750
+ .map((k: string) =>
751
+ ` ${guardName(e, k)}(${jsProp(src, k)}, '${cmd}')\n`)
752
+ .join('')
753
+ }
754
+
755
+ // Reading the record's own key off the Seneca query, which always
756
+ // spells it `id`, and every other required key off its own name.
757
+ const rk = recordKey(e.ent)
758
+ const sdkArg = (opname: string) => {
759
+ const keys = requiredKeys(e.ent, opname)
760
+ if (0 === keys.length) {
761
+ return '{}'
762
+ }
763
+ return `{ ${keys.map((k: string) =>
764
+ `${jsKey(k)}: ${jsProp('q', k === rk ? 'id' : k)}`).join(', ')} }`
765
+ }
766
+
767
+ // The data hop, plus the id alias when the API keys the record by
768
+ // something other than `id`.
769
+ const out = (expr: string) =>
770
+ 'id' === rk ? `plain(${expr})` : `id_${e.name}(plain(${expr}))`
771
+
772
+ if (e.cmds.includes('list')) {
773
+ Content(`
774
+ entity.${e.name}.cmd.list.action =
775
+ async function list_${e.name}(this: any, entize: any, msg: any) {
776
+ const q = cleanq(msg.q)
777
+ ${guard('list', 'q')} const list = await this.shared.sdk.${e.acc}().list(q)
778
+ return list.map((data: any) => entize(${out('data')}))
779
+ }
780
+
781
+ `)
782
+ }
783
+
784
+ if (e.cmds.includes('load')) {
785
+ Content(`
786
+ entity.${e.name}.cmd.load.action =
787
+ async function load_${e.name}(this: any, entize: any, msg: any) {
788
+ const q = cleanq(msg.q)
789
+ ${guard('load', 'q')} const res = await ornull(() => this.shared.sdk.${e.acc}().load(${sdkArg('load')}))
790
+ return null == res ? null : entize(${out('res')})
791
+ }
792
+
793
+ `)
794
+ }
795
+
796
+ if (e.cmds.includes('save')) {
797
+ const hasCreate = e.ops.includes('create')
798
+ const hasUpdate = e.ops.includes('update')
799
+
800
+ // Dispatch on the SENECA key. The record arriving here is a Seneca
801
+ // entity's data, so its id lives at `id` whatever the API calls it —
802
+ // dispatching on the API's key sent every save to `create`, leaving
803
+ // update unreachable.
804
+ const body = hasCreate && hasUpdate
805
+ ? ` const res = null == data.id
806
+ ? await sdk.${e.acc}().create(data)
807
+ : await sdk.${e.acc}().update(data)`
808
+ : hasCreate
809
+ ? ` const res = await sdk.${e.acc}().create(data)`
810
+ : ` const res = await sdk.${e.acc}().update(data)`
811
+
812
+ // ... and hand the API back its own key, which Seneca does not know
813
+ // to send.
814
+ const alias = 'id' === rk ? '' :
815
+ `
816
+ // This API keys a ${e.name} by \`${rk}\`; Seneca carries it as \`id\`.
817
+ if (null == ${jsProp('data', rk)} && null != data.id) {
818
+ ${jsProp('data', rk)} = data.id
819
+ }
820
+ `
821
+
822
+ Content(`
823
+ entity.${e.name}.cmd.save.action =
824
+ async function save_${e.name}(this: any, entize: any, msg: any) {
825
+ const data = msg.ent.data$(false)
826
+ ${guard('save', 'data')}${alias} const sdk = this.shared.sdk
827
+
828
+ ${body}
829
+
830
+ return entize(${out('res')})
831
+ }
832
+
833
+ `)
834
+ }
835
+
836
+ if (e.cmds.includes('remove')) {
837
+ Content(`
838
+ entity.${e.name}.cmd.remove.action =
839
+ async function remove_${e.name}(this: any, _entize: any, msg: any) {
840
+ const q = cleanq(msg.q)
841
+ ${guard('remove', 'q')} await ornull(() => this.shared.sdk.${e.acc}().remove(${sdkArg('remove')}))
842
+ return null
843
+ }
844
+
845
+ `)
846
+ }
847
+ })
848
+
849
+ Content(`
850
+ entityBuilder(this, {
851
+ provider: {
852
+ name: '${provider.lower}',
853
+ },
854
+ entity
855
+ })
856
+
857
+
858
+ seneca.prepare(async function(this: any) {
859
+ const sdkopts: any = Object.assign({}, options.sdk)
860
+ ${provider.authActive ? `
861
+ // The provider convention carries credentials, so honour an \`apikey\`
862
+ // when one is configured and stay quiet when it is not.
863
+ const res = await this.post('sys:provider,get:keymap,provider:${provider.lower}')
864
+ const apikey = res?.keymap?.apikey?.value
865
+
866
+ // Hand the credential to the SDK as \`apikey\`, NOT as an authorization
867
+ // HEADER. The SDK's own auth stage owns that header: it reads
868
+ // \`options.apikey\`, and on every path where it finds none it DELETES
869
+ // \`authorization\` before the request goes out. A provider that set the
870
+ // header itself was therefore never authenticated — the SDK stripped the
871
+ // very thing it had just written, on every call, silently. The SDK also
872
+ // owns the scheme prefix, which is resolved from the API definition
873
+ // rather than assumed to be \`Bearer\`.
874
+ if (null != apikey && '' !== apikey) {
875
+ sdkopts.apikey = apikey
876
+ }
877
+ ` : `
878
+ // This API declares no authentication, so no credential is plumbed. The
879
+ // SDK's auth stage emits nothing for an auth-inactive model and deletes
880
+ // any \`authorization\` header regardless of options, so a keymap lookup
881
+ // here would read a key that could not reach the wire — which is what the
882
+ // first version of this target did.
883
+ `}
884
+ this.shared.sdk = options.test
885
+ ? ${provider.sdkClass}.test(options.testopts || {}, sdkopts)
886
+ : new ${provider.sdkClass}(sdkopts)
887
+ })
888
+
889
+
890
+ return {
891
+ exports: {
892
+ sdk: () => this.shared.sdk,
893
+ },
894
+ }
895
+ }
896
+
897
+
898
+ // Default options.
899
+ const defaults: ${provider.pluginName}Options = {
900
+ sdk: {},
901
+ test: false,
902
+ testopts: {},
903
+ }
904
+
905
+ Object.assign(${provider.pluginName}, { defaults })
906
+
907
+ export default ${provider.pluginName}
908
+
909
+ if ('undefined' !== typeof module) {
910
+ module.exports = ${provider.pluginName}
911
+ }
912
+ `)
913
+ })
914
+ })
915
+ })
916
+
917
+
918
+ // --- src/<Name>Provider-doc.ts ----------------------------------------------
919
+
920
+ const ProviderDoc = cmp(function ProviderDoc(props: any) {
921
+ const { provider } = props
922
+
923
+ Folder({ name: 'src' }, () => {
924
+ File({ name: `${provider.pluginName}-doc.ts` }, () => {
925
+ Content(`/* Generated by @voxgig/sdkgen. Do not edit. */
926
+
927
+
928
+ const messages = {
929
+ get_info: {
930
+ desc: 'Get information about the ${provider.api} SDK.',
931
+ },
932
+ }
933
+
934
+
935
+ const sections = {
936
+ intro: {
937
+ path: '../provider/doc/intro.md'
938
+ }
939
+ }
940
+
941
+ const docs = {
942
+ sections,
943
+ messages
944
+ }
945
+
946
+ export default docs
947
+
948
+
949
+ if ('undefined' !== typeof module) {
950
+ module.exports = docs
951
+ }
952
+ `)
953
+ })
954
+ })
955
+ })
956
+
957
+
958
+ export {
959
+ Main,
960
+ }