@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
@@ -109,18 +109,23 @@ public class TestFeature extends BaseFeature {
109
109
  return data;
110
110
  }
111
111
  String spec = (String) restf;
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.startsWith("`body.") || !spec.endsWith("`") || spec.length() < 8) {
115
115
  return data;
116
116
  }
117
117
  String inner = spec.substring(6, spec.length() - 1);
118
- if (inner.isEmpty() || inner.contains(".")) {
118
+ if (inner.isEmpty()) {
119
119
  return data;
120
120
  }
121
- Map<String, Object> wrapped = new LinkedHashMap<>();
122
- wrapped.put(inner, data);
123
- return wrapped;
121
+ String[] segs = inner.split("\\.", -1);
122
+ Object out = data;
123
+ for (int i = segs.length - 1; 0 <= i; i--) {
124
+ Map<String, Object> wrapped = new LinkedHashMap<>();
125
+ wrapped.put(segs[i], out);
126
+ out = wrapped;
127
+ }
128
+ return out;
124
129
  }
125
130
 
126
131
  private Map<String, Object> respond(Context ctx, int status, Object data, Map<String, Object> extra) {
@@ -223,19 +228,12 @@ public class TestFeature extends BaseFeature {
223
228
  Object args = buildArgs(ctx, op, updateMatch);
224
229
  List<Object> found = Struct.select(entmap, args);
225
230
  Object ent = Struct.getelem(found, 0);
226
- if (ent == null && entmap != null) {
227
- for (Object e : entmap.values()) {
228
- if (e instanceof Map) {
229
- ent = e;
230
- break;
231
- }
232
- }
233
- }
234
231
  if (ent == null) {
232
+ // update miss: 404, never another record
235
233
  return respond(ctx, 404, null, extra("statusText", "Not found"));
236
234
  }
237
235
  if (ent instanceof Map && ctx.reqdata != null) {
238
- ((Map<String, Object>) ent).putAll(ctx.reqdata);
236
+ Struct.merge(Struct.jt(ent, ctx.reqdata));
239
237
  }
240
238
  Struct.delprop(ent, "$KEY");
241
239
  Object out = Struct.clone(ent);
@@ -369,10 +367,14 @@ public class TestFeature extends BaseFeature {
369
367
  }
370
368
  }
371
369
 
372
- // Get required params.
373
- Object paramsPath = Struct.getpath(point, List.of("args", "params"));
374
- Object reqdParams = Struct.select(paramsPath, Struct.jm("reqd", true));
375
- Object reqd = Struct.transform(reqdParams,
370
+ // Path AND query: a path-only read misses a query-addressed record
371
+ // (e.g. GET /result?trace_id=), which has no path param at all.
372
+ List<Object> reqdArgs = Struct.jt();
373
+ for (String kind : new String[] { "params", "query" }) {
374
+ Object argsPath = Struct.getpath(point, List.of("args", kind));
375
+ reqdArgs.addAll(Struct.select(argsPath, Struct.jm("reqd", true)));
376
+ }
377
+ Object reqd = Struct.transform(reqdArgs,
376
378
  Struct.jt("`$EACH`", "", "`$KEY.name`"));
377
379
 
378
380
  List<Object> qand = Struct.jt();
@@ -405,6 +405,9 @@ public class FeatureCorpusTest {
405
405
  ProjectNameSDK probe = buildClient(Map.of("feature",
406
406
  List.of(Map.of("name", name, "active", true))));
407
407
  if (null == record(probe, name)) {
408
+ // The one line every runner prints for an inert section.
409
+ System.err.println(String.format(
410
+ "feature.%s: inert (this SDK does not generate the feature)", name));
408
411
  continue;
409
412
  }
410
413
 
@@ -867,6 +867,48 @@ public class FeatureTest {
867
867
  assertEquals(true, res.result.paging.get("hasMore"), "expected hasMore");
868
868
  }
869
869
 
870
+ @Test
871
+ public void paging_snakeCaseSignalsAndCtrlWriteBack() {
872
+ assumeFeatures("paging");
873
+ FhRecorder rec = new FhRecorder();
874
+ rec.reply = (n, fetchdef) -> 1 == n
875
+ ? fhResponse(200, fhMap("has_more", true, "next_cursor", "c2"), null)
876
+ : fhResponse(200, fhMap("has_more", false), null);
877
+ FhHarness h = fhMake(rec::fetch, fhF(new PagingFeature(), null));
878
+ Map<String, Object> pg = new LinkedHashMap<>();
879
+ Map<String, Object> ctrl = fhMap("paging", pg);
880
+ FhOpResult res = h.op(fhOp("list").path("/w").ctrl(ctrl));
881
+ assertEquals(true, res.result.paging.get("hasMore"), "expected has_more read");
882
+ assertEquals("c2", res.result.paging.get("cursor"), "expected next_cursor read");
883
+ assertEquals("c2", pg.get("cursor"), "expected record written back into ctrl");
884
+ assertEquals(true, pg.get("hasMore"), "expected record written back into ctrl");
885
+ h.op(fhOp("list").path("/w").ctrl(ctrl));
886
+ assertTrue(rec.url(1).contains("cursor=c2"),
887
+ "expected written-back cursor sent: " + rec.url(1));
888
+ assertEquals(false, pg.get("hasMore"), "expected ctrl to carry the last record");
889
+ assertNull(pg.get("cursor"), "expected ctrl to carry the last record");
890
+ }
891
+
892
+ @Test
893
+ public void paging_continuesFromWrittenBackNextPage() {
894
+ assumeFeatures("paging");
895
+ FhRecorder rec = new FhRecorder();
896
+ rec.reply = (n, fetchdef) -> fhResponse(200,
897
+ 1 == n ? fhMap("next_page", 2) : fhMap(),
898
+ fhMap("x-page", String.valueOf(n)));
899
+ FhHarness h = fhMake(rec::fetch, fhF(new PagingFeature(), null));
900
+ Map<String, Object> pg = new LinkedHashMap<>();
901
+ Map<String, Object> ctrl = fhMap("paging", pg);
902
+ h.op(fhOp("list").path("/w").ctrl(ctrl));
903
+ assertEquals(1, pg.get("page"), "expected x-page written back");
904
+ assertEquals(2, pg.get("nextPage"), "expected next_page written back");
905
+ assertEquals(true, pg.get("hasMore"), "expected hasMore inferred from next_page");
906
+ h.op(fhOp("list").path("/w").ctrl(ctrl));
907
+ assertTrue(rec.url(1).contains("page=2"),
908
+ "expected written-back next page sent: " + rec.url(1));
909
+ assertEquals(false, pg.get("hasMore"), "expected no more pages");
910
+ }
911
+
870
912
  @Test
871
913
  public void paging_nonListNotPaged() {
872
914
  assumeFeatures("paging");
@@ -9,6 +9,7 @@ import java.net.http.HttpResponse;
9
9
  import java.util.LinkedHashMap;
10
10
  import java.util.List;
11
11
  import java.util.Map;
12
+ import java.util.concurrent.ConcurrentHashMap;
12
13
  import java.util.function.BiFunction;
13
14
  import java.util.function.Supplier;
14
15
 
@@ -20,6 +21,40 @@ final class Fetcher {
20
21
 
21
22
  private Fetcher() {}
22
23
 
24
+ // Clients keyed by redirect policy and proxy. Each HttpClient owns a
25
+ // connection pool and a selector thread, so one per request reused
26
+ // nothing; one per key pools across calls.
27
+ private static final ConcurrentHashMap<String, HttpClient> CLIENTS =
28
+ new ConcurrentHashMap<>();
29
+
30
+ private static HttpClient clientFor(Map<String, Object> fetchdef) {
31
+ // "manual" (set by the station feature's middleware under a hosts
32
+ // policy) returns a 3xx like any other response: an automatic follow
33
+ // would carry injected credentials to a host no policy approved.
34
+ final HttpClient.Redirect redirectPolicy =
35
+ "manual".equals(fetchdef.get("redirect"))
36
+ ? HttpClient.Redirect.NEVER
37
+ : HttpClient.Redirect.NORMAL;
38
+
39
+ Object praw = fetchdef.get("proxy");
40
+ final String proxy = praw instanceof String ? (String) praw : "";
41
+
42
+ return CLIENTS.computeIfAbsent(redirectPolicy + "|" + proxy, key -> {
43
+ HttpClient.Builder clientb = HttpClient.newBuilder().followRedirects(redirectPolicy);
44
+ if (!"".equals(proxy)) {
45
+ try {
46
+ URI proxyUri = URI.create(proxy);
47
+ int port = proxyUri.getPort() < 0 ? 80 : proxyUri.getPort();
48
+ clientb.proxy(ProxySelector.of(new InetSocketAddress(proxyUri.getHost(), port)));
49
+ }
50
+ catch (RuntimeException e) {
51
+ // Unparseable proxy target: direct connection, as the go transport.
52
+ }
53
+ }
54
+ return clientb.build();
55
+ });
56
+ }
57
+
23
58
  static Map<String, Object> defaultHttpFetch(String fullurl, Map<String, Object> fetchdef) {
24
59
  String method = fetchdef.get("method") instanceof String
25
60
  ? (String) fetchdef.get("method") : "";
@@ -59,36 +94,9 @@ final class Fetcher {
59
94
  reqb.setHeader("User-Agent", "Mozilla/5.0 (compatible; ProjectNameSDK/1.0)");
60
95
  }
61
96
 
62
- // Honour a redirect annotation on the fetch definition (set by the
63
- // station feature's middleware under a hosts policy): "manual" returns
64
- // a 3xx like any other response instead of following it — the ts
65
- // donor's fetch honours the same key natively, and an automatic follow
66
- // would carry injected credentials to a host no policy approved.
67
- HttpClient.Redirect redirectPolicy =
68
- "manual".equals(fetchdef.get("redirect"))
69
- ? HttpClient.Redirect.NEVER
70
- : HttpClient.Redirect.NORMAL;
71
-
72
- // Honour a proxy annotation on the fetch definition (set by the proxy
73
- // feature): route the request through a proxied HttpClient.
74
- HttpClient.Builder clientb = HttpClient.newBuilder()
75
- .followRedirects(redirectPolicy);
76
- Object proxy = fetchdef.get("proxy");
77
- if (proxy instanceof String && !"".equals(proxy)) {
78
- try {
79
- URI proxyUri = URI.create((String) proxy);
80
- int port = proxyUri.getPort() < 0 ? 80 : proxyUri.getPort();
81
- clientb.proxy(ProxySelector.of(new InetSocketAddress(proxyUri.getHost(), port)));
82
- }
83
- catch (RuntimeException e) {
84
- // Unparseable proxy target: fall through to a direct connection,
85
- // mirroring the go transport (bad proxy URL is ignored).
86
- }
87
- }
88
-
89
97
  HttpResponse<String> resp;
90
98
  try {
91
- resp = clientb.build().send(reqb.build(), HttpResponse.BodyHandlers.ofString());
99
+ resp = clientFor(fetchdef).send(reqb.build(), HttpResponse.BodyHandlers.ofString());
92
100
  }
93
101
  catch (Exception e) {
94
102
  throw new RuntimeException("fetch: " + e.getMessage(), e);
@@ -35,7 +35,7 @@ final class PrepareQuery {
35
35
  for (List<Object> item : Struct.items(reqmatch)) {
36
36
  String key = item.get(0) instanceof String ? (String) item.get(0) : "";
37
37
  Object val = item.get(1);
38
- if (val != null && !containsStr(params, key)) {
38
+ if (val != null && !"$action".equals(key) && !containsStr(params, key)) {
39
39
  out.put(key, val);
40
40
  }
41
41
  }
@@ -19,17 +19,32 @@ final class TransformRequest {
19
19
  Map<String, Object> transform =
20
20
  Helpers.toMapAny(Struct.getprop(ctx.point, "transform"));
21
21
  if (transform == null) {
22
- return ctx.reqdata;
22
+ return stripAction(ctx.reqdata);
23
23
  }
24
24
 
25
25
  Object reqform = Struct.getprop(transform, "req", null);
26
26
  if (reqform == null) {
27
- return ctx.reqdata;
27
+ return stripAction(ctx.reqdata);
28
28
  }
29
29
 
30
30
  Map<String, Object> data = new LinkedHashMap<>();
31
31
  data.put("reqdata", ctx.reqdata);
32
32
 
33
- return Struct.transform(data, reqform);
33
+ return stripAction(Struct.transform(data, reqform));
34
+ }
35
+
36
+ // `$action` selects the point (see MakePoint); it is never an API field, so
37
+ // the body is a copy without it. The caller's map is left untouched.
38
+ private static Object stripAction(Object reqdata) {
39
+ if (!(reqdata instanceof Map) || !((Map<?, ?>) reqdata).containsKey("$action")) {
40
+ return reqdata;
41
+ }
42
+ Map<String, Object> body = new LinkedHashMap<>();
43
+ for (Map.Entry<?, ?> e : ((Map<?, ?>) reqdata).entrySet()) {
44
+ if (!"$action".equals(e.getKey())) {
45
+ body.put(String.valueOf(e.getKey()), e.getValue());
46
+ }
47
+ }
48
+ return body;
34
49
  }
35
50
  }
@@ -57,7 +57,13 @@ class Context {
57
57
  this.client = getprop(ctxmap, 'client', getprop(basectx, 'client'))
58
58
  this.utility = getprop(ctxmap, 'utility', getprop(basectx, 'utility'))
59
59
 
60
- this.ctrl = getprop(ctxmap, 'ctrl', getprop(basectx, 'ctrl', this.ctrl))
60
+ // An operation gets its OWN control unless the caller passed one: a
61
+ // paging cursor left on the client's control would otherwise be picked
62
+ // up by the next, unrelated call. A context with no opname is not an
63
+ // operation, so it still shares (an entity's, with the client's).
64
+ const opname = getprop(ctxmap, 'opname')
65
+ const basectrl = null == opname ? getprop(basectx, 'ctrl', this.ctrl) : this.ctrl
66
+ this.ctrl = getprop(ctxmap, 'ctrl', basectrl)
61
67
  this.meta = getprop(ctxmap, 'meta', getprop(basectx, 'meta', this.meta))
62
68
 
63
69
  this.config = getprop(ctxmap, 'config', getprop(basectx, 'config'))
@@ -78,7 +84,6 @@ class Context {
78
84
  this.result = getprop(ctxmap, 'result', getprop(basectx, 'result'))
79
85
  this.response = getprop(ctxmap, 'response', getprop(basectx, 'response'))
80
86
 
81
- const opname = getprop(ctxmap, 'opname')
82
87
  this.op = this.resolveOp(opname)
83
88
  }
84
89
 
@@ -7,8 +7,9 @@ const { BaseFeature } = require('../base/BaseFeature')
7
7
  // stamps page/limit (or a cursor) into the request query; on the way back
8
8
  // (PreResult) it reads the server's pagination signals — a `Link:
9
9
  // rel="next"` header, `X-Next-Page`/`X-Total-Count` headers, or `next`/
10
- // `cursor`/`hasMore` fields in the body — and records them on
11
- // `ctx.result.paging`. Generated SDKs build auto-iteration on top of this
10
+ // `cursor`/`hasMore` fields in the body (snake_case forms too) — and
11
+ // records them on `ctx.result.paging` and the caller's `ctrl.paging`.
12
+ // Generated SDKs build auto-iteration on top of this
12
13
  // (advance the cursor/page and re-issue the list call until `hasMore` is
13
14
  // false). Parameter names and page size are configurable.
14
15
  class PagingFeature extends BaseFeature {
@@ -28,7 +29,7 @@ class PagingFeature extends BaseFeature {
28
29
 
29
30
 
30
31
  PreRequest(ctx) {
31
- if (!this._isList(ctx)) {
32
+ if (!this.active || !this._isList(ctx)) {
32
33
  return
33
34
  }
34
35
  const spec = ctx.spec
@@ -58,7 +59,10 @@ class PagingFeature extends BaseFeature {
58
59
  spec.query[cursorParam] = paging.cursor
59
60
  }
60
61
  else if (null == spec.query[pageParam]) {
61
- spec.query[pageParam] = null != paging.page ? paging.page : (this._options.startPage || 1)
62
+ // A record written back by PreResult holds the page just fetched as
63
+ // `page` and the one to fetch as `nextPage`, so nextPage wins.
64
+ spec.query[pageParam] = null != paging.nextPage ? paging.nextPage :
65
+ null != paging.page ? paging.page : (this._options.startPage || 1)
62
66
  }
63
67
 
64
68
  if (null != this._options.limit && null == spec.query[limitParam]) {
@@ -68,7 +72,7 @@ class PagingFeature extends BaseFeature {
68
72
 
69
73
 
70
74
  PreResult(ctx) {
71
- if (!this._isList(ctx)) {
75
+ if (!this.active || !this._isList(ctx)) {
72
76
  return
73
77
  }
74
78
  const result = ctx.result
@@ -124,11 +128,20 @@ class PagingFeature extends BaseFeature {
124
128
  }
125
129
  }
126
130
 
127
- // Body-level cursors.
131
+ // Body-level signals; snake_case forms are read first so camelCase wins.
128
132
  if (body && 'object' === typeof body) {
129
133
  if (null != body.next) { paging.next = paging.next || body.next }
134
+ if (null != body.next_cursor) { paging.cursor = body.next_cursor }
130
135
  if (null != body.cursor) { paging.cursor = body.cursor }
131
136
  if (null != body.nextCursor) { paging.cursor = body.nextCursor }
137
+ if (null == paging.nextPage) {
138
+ const np = null != body.nextPage ? body.nextPage : body.next_page
139
+ if ('number' === typeof np || 'string' === typeof np) { paging.nextPage = np }
140
+ }
141
+ if ('boolean' === typeof body.has_more) {
142
+ paging.hasMore = body.has_more
143
+ explicitMore = true
144
+ }
132
145
  if ('boolean' === typeof body.hasMore) {
133
146
  paging.hasMore = body.hasMore
134
147
  explicitMore = true
@@ -147,6 +160,11 @@ class PagingFeature extends BaseFeature {
147
160
 
148
161
  result.paging = paging
149
162
 
163
+ // ctx.ctrl is the caller's own object, so the record reaches them.
164
+ if (null != ctx.ctrl) {
165
+ ctx.ctrl.paging = paging
166
+ }
167
+
150
168
  const client = this._client
151
169
  client._paging = { last: paging }
152
170
  }
@@ -148,6 +148,7 @@ class TestFeature extends BaseFeature {
148
148
  const found = select(entmap, args)
149
149
  const ent = getelem(found, 0)
150
150
  if (null == ent) {
151
+ // update miss: 404, never another record
151
152
  return respond(404, undefined, { statusText: S_NOT_FOUND })
152
153
  }
153
154
  else {
@@ -161,13 +162,12 @@ class TestFeature extends BaseFeature {
161
162
  const args = self.buildArgs(ctx, op, ctx.reqmatch)
162
163
  const found = select(entmap, args)
163
164
  const ent = getelem(found, 0)
164
- if (null == ent) {
165
- return respond(404, undefined, { statusText: S_NOT_FOUND })
166
- }
167
- else {
165
+ // Remove only the first matched entity. If nothing matches,
166
+ // succeed as a no-op rather than erroring.
167
+ if (null != ent) {
168
168
  delprop(entmap, getprop(ent, 'id'))
169
- return respond(200)
170
169
  }
170
+ return respond(200)
171
171
  }
172
172
  else if ('create' === op.name) {
173
173
  const args = self.buildArgs(ctx, op, ctx.reqdata)
@@ -183,6 +183,8 @@ class TestFeature extends BaseFeature {
183
183
  const out = clone(ent)
184
184
  return respond(200, out)
185
185
  }
186
+
187
+ return respond(404, undefined, { statusText: 'Unknown operation' })
186
188
  }
187
189
 
188
190
  // Optional network behaviour simulation over the mock transport. Enable
@@ -13,7 +13,7 @@ function prepareQuery(ctx) {
13
13
 
14
14
  const out = {}
15
15
  for (let [key, val] of items(reqmatch)) {
16
- if (null != val && !params.includes(key)) {
16
+ if (null != val && '$action' !== key && !params.includes(key)) {
17
17
  out[key] = val
18
18
  }
19
19
  }
@@ -254,6 +254,10 @@ describe('FeatureCorpus', () => {
254
254
 
255
255
  const probe = makeClient({})
256
256
  if (!probe._rootctx.config.hasFeature(name)) {
257
+ // The one line every runner prints for a section that names a
258
+ // feature this SDK does not generate, so an inert section is
259
+ // visible in the output rather than inferred from a green tick.
260
+ t.diagnostic(`feature.${name}: inert (this SDK does not generate the feature)`)
257
261
  return t.skip(`this SDK was generated without the ${name} feature`)
258
262
  }
259
263
 
@@ -10,26 +10,26 @@ const live_runner_1 = require("./live-runner");
10
10
  const utility_1 = require("./utility");
11
11
  // The offline flow keeps its deterministic fixture assertions. Live flows
12
12
  // resolve real prerequisites per operation and collect failures until done.
13
- async function runLiveEntity(setup, entity, flow, accessor) {
13
+ async function runLiveEntity(setup, entity, flow, accessor, facts = {}) {
14
14
  const { client, transport } = setup;
15
- const steps = flow.step || [];
15
+ const steps = (flow.step || []).filter((step) => false !== step.a);
16
16
  const created = new Map();
17
17
  const listed = [];
18
18
  const marks = new Map();
19
19
  const idField = entity.id?.field || 'id';
20
20
  const copy = (value) => JSON.parse(JSON.stringify(value ?? {}));
21
- const hasCreate = steps.some(step => step.op === 'create');
21
+ const hasCreate = steps.some(step => step.o === 'create');
22
22
  const report = await (0, live_runner_1.runLiveSteps)(steps.map((step, index) => {
23
- const ref = step.input?.ref || entity.name + '_ref01';
24
- const op = step.op;
23
+ const ref = step.i?.ref || entity.name + '_ref01';
24
+ const op = step.o;
25
25
  const excluded = (0, utility_1.isControlSkipped)('entityOp', entity.name + '.' + op, 'live');
26
26
  return {
27
27
  id: entity.name + '.' + op + '.' + index,
28
- cleanup: op === 'remove' || (step.valid || []).some((v) => v.apply === 'ItemNotExists'),
28
+ cleanup: op === 'remove' || (step.v || []).some((v) => v.apply === 'ItemNotExists'),
29
29
  excluded: excluded.skip ? excluded.reason || 'Excluded by test control' : undefined,
30
30
  run: async (context) => {
31
31
  transport.enter(context);
32
- const points = entity.op?.[op]?.points || [];
32
+ const points = (entity.op?.[op]?.points || []).filter((point) => false !== point.a);
33
33
  if (!points.length)
34
34
  throw new live_runner_1.LiveBlocked('No modelled operation point');
35
35
  const record = created.get(ref);
@@ -48,7 +48,7 @@ async function runLiveEntity(setup, entity, flow, accessor) {
48
48
  }
49
49
  let input = op === 'create'
50
50
  ? copy(setup.data.new?.[entity.name]?.[ref]) : {};
51
- for (const [name, binding] of Object.entries({ ...step.match, ...step.data })) {
51
+ for (const [name, binding] of Object.entries({ ...step.m, ...step.d })) {
52
52
  const value = setup.idmap[binding] ?? setup.idmap[name];
53
53
  if (undefined !== value)
54
54
  input[name] = value;
@@ -66,22 +66,22 @@ async function runLiveEntity(setup, entity, flow, accessor) {
66
66
  let selected;
67
67
  const missing = new Set();
68
68
  for (const point of points) {
69
- if (point.select?.$action !== input.$action)
69
+ if (point.q?.$action !== input.$action)
70
70
  continue;
71
71
  const candidate = { ...input };
72
72
  let viable = true;
73
- const params = point.args?.params || [];
74
- const query = (point.args?.query || []).filter((arg) => arg.reqd);
73
+ const params = point.g?.params || [];
74
+ const query = (point.g?.query || []).filter((arg) => arg.r);
75
75
  for (const arg of [...params, ...query]) {
76
- if (undefined !== candidate[arg.name] && null !== candidate[arg.name])
76
+ if (undefined !== candidate[arg.n] && null !== candidate[arg.n])
77
77
  continue;
78
- const key = arg.name === 'id' ? entity.name + '01' : arg.name.replace(/_id$/, '') + '01';
79
- const value = setup.idmap[key] ?? setup.idmap[arg.name] ?? loaded?.[arg.name] ?? arg.example;
78
+ const key = arg.n === 'id' ? entity.name + '01' : arg.n.replace(/_id$/, '') + '01';
79
+ const value = setup.idmap[key] ?? setup.idmap[arg.n] ?? loaded?.[arg.n] ?? arg.ex;
80
80
  if (undefined !== value && null !== value)
81
- candidate[arg.name] = value;
82
- else if (arg.reqd !== false) {
81
+ candidate[arg.n] = value;
82
+ else if (arg.r !== false) {
83
83
  viable = false;
84
- missing.add(arg.name);
84
+ missing.add(arg.n);
85
85
  }
86
86
  }
87
87
  if (viable) {
@@ -93,22 +93,22 @@ async function runLiveEntity(setup, entity, flow, accessor) {
93
93
  if (!resolved)
94
94
  throw new live_runner_1.LiveBlocked('No usable route; missing arguments: ' + [...missing].join(', '));
95
95
  input = resolved;
96
- if (op === 'create' && selected.contract) {
97
- const facts = JSON.parse(selected.contract.json);
98
- const request = (0, live_contract_1.requestContract)(facts);
96
+ if (op === 'create' && facts[selected.m + ' ' + selected.o]) {
97
+ const selectedFacts = facts[selected.m + ' ' + selected.o];
98
+ const request = (0, live_contract_1.requestContract)(selectedFacts);
99
99
  if (request.schema)
100
- input = { ...(0, live_contract_1.synthesizeInput)(request.schema, facts.live?.input ?? request.example) };
101
- else if (facts.protocol === 'http')
100
+ input = { ...(0, live_contract_1.synthesizeInput)(request.schema, selected.li?.input ?? request.example) };
101
+ else if (selectedFacts.protocol === 'http')
102
102
  input = {};
103
- for (const arg of selected.args?.params || [])
104
- if (resolved[arg.name] !== undefined)
105
- input[arg.name] = resolved[arg.name];
103
+ for (const arg of selected.g?.params || [])
104
+ if (resolved[arg.n] !== undefined)
105
+ input[arg.n] = resolved[arg.n];
106
106
  }
107
107
  let intendedMark;
108
108
  if (op === 'update') {
109
- for (const spec of step.spec || []) {
110
- if (spec.apply === 'TextFieldMark' && step.input?.textfield) {
111
- const mark = { name: step.input.textfield, value: spec.def.mark + '_' + setup.now };
109
+ for (const spec of step.s || []) {
110
+ if (spec.apply === 'TextFieldMark' && step.i?.textfield) {
111
+ const mark = { name: step.i.textfield, value: spec.def.mark + '_' + setup.now };
112
112
  input[mark.name] = mark.value;
113
113
  intendedMark = mark;
114
114
  }
@@ -127,7 +127,7 @@ async function runLiveEntity(setup, entity, flow, accessor) {
127
127
  });
128
128
  listed.splice(0, listed.length, ...data);
129
129
  context.publish(data);
130
- for (const validation of step.valid || []) {
130
+ for (const validation of step.v || []) {
131
131
  const previous = created.get(validation.def?.ref);
132
132
  const id = previous?.[idField] ?? previous?.id;
133
133
  if (undefined === id)
@@ -64,10 +64,10 @@ async function runLiveScenarios(SDK, plan, envPrefix, liveDefaults = {}) {
64
64
  let input = request.schema ? (0, live_contract_1.synthesizeInput)(request.schema, explicit) : explicit ?? {};
65
65
  for (const kind of ['params', 'query', 'header', 'cookie'])
66
66
  for (const arg of point.args?.[kind] || []) {
67
- if (arg.reqd && input[arg.name] === undefined) {
68
- if (arg.example === undefined)
69
- throw new live_runner_1.LiveBlocked('Missing required argument: ' + arg.name);
70
- input[arg.name] = arg.example;
67
+ if (arg.r && input[arg.n] === undefined) {
68
+ if (arg.ex === undefined)
69
+ throw new live_runner_1.LiveBlocked('Missing required argument: ' + arg.n);
70
+ input[arg.n] = arg.ex;
71
71
  }
72
72
  }
73
73
  const role = hint.auth || (point.facts.security?.length === 0 || point.facts.securitySource === 'unspecified' ? 'public' : 'account');
@@ -76,7 +76,7 @@ class Context(ctxmap: MutableMap<String, Any?>?, basectx: Context?) {
76
76
  } else if (cv is Control) {
77
77
  this.ctrl = cv
78
78
  }
79
- } else if (basectx != null) {
79
+ } else if (basectx != null && Helpers.getCtxProp(ctxmap, "opname") == null) {
80
80
  this.ctrl = basectx.ctrl
81
81
  }
82
82
 
@@ -8,8 +8,9 @@ import KOTLINPACKAGE.utility.struct.Struct
8
8
 
9
9
  // Pagination support for list operations. On the way out (PreRequest) it
10
10
  // stamps page/limit (or a cursor) into the request query; on the way back
11
- // (PreResult) it reads the server's pagination signals and records them on
12
- // `ctx.result.paging`.
11
+ // (PreResult) it reads the server's pagination signals (camelCase and
12
+ // snake_case body forms) and records them on `ctx.result.paging` and the
13
+ // caller's `ctrl.paging`.
13
14
  @Suppress("UNCHECKED_CAST")
14
15
  class PagingFeature : BaseFeature("paging", "0.0.1", true) {
15
16
 
@@ -53,7 +54,9 @@ class PagingFeature : BaseFeature("paging", "0.0.1", true) {
53
54
  if (cursor != null) {
54
55
  spec.query[cursorParam] = cursor
55
56
  } else if (spec.query[pageParam] == null) {
56
- val page = paging["page"]
57
+ // A record written back by preResult holds the page just fetched as
58
+ // "page" and the one to fetch as "nextPage", so nextPage wins.
59
+ val page = paging["nextPage"] ?: paging["page"]
57
60
  if (page != null) {
58
61
  spec.query[pageParam] = page
59
62
  } else {
@@ -166,18 +169,33 @@ class PagingFeature : BaseFeature("paging", "0.0.1", true) {
166
169
  }
167
170
  }
168
171
 
169
- // Body-level cursors.
172
+ // Body-level signals; snake_case forms are read first so camelCase wins.
170
173
  if (body is MutableMap<*, *>) {
171
174
  val bm = body as MutableMap<String, Any?>
172
175
  if (bm["next"] != null && paging["next"] == null) {
173
176
  paging["next"] = bm["next"]
174
177
  }
178
+ if (bm["next_cursor"] != null) {
179
+ paging["cursor"] = bm["next_cursor"]
180
+ }
175
181
  if (bm["cursor"] != null) {
176
182
  paging["cursor"] = bm["cursor"]
177
183
  }
178
184
  if (bm["nextCursor"] != null) {
179
185
  paging["cursor"] = bm["nextCursor"]
180
186
  }
187
+ if (paging["nextPage"] == null) {
188
+ val np = bm["nextPage"] ?: bm["next_page"]
189
+ if (np is Number) {
190
+ paging["nextPage"] = np.toInt()
191
+ } else if (np is String) {
192
+ paging["nextPage"] = np
193
+ }
194
+ }
195
+ if (bm["has_more"] is Boolean) {
196
+ paging["hasMore"] = bm["has_more"]
197
+ explicitMore = true
198
+ }
181
199
  if (bm["hasMore"] is Boolean) {
182
200
  paging["hasMore"] = bm["hasMore"]
183
201
  explicitMore = true
@@ -197,6 +215,20 @@ class PagingFeature : BaseFeature("paging", "0.0.1", true) {
197
215
 
198
216
  result.paging = paging
199
217
  this.last = paging
218
+
219
+ // The Context shares the caller's paging map by reference, so refill it
220
+ // in place; an immutable map falls back to replacing the reference.
221
+ val shared = ctx.ctrl.paging
222
+ if (shared == null) {
223
+ ctx.ctrl.paging = paging
224
+ } else {
225
+ try {
226
+ shared.clear()
227
+ shared.putAll(paging)
228
+ } catch (e: UnsupportedOperationException) {
229
+ ctx.ctrl.paging = paging
230
+ }
231
+ }
200
232
  }
201
233
 
202
234
  private fun isList(ctx: Context): Boolean {