@voxgig/sdkgen 4.22.0 → 4.24.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 (315) hide show
  1. package/bin/voxgig-sdkgen +18 -2
  2. package/dist/action/doctor.d.ts +1 -1
  3. package/dist/action/doctor.js +12 -10
  4. package/dist/action/doctor.js.map +1 -1
  5. package/dist/action/edition.js +4 -0
  6. package/dist/action/edition.js.map +1 -1
  7. package/dist/action/feature.js +5 -1
  8. package/dist/action/feature.js.map +1 -1
  9. package/dist/action/remove.d.ts +16 -0
  10. package/dist/action/remove.js +345 -0
  11. package/dist/action/remove.js.map +1 -0
  12. package/dist/action/target.js +6 -1
  13. package/dist/action/target.js.map +1 -1
  14. package/dist/cmp/ReadmeTop.js +1 -1
  15. package/dist/cmp/ReadmeTop.js.map +1 -1
  16. package/dist/cmp/ReadmeUnions.js +1 -1
  17. package/dist/cmp/ReadmeUnions.js.map +1 -1
  18. package/dist/cmp/Test.js +1 -1
  19. package/dist/cmp/Test.js.map +1 -1
  20. package/dist/helpers/buildIdNames.d.ts +3 -1
  21. package/dist/helpers/buildIdNames.js +15 -7
  22. package/dist/helpers/buildIdNames.js.map +1 -1
  23. package/dist/helpers/canonSpec.js +2 -2
  24. package/dist/helpers/canonSpec.js.map +1 -1
  25. package/dist/helpers/getMatchEntries.js +2 -2
  26. package/dist/helpers/getMatchEntries.js.map +1 -1
  27. package/dist/helpers/modelNames.js +5 -1
  28. package/dist/helpers/modelNames.js.map +1 -1
  29. package/dist/helpers/opShape.js +33 -33
  30. package/dist/helpers/opShape.js.map +1 -1
  31. package/dist/helpers/pointPath.js +5 -10
  32. package/dist/helpers/pointPath.js.map +1 -1
  33. package/dist/helpers/resolved.js +2 -29
  34. package/dist/helpers/resolved.js.map +1 -1
  35. package/dist/sdkgen.d.ts +2 -2
  36. package/dist/sdkgen.js +5 -3
  37. package/dist/sdkgen.js.map +1 -1
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/dist/utility.js +15 -7
  40. package/dist/utility.js.map +1 -1
  41. package/package.json +3 -3
  42. package/project/.sdk/src/cmp/c/EntityTypes_c.ts +4 -4
  43. package/project/.sdk/src/cmp/c/ReadmeEntity_c.ts +3 -3
  44. package/project/.sdk/src/cmp/c/ReadmeModel_c.ts +3 -3
  45. package/project/.sdk/src/cmp/c/ReadmeRef_c.ts +5 -5
  46. package/project/.sdk/src/cmp/c/Schema_c.ts +1 -1
  47. package/project/.sdk/src/cmp/c/TestDirect_c.ts +12 -12
  48. package/project/.sdk/src/cmp/clojure/ReadmeEntity_clojure.ts +3 -3
  49. package/project/.sdk/src/cmp/clojure/ReadmeModel_clojure.ts +3 -3
  50. package/project/.sdk/src/cmp/clojure/ReadmeRef_clojure.ts +5 -5
  51. package/project/.sdk/src/cmp/clojure/Schema_clojure.ts +1 -1
  52. package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +3 -3
  53. package/project/.sdk/src/cmp/cpp/ReadmeEntity_cpp.ts +3 -3
  54. package/project/.sdk/src/cmp/cpp/ReadmeModel_cpp.ts +3 -3
  55. package/project/.sdk/src/cmp/cpp/ReadmeRef_cpp.ts +5 -5
  56. package/project/.sdk/src/cmp/cpp/Schema_cpp.ts +1 -1
  57. package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +14 -14
  58. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +51 -50
  59. package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +4 -4
  60. package/project/.sdk/src/cmp/csharp/ReadmeEntity_csharp.ts +3 -3
  61. package/project/.sdk/src/cmp/csharp/ReadmeModel_csharp.ts +3 -3
  62. package/project/.sdk/src/cmp/csharp/ReadmeRef_csharp.ts +5 -5
  63. package/project/.sdk/src/cmp/csharp/Schema_csharp.ts +1 -1
  64. package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +30 -30
  65. package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +66 -65
  66. package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +4 -4
  67. package/project/.sdk/src/cmp/elixir/ReadmeEntity_elixir.ts +3 -3
  68. package/project/.sdk/src/cmp/elixir/ReadmeModel_elixir.ts +3 -3
  69. package/project/.sdk/src/cmp/elixir/ReadmeRef_elixir.ts +4 -4
  70. package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +1 -1
  71. package/project/.sdk/src/cmp/go/EntityTypes_go.ts +4 -4
  72. package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +3 -3
  73. package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +3 -3
  74. package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +5 -5
  75. package/project/.sdk/src/cmp/go/Schema_go.ts +1 -1
  76. package/project/.sdk/src/cmp/go/TestDirect_go.ts +38 -38
  77. package/project/.sdk/src/cmp/go/TestEntity_go.ts +75 -74
  78. package/project/.sdk/src/cmp/go/utility_go.ts +5 -5
  79. package/project/.sdk/src/cmp/java/EntityTypes_java.ts +4 -4
  80. package/project/.sdk/src/cmp/java/ReadmeEntity_java.ts +3 -3
  81. package/project/.sdk/src/cmp/java/ReadmeModel_java.ts +3 -3
  82. package/project/.sdk/src/cmp/java/ReadmeRef_java.ts +5 -5
  83. package/project/.sdk/src/cmp/java/Schema_java.ts +1 -1
  84. package/project/.sdk/src/cmp/java/TestDirect_java.ts +30 -30
  85. package/project/.sdk/src/cmp/java/TestEntity_java.ts +69 -68
  86. package/project/.sdk/src/cmp/js/EntityTypes_js.ts +5 -5
  87. package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +3 -3
  88. package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +3 -3
  89. package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +5 -5
  90. package/project/.sdk/src/cmp/js/Schema_js.ts +1 -1
  91. package/project/.sdk/src/cmp/js/TestDirect_js.ts +27 -27
  92. package/project/.sdk/src/cmp/js/TestEntity_js.ts +66 -69
  93. package/project/.sdk/src/cmp/js/TestLive_js.ts +3 -3
  94. package/project/.sdk/src/cmp/js/utility_js.ts +5 -5
  95. package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +4 -4
  96. package/project/.sdk/src/cmp/kotlin/ReadmeEntity_kotlin.ts +3 -3
  97. package/project/.sdk/src/cmp/kotlin/ReadmeModel_kotlin.ts +3 -3
  98. package/project/.sdk/src/cmp/kotlin/ReadmeRef_kotlin.ts +5 -5
  99. package/project/.sdk/src/cmp/kotlin/Schema_kotlin.ts +1 -1
  100. package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +30 -30
  101. package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +67 -66
  102. package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +5 -5
  103. package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +3 -3
  104. package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +3 -3
  105. package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +4 -4
  106. package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +5 -5
  107. package/project/.sdk/src/cmp/lua/Schema_lua.ts +1 -1
  108. package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +25 -25
  109. package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +66 -65
  110. package/project/.sdk/src/cmp/ocaml/ReadmeEntity_ocaml.ts +3 -3
  111. package/project/.sdk/src/cmp/ocaml/ReadmeModel_ocaml.ts +3 -3
  112. package/project/.sdk/src/cmp/ocaml/ReadmeRef_ocaml.ts +5 -5
  113. package/project/.sdk/src/cmp/ocaml/Schema_ocaml.ts +1 -1
  114. package/project/.sdk/src/cmp/perl/ReadmeEntity_perl.ts +3 -3
  115. package/project/.sdk/src/cmp/perl/ReadmeModel_perl.ts +3 -3
  116. package/project/.sdk/src/cmp/perl/ReadmeRef_perl.ts +5 -5
  117. package/project/.sdk/src/cmp/perl/Schema_perl.ts +1 -1
  118. package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +25 -25
  119. package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +60 -59
  120. package/project/.sdk/src/cmp/php/EntityTypes_php.ts +4 -4
  121. package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +3 -3
  122. package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +3 -3
  123. package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +4 -4
  124. package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +5 -5
  125. package/project/.sdk/src/cmp/php/Schema_php.ts +1 -1
  126. package/project/.sdk/src/cmp/php/TestDirect_php.ts +25 -25
  127. package/project/.sdk/src/cmp/php/TestEntity_php.ts +66 -65
  128. package/project/.sdk/src/cmp/py/EntityTypes_py.ts +4 -4
  129. package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +3 -3
  130. package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +3 -3
  131. package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +5 -5
  132. package/project/.sdk/src/cmp/py/Schema_py.ts +1 -1
  133. package/project/.sdk/src/cmp/py/TestDirect_py.ts +25 -25
  134. package/project/.sdk/src/cmp/py/TestEntity_py.ts +66 -65
  135. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +4 -4
  136. package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +4 -4
  137. package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +3 -3
  138. package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +3 -3
  139. package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +4 -4
  140. package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +5 -5
  141. package/project/.sdk/src/cmp/rb/Schema_rb.ts +1 -1
  142. package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +25 -25
  143. package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +66 -65
  144. package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +4 -4
  145. package/project/.sdk/src/cmp/rust/ReadmeEntity_rust.ts +3 -3
  146. package/project/.sdk/src/cmp/rust/ReadmeModel_rust.ts +3 -3
  147. package/project/.sdk/src/cmp/rust/ReadmeRef_rust.ts +5 -5
  148. package/project/.sdk/src/cmp/rust/Schema_rust.ts +1 -1
  149. package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +18 -18
  150. package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +63 -62
  151. package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +4 -4
  152. package/project/.sdk/src/cmp/scala/ReadmeEntity_scala.ts +3 -3
  153. package/project/.sdk/src/cmp/scala/ReadmeModel_scala.ts +3 -3
  154. package/project/.sdk/src/cmp/scala/ReadmeRef_scala.ts +5 -5
  155. package/project/.sdk/src/cmp/scala/Schema_scala.ts +1 -1
  156. package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +14 -14
  157. package/project/.sdk/src/cmp/scala/TestEntity_scala.ts +60 -59
  158. package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +4 -4
  159. package/project/.sdk/src/cmp/swift/ReadmeEntity_swift.ts +3 -3
  160. package/project/.sdk/src/cmp/swift/ReadmeModel_swift.ts +3 -3
  161. package/project/.sdk/src/cmp/swift/ReadmeRef_swift.ts +5 -5
  162. package/project/.sdk/src/cmp/swift/Schema_swift.ts +1 -1
  163. package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +5 -5
  164. package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +3 -3
  165. package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +3 -3
  166. package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +1 -1
  167. package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +5 -5
  168. package/project/.sdk/src/cmp/ts/Schema_ts.ts +1 -1
  169. package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +40 -40
  170. package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +72 -75
  171. package/project/.sdk/src/cmp/ts/TestLive_ts.ts +3 -3
  172. package/project/.sdk/src/cmp/ts/utility_ts.ts +5 -5
  173. package/project/.sdk/src/cmp/zig/ReadmeEntity_zig.ts +3 -3
  174. package/project/.sdk/src/cmp/zig/ReadmeModel_zig.ts +3 -3
  175. package/project/.sdk/src/cmp/zig/ReadmeRef_zig.ts +5 -5
  176. package/project/.sdk/src/cmp/zig/Schema_zig.ts +1 -1
  177. package/project/.sdk/tm/c/core/context.c +3 -1
  178. package/project/.sdk/tm/c/feature/paging.c +37 -3
  179. package/project/.sdk/tm/c/feature/test.c +71 -31
  180. package/project/.sdk/tm/c/utility/prepare_query.c +2 -1
  181. package/project/.sdk/tm/c/utility/transform_request.c +25 -3
  182. package/project/.sdk/tm/clojure/src/sdk/core.clj +21 -7
  183. package/project/.sdk/tm/clojure/src/sdk/features.clj +74 -22
  184. package/project/.sdk/tm/cpp/core/types.hpp +1 -1
  185. package/project/.sdk/tm/cpp/feature/paging.hpp +36 -3
  186. package/project/.sdk/tm/cpp/feature/test.hpp +58 -19
  187. package/project/.sdk/tm/cpp/utility/pipeline.hpp +16 -4
  188. package/project/.sdk/tm/csharp/core/Context.cs +1 -1
  189. package/project/.sdk/tm/csharp/feature/PagingFeature.cs +58 -4
  190. package/project/.sdk/tm/csharp/feature/TestFeature.cs +23 -25
  191. package/project/.sdk/tm/csharp/utility/Fetcher.cs +19 -12
  192. package/project/.sdk/tm/csharp/utility/PrepareQuery.cs +1 -1
  193. package/project/.sdk/tm/csharp/utility/TransformRequest.cs +23 -3
  194. package/project/.sdk/tm/elixir/lib/projectname/context.ex +1 -1
  195. package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +52 -10
  196. package/project/.sdk/tm/elixir/lib/projectname/feature/test.ex +58 -22
  197. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +30 -9
  198. package/project/.sdk/tm/go/core/context.go +13 -13
  199. package/project/.sdk/tm/go/feature/paging_feature.go +40 -2
  200. package/project/.sdk/tm/go/feature/test_feature.go +3 -15
  201. package/project/.sdk/tm/go/test/feature_corpus_test.go +1 -0
  202. package/project/.sdk/tm/go/test/feature_test.go +54 -0
  203. package/project/.sdk/tm/go/utility/fetcher.go +41 -20
  204. package/project/.sdk/tm/go/utility/prepare_query.go +1 -1
  205. package/project/.sdk/tm/go/utility/transform_request.go +22 -3
  206. package/project/.sdk/tm/java/core/Context.java +2 -1
  207. package/project/.sdk/tm/java/feature/PagingFeature.java +46 -4
  208. package/project/.sdk/tm/java/feature/TestFeature.java +21 -19
  209. package/project/.sdk/tm/java/test/FeatureCorpusTest.java +3 -0
  210. package/project/.sdk/tm/java/test/FeatureTest.java +42 -0
  211. package/project/.sdk/tm/java/utility/Fetcher.java +36 -28
  212. package/project/.sdk/tm/java/utility/PrepareQuery.java +1 -1
  213. package/project/.sdk/tm/java/utility/TransformRequest.java +18 -3
  214. package/project/.sdk/tm/js/src/Context.js +7 -2
  215. package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +24 -6
  216. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +7 -5
  217. package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +1 -1
  218. package/project/.sdk/tm/js/test/feature/Corpus.test.js +4 -0
  219. package/project/.sdk/tm/js/test/live-entity.js +29 -29
  220. package/project/.sdk/tm/js/test/live-scenarios.js +4 -4
  221. package/project/.sdk/tm/kotlin/core/Context.kt +1 -1
  222. package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +36 -4
  223. package/project/.sdk/tm/kotlin/feature/TestFeature.kt +19 -18
  224. package/project/.sdk/tm/kotlin/utility/Fetcher.kt +33 -24
  225. package/project/.sdk/tm/kotlin/utility/Prepare.kt +1 -1
  226. package/project/.sdk/tm/kotlin/utility/ResultTransform.kt +18 -3
  227. package/project/.sdk/tm/lua/core/context.lua +8 -1
  228. package/project/.sdk/tm/lua/core/control.lua +3 -0
  229. package/project/.sdk/tm/lua/feature/paging_feature.lua +44 -5
  230. package/project/.sdk/tm/lua/feature/test_feature.lua +32 -14
  231. package/project/.sdk/tm/lua/utility/prepare_query.lua +2 -1
  232. package/project/.sdk/tm/lua/utility/transform_request.lua +19 -3
  233. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -25
  234. package/project/.sdk/tm/ocaml/sdk_runtime.ml +23 -8
  235. package/project/.sdk/tm/perl/core/context.pm +2 -1
  236. package/project/.sdk/tm/perl/feature/paging_feature.pm +31 -5
  237. package/project/.sdk/tm/perl/feature/test_feature.pm +52 -20
  238. package/project/.sdk/tm/perl/feature/timeout_feature.pm +17 -13
  239. package/project/.sdk/tm/perl/t/feature_corpus.t +14 -1
  240. package/project/.sdk/tm/perl/utility/fetcher.pm +15 -1
  241. package/project/.sdk/tm/perl/utility/prepare_query.pm +1 -0
  242. package/project/.sdk/tm/perl/utility/transform_request.pm +13 -3
  243. package/project/.sdk/tm/php/core/Context.php +5 -1
  244. package/project/.sdk/tm/php/core/Control.php +5 -0
  245. package/project/.sdk/tm/php/feature/PagingFeature.php +26 -5
  246. package/project/.sdk/tm/php/feature/TestFeature.php +27 -42
  247. package/project/.sdk/tm/php/test/FeatureCorpusTest.php +17 -1
  248. package/project/.sdk/tm/php/test/FeatureTest.php +44 -0
  249. package/project/.sdk/tm/php/utility/Fetcher.php +17 -3
  250. package/project/.sdk/tm/php/utility/PrepareQuery.php +1 -1
  251. package/project/.sdk/tm/php/utility/TransformRequest.php +15 -3
  252. package/project/.sdk/tm/py/pkg/core/context.py +2 -1
  253. package/project/.sdk/tm/py/pkg/feature/paging_feature.py +29 -4
  254. package/project/.sdk/tm/py/pkg/feature/test_feature.py +29 -12
  255. package/project/.sdk/tm/py/pkg/utility/fetcher.py +63 -65
  256. package/project/.sdk/tm/py/pkg/utility/prepare_query.py +2 -1
  257. package/project/.sdk/tm/py/pkg/utility/transform_request.py +11 -3
  258. package/project/.sdk/tm/py/test/test_feature.py +27 -0
  259. package/project/.sdk/tm/py/test/test_feature_corpus.py +11 -1
  260. package/project/.sdk/tm/rb/core/context.rb +1 -1
  261. package/project/.sdk/tm/rb/feature/paging_feature.rb +27 -5
  262. package/project/.sdk/tm/rb/feature/test_feature.rb +39 -11
  263. package/project/.sdk/tm/rb/test/feature_corpus_test.rb +12 -1
  264. package/project/.sdk/tm/rb/test/feature_test.rb +38 -0
  265. package/project/.sdk/tm/rb/utility/fetcher.rb +49 -3
  266. package/project/.sdk/tm/rb/utility/prepare_query.rb +1 -1
  267. package/project/.sdk/tm/rb/utility/transform_request.rb +10 -3
  268. package/project/.sdk/tm/rust/core/context.rs +2 -6
  269. package/project/.sdk/tm/rust/feature/paging.rs +44 -3
  270. package/project/.sdk/tm/rust/feature/secrets.rs +1 -1
  271. package/project/.sdk/tm/rust/feature/test.rs +74 -37
  272. package/project/.sdk/tm/rust/utility/fetcher.rs +41 -14
  273. package/project/.sdk/tm/rust/utility/prepare_query.rs +1 -1
  274. package/project/.sdk/tm/rust/utility/transform_request.rs +31 -5
  275. package/project/.sdk/tm/scala/core/Context.scala +2 -1
  276. package/project/.sdk/tm/scala/feature/PagingFeature.scala +41 -4
  277. package/project/.sdk/tm/scala/feature/TestFeature.scala +21 -18
  278. package/project/.sdk/tm/scala/utility/Fetcher.scala +34 -13
  279. package/project/.sdk/tm/scala/utility/Prepare.scala +1 -1
  280. package/project/.sdk/tm/scala/utility/Transform.scala +19 -3
  281. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +1 -1
  282. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +31 -4
  283. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TestFeature.swift +22 -15
  284. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Fetcher.swift +22 -3
  285. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +1 -1
  286. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +14 -3
  287. package/project/.sdk/tm/ts/src/Context.ts +7 -2
  288. package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +19 -3
  289. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +3 -0
  290. package/project/.sdk/tm/ts/src/utility/PrepareQueryUtility.ts +1 -1
  291. package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +1 -0
  292. package/project/.sdk/tm/ts/test/live-entity.ts +26 -26
  293. package/project/.sdk/tm/ts/test/live-scenarios.ts +3 -3
  294. package/project/.sdk/tm/zig/core/context.zig +1 -1
  295. package/project/.sdk/tm/zig/core/utility.zig +19 -5
  296. package/project/.sdk/tm/zig/feature/paging.zig +34 -4
  297. package/project/.sdk/tm/zig/feature/test.zig +65 -30
  298. package/project/sdkgen-package.json +1 -1
  299. package/src/action/doctor.ts +12 -9
  300. package/src/action/edition.ts +8 -0
  301. package/src/action/feature.ts +7 -1
  302. package/src/action/remove.ts +492 -0
  303. package/src/action/target.ts +8 -1
  304. package/src/cmp/ReadmeTop.ts +1 -1
  305. package/src/cmp/ReadmeUnions.ts +1 -1
  306. package/src/cmp/Test.ts +1 -1
  307. package/src/helpers/buildIdNames.ts +17 -7
  308. package/src/helpers/canonSpec.ts +2 -2
  309. package/src/helpers/getMatchEntries.ts +2 -2
  310. package/src/helpers/modelNames.ts +6 -1
  311. package/src/helpers/opShape.ts +33 -33
  312. package/src/helpers/pointPath.ts +5 -10
  313. package/src/helpers/resolved.ts +3 -14
  314. package/src/sdkgen.ts +3 -1
  315. package/src/utility.ts +16 -7
@@ -5,26 +5,26 @@ import { isControlSkipped, liveDelayMs } from './utility'
5
5
 
6
6
  // The offline flow keeps its deterministic fixture assertions. Live flows
7
7
  // resolve real prerequisites per operation and collect failures until done.
8
- async function runLiveEntity(setup: any, entity: any, flow: any, accessor: string) {
8
+ async function runLiveEntity(setup: any, entity: any, flow: any, accessor: string, facts: any = {}) {
9
9
  const { client, transport } = setup
10
- const steps: any[] = flow.step || []
10
+ const steps: any[] = (flow.step || []).filter((step: any) => false !== step.a)
11
11
  const created = new Map<string, any>()
12
12
  const listed: any[] = []
13
13
  const marks = new Map<string, { name: string, value: any }>()
14
14
  const idField = entity.id?.field || 'id'
15
15
  const copy = (value: any) => JSON.parse(JSON.stringify(value ?? {}))
16
- const hasCreate = steps.some(step => step.op === 'create')
16
+ const hasCreate = steps.some(step => step.o === 'create')
17
17
  const report = await runLiveSteps(steps.map((step, index) => {
18
- const ref = step.input?.ref || entity.name + '_ref01'
19
- const op = step.op
18
+ const ref = step.i?.ref || entity.name + '_ref01'
19
+ const op = step.o
20
20
  const excluded = isControlSkipped('entityOp', entity.name + '.' + op, 'live')
21
21
  return {
22
22
  id: entity.name + '.' + op + '.' + index,
23
- cleanup: op === 'remove' || (step.valid || []).some((v: any) => v.apply === 'ItemNotExists'),
23
+ cleanup: op === 'remove' || (step.v || []).some((v: any) => v.apply === 'ItemNotExists'),
24
24
  excluded: excluded.skip ? excluded.reason || 'Excluded by test control' : undefined,
25
25
  run: async (context: any) => {
26
26
  transport.enter(context)
27
- const points = entity.op?.[op]?.points || []
27
+ const points = (entity.op?.[op]?.points || []).filter((point: any) => false !== point.a)
28
28
  if (!points.length) throw new LiveBlocked('No modelled operation point')
29
29
  const record = created.get(ref)
30
30
  // A failed create must not turn a later update/remove into a write
@@ -41,7 +41,7 @@ async function runLiveEntity(setup: any, entity: any, flow: any, accessor: strin
41
41
 
42
42
  let input: any = op === 'create'
43
43
  ? copy(setup.data.new?.[entity.name]?.[ref]) : {}
44
- for (const [name, binding] of Object.entries({ ...step.match, ...step.data })) {
44
+ for (const [name, binding] of Object.entries({ ...step.m, ...step.d })) {
45
45
  const value = setup.idmap[binding as string] ?? setup.idmap[name]
46
46
  if (undefined !== value) input[name] = value
47
47
  }
@@ -57,34 +57,34 @@ async function runLiveEntity(setup: any, entity: any, flow: any, accessor: strin
57
57
  let selected: any
58
58
  const missing = new Set<string>()
59
59
  for (const point of points) {
60
- if (point.select?.$action !== input.$action) continue
60
+ if (point.q?.$action !== input.$action) continue
61
61
  const candidate = { ...input }
62
62
  let viable = true
63
- const params = point.args?.params || []
64
- const query = (point.args?.query || []).filter((arg: any) => arg.reqd)
63
+ const params = point.g?.params || []
64
+ const query = (point.g?.query || []).filter((arg: any) => arg.r)
65
65
  for (const arg of [...params, ...query]) {
66
- if (undefined !== candidate[arg.name] && null !== candidate[arg.name]) continue
67
- const key = arg.name === 'id' ? entity.name + '01' : arg.name.replace(/_id$/, '') + '01'
68
- const value = setup.idmap[key] ?? setup.idmap[arg.name] ?? loaded?.[arg.name] ?? arg.example
69
- if (undefined !== value && null !== value) candidate[arg.name] = value
70
- else if (arg.reqd !== false) { viable = false; missing.add(arg.name) }
66
+ if (undefined !== candidate[arg.n] && null !== candidate[arg.n]) continue
67
+ const key = arg.n === 'id' ? entity.name + '01' : arg.n.replace(/_id$/, '') + '01'
68
+ const value = setup.idmap[key] ?? setup.idmap[arg.n] ?? loaded?.[arg.n] ?? arg.ex
69
+ if (undefined !== value && null !== value) candidate[arg.n] = value
70
+ else if (arg.r !== false) { viable = false; missing.add(arg.n) }
71
71
  }
72
72
  if (viable) { resolved = candidate; selected = point; break }
73
73
  }
74
74
  if (!resolved) throw new LiveBlocked('No usable route; missing arguments: ' + [...missing].join(', '))
75
75
  input = resolved
76
- if (op === 'create' && selected.contract) {
77
- const facts = JSON.parse(selected.contract.json)
78
- const request = requestContract(facts)
79
- if (request.schema) input = { ...synthesizeInput(request.schema, facts.live?.input ?? request.example) }
80
- else if (facts.protocol === 'http') input = {}
81
- for (const arg of selected.args?.params || []) if (resolved[arg.name] !== undefined) input[arg.name] = resolved[arg.name]
76
+ if (op === 'create' && facts[selected.m + ' ' + selected.o]) {
77
+ const selectedFacts = facts[selected.m + ' ' + selected.o]
78
+ const request = requestContract(selectedFacts)
79
+ if (request.schema) input = { ...synthesizeInput(request.schema, selected.li?.input ?? request.example) }
80
+ else if (selectedFacts.protocol === 'http') input = {}
81
+ for (const arg of selected.g?.params || []) if (resolved[arg.n] !== undefined) input[arg.n] = resolved[arg.n]
82
82
  }
83
83
  let intendedMark: { name: string, value: any } | undefined
84
84
  if (op === 'update') {
85
- for (const spec of step.spec || []) {
86
- if (spec.apply === 'TextFieldMark' && step.input?.textfield) {
87
- const mark = { name: step.input.textfield, value: spec.def.mark + '_' + setup.now }
85
+ for (const spec of step.s || []) {
86
+ if (spec.apply === 'TextFieldMark' && step.i?.textfield) {
87
+ const mark = { name: step.i.textfield, value: spec.def.mark + '_' + setup.now }
88
88
  input[mark.name] = mark.value
89
89
  intendedMark = mark
90
90
  }
@@ -103,7 +103,7 @@ async function runLiveEntity(setup: any, entity: any, flow: any, accessor: strin
103
103
  })
104
104
  listed.splice(0, listed.length, ...data)
105
105
  context.publish(data)
106
- for (const validation of step.valid || []) {
106
+ for (const validation of step.v || []) {
107
107
  const previous = created.get(validation.def?.ref)
108
108
  const id = previous?.[idField] ?? previous?.id
109
109
  if (undefined === id) continue
@@ -52,9 +52,9 @@ export async function runLiveScenarios(SDK: any, plan: any[], envPrefix: string,
52
52
  const explicit = hint.input === undefined ? request.example : resolveRecipe(hint.input, ctx.values)
53
53
  let input = request.schema ? synthesizeInput(request.schema, explicit) : explicit ?? {}
54
54
  for (const kind of ['params', 'query', 'header', 'cookie']) for (const arg of point.args?.[kind] || []) {
55
- if (arg.reqd && input[arg.name] === undefined) {
56
- if (arg.example === undefined) throw new LiveBlocked('Missing required argument: ' + arg.name)
57
- input[arg.name] = arg.example
55
+ if (arg.r && input[arg.n] === undefined) {
56
+ if (arg.ex === undefined) throw new LiveBlocked('Missing required argument: ' + arg.n)
57
+ input[arg.n] = arg.ex
58
58
  }
59
59
  }
60
60
  const role = hint.auth || (point.facts.security?.length === 0 || point.facts.securitySource === 'unspecified' ? 'public' : 'account')
@@ -100,7 +100,7 @@ pub const Context = struct {
100
100
  ctrl = c;
101
101
  } else if (ctxspec.ctrl_obj) |co| {
102
102
  ctrl = co;
103
- } else if (basectx) |b| {
103
+ } else if (if (ctxspec.opname == null) basectx else null) |b| {
104
104
  ctrl = b.ctrl;
105
105
  } else {
106
106
  ctrl = Control.make();
@@ -1120,7 +1120,7 @@ pub fn prepare_query_util(ctx: *Context) Value {
1120
1120
  }
1121
1121
  }
1122
1122
  }
1123
- if (!h.is_noval(val) and !contained) h.setp(out, key, val);
1123
+ if (!h.is_noval(val) and !std.mem.eql(u8, key, "$action") and !contained) h.setp(out, key, val);
1124
1124
  }
1125
1125
  }
1126
1126
  return out;
@@ -1375,6 +1375,20 @@ pub fn result_body_util(ctx: *Context) ?*SdkResult {
1375
1375
  return result;
1376
1376
  }
1377
1377
 
1378
+ // `$action` selects the point (see make_point_util); it is never an API
1379
+ // field, so the body is a copy without it. The caller's map is left untouched.
1380
+ fn strip_action(reqdata: Value) Value {
1381
+ if (reqdata != .object) return reqdata;
1382
+ if (reqdata.object.get("$action") == null) return reqdata;
1383
+ const body = h.omap();
1384
+ var it = reqdata.object.iterator();
1385
+ while (it.next()) |kv| {
1386
+ const key = kv.key_ptr.*;
1387
+ if (!std.mem.eql(u8, key, "$action")) h.setp(body, key, kv.value_ptr.*);
1388
+ }
1389
+ return body;
1390
+ }
1391
+
1378
1392
  pub fn transform_request_util(ctx: *Context) Value {
1379
1393
  const spec = ctx.spec;
1380
1394
  const point = ctx.point;
@@ -1382,16 +1396,16 @@ pub fn transform_request_util(ctx: *Context) Value {
1382
1396
  if (spec) |sp| sp.step = "reqform";
1383
1397
 
1384
1398
  const transform = h.to_map(h.getp(point, "transform"));
1385
- if (h.is_noval(transform)) return ctx.reqdata;
1399
+ if (h.is_noval(transform)) return strip_action(ctx.reqdata);
1386
1400
 
1387
1401
  const reqform = h.getp(transform, "req");
1388
- if (h.is_noval(reqform)) return ctx.reqdata;
1402
+ if (h.is_noval(reqform)) return strip_action(ctx.reqdata);
1389
1403
 
1390
1404
  const store = h.jo(&.{.{ "reqdata", ctx.reqdata }});
1391
1405
  // transform now reports collected injection errors beside the value; .out
1392
1406
  // is what it used to return on its own, errors or not.
1393
- const tres = vs.transform(h.A(), store, reqform) catch return ctx.reqdata;
1394
- return tres.out;
1407
+ const tres = vs.transform(h.A(), store, reqform) catch return strip_action(ctx.reqdata);
1408
+ return strip_action(tres.out);
1395
1409
  }
1396
1410
 
1397
1411
  pub fn transform_response_util(ctx: *Context) Value {
@@ -3,8 +3,8 @@
3
3
  // (or a cursor) into the request query; on the way back (PreResult) it reads
4
4
  // the server's pagination signals — a `Link: rel="next"` header,
5
5
  // `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
6
- // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body — and records them
7
- // on `result.paging`. A per-call cursor/page from ctrl takes priority (used by
6
+ // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case forms
7
+ // too) — and records them on `result.paging` and the caller's ctrl paging. A per-call cursor/page from ctrl takes priority (used by
8
8
  // auto-iteration). Parameter names (`pageParam`, `limitParam`, `cursorParam`),
9
9
  // the page size (`limit`) and the start page (`startPage`, default 1) are
10
10
  // configurable.
@@ -114,7 +114,10 @@ pub const PagingFeature = struct {
114
114
  if (!h.is_noval(cursor)) {
115
115
  h.setp(query, cursor_param, cursor);
116
116
  } else if (h.is_noval(h.getp(query, page_param))) {
117
- const page = h.getp(paging, "page");
117
+ // A record written back by pre_result holds the page just fetched
118
+ // as "page" and the one to fetch as "nextPage", so nextPage wins.
119
+ var page = h.getp(paging, "nextPage");
120
+ if (h.is_noval(page)) page = h.getp(paging, "page");
118
121
  if (!h.is_noval(page)) {
119
122
  h.setp(query, page_param, page);
120
123
  } else {
@@ -257,12 +260,16 @@ pub const PagingFeature = struct {
257
260
  }
258
261
  }
259
262
 
260
- // Body-level cursors.
263
+ // Body-level signals; snake_case forms are read first so camelCase wins.
261
264
  if (body == .object) {
262
265
  const next = h.getp(body, "next");
263
266
  if (!h.is_noval(next) and h.is_noval(h.getp(paging, "next"))) {
264
267
  h.setp(paging, "next", next);
265
268
  }
269
+ const snake_cursor = h.getp(body, "next_cursor");
270
+ if (!h.is_noval(snake_cursor)) {
271
+ h.setp(paging, "cursor", snake_cursor);
272
+ }
266
273
  const cursor = h.getp(body, "cursor");
267
274
  if (!h.is_noval(cursor)) {
268
275
  h.setp(paging, "cursor", cursor);
@@ -271,6 +278,18 @@ pub const PagingFeature = struct {
271
278
  if (!h.is_noval(next_cursor)) {
272
279
  h.setp(paging, "cursor", next_cursor);
273
280
  }
281
+ if (h.is_noval(h.getp(paging, "nextPage"))) {
282
+ var np = h.getp(body, "nextPage");
283
+ if (h.is_noval(np)) np = h.getp(body, "next_page");
284
+ switch (np) {
285
+ .integer, .float, .string => h.setp(paging, "nextPage", np),
286
+ else => {},
287
+ }
288
+ }
289
+ if (h.get_bool(body, "has_more")) |has_more| {
290
+ h.setp(paging, "hasMore", h.vbool(has_more));
291
+ explicit_more = true;
292
+ }
274
293
  if (h.get_bool(body, "hasMore")) |has_more| {
275
294
  h.setp(paging, "hasMore", h.vbool(has_more));
276
295
  explicit_more = true;
@@ -292,6 +311,17 @@ pub const PagingFeature = struct {
292
311
 
293
312
  result.paging = paging;
294
313
  self.last = paging;
314
+
315
+ // `.object` is a *MapRef, so the caller's map is refilled in place; a
316
+ // fresh map on ctrl never reaches the caller.
317
+ if (ctx.ctrl.paging == .object) {
318
+ const shared = ctx.ctrl.paging.object;
319
+ shared.data.clearRetainingCapacity();
320
+ var it = paging.object.iterator();
321
+ while (it.next()) |kv| h.setp(ctx.ctrl.paging, kv.key_ptr.*, kv.value_ptr.*);
322
+ } else {
323
+ ctx.ctrl.paging = paging;
324
+ }
295
325
  }
296
326
 
297
327
  fn vname(p: *anyopaque) []const u8 {
@@ -109,15 +109,22 @@ fn envelope(ctx: *Context, data: Value) Value {
109
109
  const restf = h.getpath(&.{ "transform", "res" }, ctx.point);
110
110
  if (restf != .string) return data;
111
111
  const spec = restf.string;
112
- // Exactly `body.<key>`; a deeper path is not an envelope this mock can
113
- // synthesise, so it is left alone rather than guessed at.
112
+ // Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
113
+ // GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
114
114
  if (spec.len < 8) return data;
115
115
  if (!std.mem.startsWith(u8, spec, "`body.")) return data;
116
116
  if (!std.mem.endsWith(u8, spec, "`")) return data;
117
117
  const inner = spec[6 .. spec.len - 1];
118
118
  if (inner.len == 0) return data;
119
- if (std.mem.indexOfScalar(u8, inner, '.') != null) return data;
120
- return h.jo(&.{.{ inner, data }});
119
+ var out = data;
120
+ var end: usize = inner.len;
121
+ while (true) {
122
+ const cut = std.mem.lastIndexOfScalar(u8, inner[0..end], '.');
123
+ const start = if (cut) |c| c + 1 else 0;
124
+ out = h.jo(&.{.{ inner[start..end], out }});
125
+ if (cut) |c| end = c else break;
126
+ }
127
+ return out;
121
128
  }
122
129
 
123
130
  fn respond(ctx: *Context, status: i64, data: Value, extra: []const h.Pair) Value {
@@ -143,26 +150,62 @@ fn resolve_match(ctx: *Context, explicit: Value) Value {
143
150
  return h.omap();
144
151
  }
145
152
 
153
+ fn point_terminal(p: Value) bool {
154
+ const parts = h.getp(p, "parts");
155
+ if (parts != .array) return false;
156
+ const items = parts.array.data.items;
157
+ if (items.len == 0) return false;
158
+ const last = items[items.len - 1];
159
+ return last == .string and std.mem.startsWith(u8, last.string, "{");
160
+ }
161
+
162
+ fn point_depth(p: Value) usize {
163
+ const parts = h.getp(p, "parts");
164
+ return if (parts == .array) parts.array.data.items.len else 0;
165
+ }
166
+
167
+ // The entity's own endpoint: a terminal `{param}` marks a record route, and
168
+ // among equals the shallower path wins (the same rule as make_point).
169
+ fn pick_point(points: Value) Value {
170
+ if (points != .array) return h.vnull();
171
+ const items = points.array.data.items;
172
+ if (items.len == 0) return h.vnull();
173
+ var point = items[0];
174
+ for (items[1..]) |cand| {
175
+ if (point_terminal(cand) != point_terminal(point)) {
176
+ if (point_terminal(cand)) point = cand;
177
+ } else if (point_depth(cand) < point_depth(point)) {
178
+ point = cand;
179
+ }
180
+ }
181
+ return point;
182
+ }
183
+
184
+ fn reqd_names(point: Value, kind: []const u8) Value {
185
+ const args_path = h.getpath(&.{ "args", kind }, point);
186
+ const reqd_args = vs.select(h.A(), args_path, h.jo(&.{.{ "reqd", h.vbool(true) }})) catch return h.olist();
187
+ // transform reports collected injection errors beside the value; .out is
188
+ // the value itself, errors or not.
189
+ const tres = vs.transform(h.A(), reqd_args, h.ja(&.{
190
+ h.vstr("`$EACH`"),
191
+ h.vstr(""),
192
+ h.vstr("`$KEY.name`"),
193
+ })) catch return h.olist();
194
+ return tres.out;
195
+ }
196
+
146
197
  fn build_args(ctx: *Context, args: Value) Value {
147
198
  const op = ctx.op;
148
199
  const opname = op.name;
149
200
  const entname: []const u8 = if (ctx.entity) |e| e.get_name() else op.entity;
150
201
 
151
202
  const points = h.getpath(&.{ "entity", entname, "op", opname, "points" }, ctx.config);
152
- const point = h.get_elem(points, h.vnum(-1), h.vnull());
153
-
154
- const params_path = h.getpath(&.{ "args", "params" }, point);
155
- const reqd_params = vs.select(h.A(), params_path, h.jo(&.{.{ "reqd", h.vbool(true) }})) catch h.olist();
156
- const reqd = blk: {
157
- // transform now reports collected injection errors beside the value;
158
- // .out is what it used to return on its own, errors or not.
159
- const tres = vs.transform(h.A(), reqd_params, h.ja(&.{
160
- h.vstr("`$EACH`"),
161
- h.vstr(""),
162
- h.vstr("`$KEY.name`"),
163
- })) catch break :blk h.olist();
164
- break :blk tres.out;
165
- };
203
+ const point = pick_point(points);
204
+
205
+ // Path AND query: a path-only read misses a query-addressed record
206
+ // (e.g. GET /result?trace_id=), which has no path param at all.
207
+ const reqd_params = reqd_names(point, "params");
208
+ const reqd_query = reqd_names(point, "query");
166
209
 
167
210
  const qand = h.olist();
168
211
  const q = h.jo(&.{.{ "`$AND`", qand }});
@@ -171,8 +214,8 @@ fn build_args(ctx: *Context, args: Value) Value {
171
214
  const keys = h.keysof_vec(args);
172
215
  for (keys) |key| {
173
216
  const is_id = std.mem.eql(u8, key, "id");
174
- const selected = vs.select(h.A(), reqd, h.vstr(key)) catch h.olist();
175
- const is_reqd = !h.is_empty(selected);
217
+ const is_reqd = !h.is_empty(vs.select(h.A(), reqd_params, h.vstr(key)) catch h.olist()) or
218
+ !h.is_empty(vs.select(h.A(), reqd_query, h.vstr(key)) catch h.olist());
176
219
 
177
220
  if (is_id or is_reqd) {
178
221
  const v = ctx.util().param(ctx, h.vstr(key));
@@ -244,20 +287,12 @@ fn test_fetch(entity: Value, ctx: *Context, _: []const u8, _: Value) err.E!Value
244
287
  const args = build_args(ctx, update_match);
245
288
  const found = vs.select(h.A(), entmap, args) catch h.olist();
246
289
  var ent = h.get_elem(found, h.vnum(0), h.vnull());
247
- if (h.is_noval(ent) and h.sizeOf(entmap) > 0) {
248
- for (h.items_vec(entmap)) |kv| {
249
- if (kv.v == .object) {
250
- ent = kv.v;
251
- break;
252
- }
253
- }
254
- }
255
290
  if (h.is_noval(ent)) {
291
+ // update miss: 404, never another record
256
292
  return respond(ctx, 404, h.vnull(), &.{.{ "statusText", h.vstr("Not found") }});
257
293
  }
258
294
  if (ent == .object and reqdata == .object) {
259
- var it = reqdata.object.iterator();
260
- while (it.next()) |kv| h.setp(ent, kv.key_ptr.*, kv.value_ptr.*);
295
+ ent = h.merge(h.ja(&.{ ent, reqdata }));
261
296
  }
262
297
  h.del_prop(ent, h.vstr("$KEY"));
263
298
  return respond(ctx, 200, h.clone(ent), &.{});
@@ -3,7 +3,7 @@
3
3
  "package": 1
4
4
  },
5
5
  "name": "@voxgig/sdkgen",
6
- "version": "4.22.0",
6
+ "version": "4.24.0",
7
7
  "provides": {
8
8
  "target": [
9
9
  "c",
@@ -230,7 +230,7 @@ function orphanModelFiles(actx: ActionContext): string[] {
230
230
 
231
231
 
232
232
  async function doctor(
233
- actx: ActionContext, scope?: DoctorScope,
233
+ actx: ActionContext, scope?: DoctorScope, selected?: string[],
234
234
  ): Promise<ActionResult> {
235
235
  const log = actx.log
236
236
  const fs = actx.fs()
@@ -283,17 +283,18 @@ async function doctor(
283
283
  }
284
284
 
285
285
  if ('target' === kind) {
286
- checkTarget(actx, source, report)
286
+ checkTarget(actx, source, report, selected)
287
287
  }
288
288
 
289
289
  if ('edition' === kind) {
290
290
  checkEdition(actx, source, report)
291
291
  }
292
292
 
293
- // Only an ACTIVE feature has source copied out; what an inactive one
294
- // left behind is stale, and the target walk reports it as such.
293
+ // Only an ACTIVE feature has source copied out; an inactive one's
294
+ // leftovers are stale. `selected` overrides that for the caller's own.
295
295
  if ('feature' === kind &&
296
- false !== (model as any)?.main?.[KIT]?.feature?.[name]?.active) {
296
+ (false !== (model as any)?.main?.[KIT]?.feature?.[name]?.active ||
297
+ true === selected?.includes(name))) {
297
298
  checkFeatureSource(actx, source, targets, report)
298
299
  }
299
300
 
@@ -409,6 +410,7 @@ function resolveDeclared(
409
410
 
410
411
  function checkTarget(
411
412
  actx: ActionContext, resolved: Source, report: DoctorReport,
413
+ selected?: string[],
412
414
  ) {
413
415
  const tname = resolved.name
414
416
  const tfolder = resolved.folder
@@ -442,14 +444,15 @@ function checkTarget(
442
444
  },
443
445
  ]
444
446
 
445
- // The feature set `target add` would select right now. A project that
446
- // added its targets before feature trimming existed carries source for
447
- // features its model never declared — expected here as STALE, which is
448
- // exactly what it is.
447
+ // The feature set `target add` would select right now, plus any the CALLER
448
+ // is acting on (`selected`, see COMMENT-NOTES.md). A project that added its
449
+ // targets before feature trimming existed carries source for features its
450
+ // model never declared — expected here as STALE, which is what it is.
449
451
  const featuremodel: any = model?.main?.[KIT]?.feature ?? {}
450
452
  const features = Array.from(new Set([
451
453
  'test',
452
454
  ...Object.keys(featuremodel).filter((n: string) => false !== featuremodel[n]?.active),
455
+ ...(selected ?? []),
453
456
  ]))
454
457
 
455
458
  // `folder` and `model` matter: the trim catalogue is resolved consumer-side
@@ -39,6 +39,7 @@ function cmpBase(): string {
39
39
 
40
40
  const CMD_MAP: any = Object.assign(Object.create(null), {
41
41
  add: cmd_edition_add,
42
+ remove: cmd_edition_remove,
42
43
  })
43
44
 
44
45
 
@@ -65,6 +66,13 @@ async function cmd_edition_add(
65
66
  }
66
67
 
67
68
 
69
+ async function cmd_edition_remove(
70
+ args: string[], actx: ActionContext,
71
+ ): Promise<ActionResult> {
72
+ return require('./remove').kind_remove('edition', parseAddNames(args), actx)
73
+ }
74
+
75
+
68
76
  async function edition_add(
69
77
  edition: string[], actx: ActionContext,
70
78
  ): Promise<ActionResult> {
@@ -42,7 +42,8 @@ import {
42
42
 
43
43
 
44
44
  const CMD_MAP: any = {
45
- add: cmd_feature_add
45
+ add: cmd_feature_add,
46
+ remove: cmd_feature_remove,
46
47
  }
47
48
 
48
49
  const BASE = 'node_modules/@voxgig/sdkgen'
@@ -74,6 +75,11 @@ async function cmd_feature_add(args: string[], actx: ActionContext): Promise<Act
74
75
  }
75
76
 
76
77
 
78
+ async function cmd_feature_remove(args: string[], actx: ActionContext): Promise<ActionResult> {
79
+ return require('./remove').kind_remove('feature', parseAddNames(args), actx)
80
+ }
81
+
82
+
77
83
  async function feature_add(features: string[], actx: ActionContext): Promise<ActionResult> {
78
84
 
79
85
  // Reuse the caller's Jostraca instance so feature generation honours the