@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
@@ -55,16 +55,22 @@ defmodule ProjectName.Feature.Test do
55
55
  defp envelope(fctx, data) do
56
56
  spec = S.getprop(S.getprop(S.getprop(fctx, "point"), "transform"), "res")
57
57
 
58
- # Exactly `body.<key>`; a deeper path is not an envelope this mock can
59
- # synthesise, so it is left alone rather than guessed at.
58
+ # Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
59
+ # GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
60
60
  case {data, spec} do
61
61
  {nil, _} ->
62
62
  data
63
63
 
64
64
  {_, s} when is_binary(s) ->
65
- case Regex.run(~r/^`body\.([^`.]+)`$/, s) do
66
- [_, inner] -> S.jm([inner, data])
67
- _ -> data
65
+ case Regex.run(~r/^`body\.(.+)`$/, s) do
66
+ [_, inner] ->
67
+ inner
68
+ |> String.split(".")
69
+ |> Enum.reverse()
70
+ |> Enum.reduce(data, fn seg, out -> S.jm([seg, out]) end)
71
+
72
+ _ ->
73
+ data
68
74
  end
69
75
 
70
76
  _ ->
@@ -161,20 +167,11 @@ defmodule ProjectName.Feature.Test do
161
167
  found = S.select(entmap, args)
162
168
  ent = S.getelem(found, 0)
163
169
 
164
- ent =
165
- if ent == nil and S.ismap(entmap) do
166
- ks = S.keysof(entmap)
167
- Enum.find_value(ks, fn k -> v = S.getprop(entmap, k); if S.ismap(v), do: v end)
168
- else
169
- ent
170
- end
171
-
172
170
  if ent == nil do
171
+ # update miss: 404, never another record
173
172
  respond(fctx, 404, nil, S.jm(["statusText", "Not found"]))
174
173
  else
175
- if S.ismap(ent) and reqdata != nil do
176
- Enum.each(H.entries(reqdata), fn {k, v} -> S.setprop(ent, k, v) end)
177
- end
174
+ if S.ismap(ent) and S.ismap(reqdata), do: S.merge(S.jt([ent, reqdata]))
178
175
 
179
176
  S.delprop(ent, "$KEY")
180
177
  respond(fctx, 200, S.clone(ent))
@@ -216,6 +213,45 @@ defmodule ProjectName.Feature.Test do
216
213
  :crypto.strong_rand_bytes(8) |> Base.encode16(case: :lower)
217
214
  end
218
215
 
216
+ defp point_terminal?(p) do
217
+ parts = S.getprop(p, "parts")
218
+ n = if S.islist(parts), do: S.size(parts), else: 0
219
+ last = if n > 0, do: S.getelem(parts, n - 1), else: nil
220
+ is_binary(last) and String.starts_with?(last, "{")
221
+ end
222
+
223
+ defp point_depth(p) do
224
+ parts = S.getprop(p, "parts")
225
+ if S.islist(parts), do: S.size(parts), else: 0
226
+ end
227
+
228
+ # The entity's own endpoint: a terminal `{param}` marks a record route,
229
+ # and among equals the shallower path wins (the same rule as make_point).
230
+ defp pick_point(points) do
231
+ n = if S.islist(points), do: S.size(points), else: 0
232
+
233
+ if n == 0 do
234
+ nil
235
+ else
236
+ rest = if n > 1, do: Enum.to_list(1..(n - 1)), else: []
237
+
238
+ Enum.reduce(rest, S.getelem(points, 0), fn i, point ->
239
+ cand = S.getelem(points, i)
240
+
241
+ cond do
242
+ point_terminal?(cand) != point_terminal?(point) -> if point_terminal?(cand), do: cand, else: point
243
+ point_depth(cand) < point_depth(point) -> cand
244
+ true -> point
245
+ end
246
+ end)
247
+ end
248
+ end
249
+
250
+ defp reqd_names(point, kind) do
251
+ reqd_args = S.select(S.getpath(point, "args." <> kind), S.jm(["reqd", true]))
252
+ S.transform(reqd_args, S.jt(["`$EACH`", "", "`$KEY.name`"]))
253
+ end
254
+
219
255
  # Build a struct select query ($AND of $OR alternatives) from the required
220
256
  # params + id, resolving each value through the pipeline param resolver.
221
257
  def build_args(_f, ctx, op, args) do
@@ -223,10 +259,11 @@ defmodule ProjectName.Feature.Test do
223
259
  config = S.getprop(ctx, "config")
224
260
  entname = Context.entity_name(S.getprop(ctx, "entity"))
225
261
  points = S.getpath(config, "entity." <> entname <> ".op." <> opname <> ".points")
226
- point = S.getelem(points, -1)
227
- params_path = S.getpath(point, "args.params")
228
- reqd_params = S.select(params_path, S.jm(["reqd", true]))
229
- reqd = S.transform(reqd_params, S.jt(["`$EACH`", "", "`$KEY.name`"]))
262
+ point = pick_point(points)
263
+ # Path AND query: a path-only read misses a query-addressed record
264
+ # (e.g. GET /result?trace_id=), which has no path param at all.
265
+ reqd_params = reqd_names(point, "params")
266
+ reqd_query = reqd_names(point, "query")
230
267
 
231
268
  qand = S.jt([])
232
269
  q = S.jm(["`$AND`", qand])
@@ -234,8 +271,7 @@ defmodule ProjectName.Feature.Test do
234
271
  if args != nil do
235
272
  Enum.each(S.keysof(args), fn key ->
236
273
  is_id = key == "id"
237
- selected = S.select(reqd, key)
238
- is_reqd = not S.isempty(selected)
274
+ is_reqd = not S.isempty(S.select(reqd_params, key)) or not S.isempty(S.select(reqd_query, key))
239
275
 
240
276
  if is_id or is_reqd do
241
277
  v = Utility.param(ctx, key)
@@ -1209,7 +1209,8 @@ defmodule ProjectName.Utility do
1209
1209
  out = S.jm([])
1210
1210
 
1211
1211
  Enum.each(H.entries(reqmatch), fn {key, val} ->
1212
- if val != nil and is_binary(key) and not Enum.member?(param_strs, key) do
1212
+ if val != nil and is_binary(key) and key != "$action" and
1213
+ not Enum.member?(param_strs, key) do
1213
1214
  S.setprop(out, key, val)
1214
1215
  end
1215
1216
  end)
@@ -1446,6 +1447,23 @@ defmodule ProjectName.Utility do
1446
1447
 
1447
1448
  # ---- transform_* ---------------------------------------------------------
1448
1449
 
1450
+ # `$action` selects the point (see make_point_impl); it is never an API
1451
+ # field, so the body is a copy without it. The caller's map is left
1452
+ # untouched.
1453
+ defp strip_action(reqdata) do
1454
+ if S.ismap(reqdata) and S.haskey(reqdata, "$action") do
1455
+ body = S.jm([])
1456
+
1457
+ Enum.each(H.entries(reqdata), fn {key, val} ->
1458
+ if key != "$action", do: S.setprop(body, key, val)
1459
+ end)
1460
+
1461
+ body
1462
+ else
1463
+ reqdata
1464
+ end
1465
+ end
1466
+
1449
1467
  def transform_request_impl(ctx) do
1450
1468
  spec = S.getprop(ctx, "spec")
1451
1469
  point = S.getprop(ctx, "point")
@@ -1453,17 +1471,20 @@ defmodule ProjectName.Utility do
1453
1471
 
1454
1472
  transform = H.to_map(S.getprop(point, "transform"))
1455
1473
 
1456
- if transform == nil do
1457
- S.getprop(ctx, "reqdata")
1458
- else
1459
- reqform = S.getprop(transform, "req")
1460
-
1461
- if reqform == nil do
1474
+ reqdata =
1475
+ if transform == nil do
1462
1476
  S.getprop(ctx, "reqdata")
1463
1477
  else
1464
- S.transform(S.jm(["reqdata", S.getprop(ctx, "reqdata")]), reqform)
1478
+ reqform = S.getprop(transform, "req")
1479
+
1480
+ if reqform == nil do
1481
+ S.getprop(ctx, "reqdata")
1482
+ else
1483
+ S.transform(S.jm(["reqdata", S.getprop(ctx, "reqdata")]), reqform)
1484
+ end
1465
1485
  end
1466
- end
1486
+
1487
+ strip_action(reqdata)
1467
1488
  end
1468
1489
 
1469
1490
  def transform_response_impl(ctx) do
@@ -9,18 +9,18 @@ import (
9
9
  )
10
10
 
11
11
  type Context struct {
12
- Id string
13
- Out map[string]any
14
- Ctrl *Control
15
- Meta map[string]any
16
- Client *ProjectNameSDK
17
- Utility *Utility
18
- Op *Operation
19
- Point map[string]any
20
- Config map[string]any
21
- Entopts map[string]any
22
- Options map[string]any
23
- Opmap map[string]*Operation
12
+ Id string
13
+ Out map[string]any
14
+ Ctrl *Control
15
+ Meta map[string]any
16
+ Client *ProjectNameSDK
17
+ Utility *Utility
18
+ Op *Operation
19
+ Point map[string]any
20
+ Config map[string]any
21
+ Entopts map[string]any
22
+ Options map[string]any
23
+ Opmap map[string]*Operation
24
24
  Opmu *sync.Mutex
25
25
  Response *Response
26
26
  Result *Result
@@ -86,7 +86,7 @@ func NewContext(ctxmap map[string]any, basectx *Context) *Context {
86
86
  } else if ctrl, ok := c.(*Control); ok {
87
87
  ctx.Ctrl = ctrl
88
88
  }
89
- } else if basectx != nil && basectx.Ctrl != nil {
89
+ } else if basectx != nil && basectx.Ctrl != nil && getCtxProp(ctxmap, "opname") == nil {
90
90
  ctx.Ctrl = basectx.Ctrl
91
91
  }
92
92
 
@@ -68,7 +68,11 @@ func (f *PagingFeature) PreRequest(ctx *core.Context) {
68
68
  if cursor, has := paging["cursor"]; has && cursor != nil {
69
69
  spec.Query[cursorParam] = cursor
70
70
  } else if spec.Query[pageParam] == nil {
71
- if page, has := paging["page"]; has && page != nil {
71
+ // A record written back by PreResult holds the page just fetched as
72
+ // "page" and the one to fetch as "nextPage", so nextPage wins.
73
+ if next, has := paging["nextPage"]; has && next != nil {
74
+ spec.Query[pageParam] = next
75
+ } else if page, has := paging["page"]; has && page != nil {
72
76
  spec.Query[pageParam] = page
73
77
  } else {
74
78
  spec.Query[pageParam] = foptInt(f.options, "startPage", 1)
@@ -178,17 +182,36 @@ func (f *PagingFeature) PreResult(ctx *core.Context) {
178
182
  }
179
183
  }
180
184
 
181
- // Body-level cursors.
185
+ // Body-level signals; snake_case forms are read first so camelCase wins.
182
186
  if bm, ok := body.(map[string]any); ok {
183
187
  if bm["next"] != nil && paging["next"] == nil {
184
188
  paging["next"] = bm["next"]
185
189
  }
190
+ if bm["next_cursor"] != nil {
191
+ paging["cursor"] = bm["next_cursor"]
192
+ }
186
193
  if bm["cursor"] != nil {
187
194
  paging["cursor"] = bm["cursor"]
188
195
  }
189
196
  if bm["nextCursor"] != nil {
190
197
  paging["cursor"] = bm["nextCursor"]
191
198
  }
199
+ if paging["nextPage"] == nil {
200
+ np := bm["nextPage"]
201
+ if np == nil {
202
+ np = bm["next_page"]
203
+ }
204
+ switch n := np.(type) {
205
+ case float64:
206
+ paging["nextPage"] = int(n)
207
+ case int, string:
208
+ paging["nextPage"] = n
209
+ }
210
+ }
211
+ if hasMore, ok := bm["has_more"].(bool); ok {
212
+ paging["hasMore"] = hasMore
213
+ explicitMore = true
214
+ }
192
215
  if hasMore, ok := bm["hasMore"].(bool); ok {
193
216
  paging["hasMore"] = hasMore
194
217
  explicitMore = true
@@ -207,6 +230,21 @@ func (f *PagingFeature) PreResult(ctx *core.Context) {
207
230
 
208
231
  result.Paging = paging
209
232
  f.Last = paging
233
+
234
+ if ctx.Ctrl != nil {
235
+ // The Context shares the caller's paging map by reference, so refill
236
+ // it in place; a fresh map on Ctrl would never reach the caller.
237
+ if ctx.Ctrl.Paging != nil {
238
+ for k := range ctx.Ctrl.Paging {
239
+ delete(ctx.Ctrl.Paging, k)
240
+ }
241
+ for k, v := range paging {
242
+ ctx.Ctrl.Paging[k] = v
243
+ }
244
+ } else {
245
+ ctx.Ctrl.Paging = paging
246
+ }
247
+ }
210
248
  }
211
249
 
212
250
  func (f *PagingFeature) isList(ctx *core.Context) bool {
@@ -164,24 +164,12 @@ func (f *TestFeature) Init(ctx *core.Context, options map[string]any) {
164
164
  args := self.buildArgs(ctx, op, updateMatch)
165
165
  found := vs.Select(entmap, args)
166
166
  ent := vs.GetElem(found, 0)
167
- if ent == nil && entmap != nil {
168
- for _, e := range entmap {
169
- if _, ok := e.(map[string]any); ok {
170
- ent = e
171
- break
172
- }
173
- }
174
- }
175
167
  if ent == nil {
168
+ // update miss: 404, never another record
176
169
  return respond(404, nil, map[string]any{"statusText": "Not found"}), nil
177
170
  }
178
- if entm, ok := ent.(map[string]any); ok {
179
- reqdata := ctx.Reqdata
180
- if reqdata != nil {
181
- for k, v := range reqdata {
182
- entm[k] = v
183
- }
184
- }
171
+ if _, ok := ent.(map[string]any); ok && ctx.Reqdata != nil {
172
+ vs.Merge([]any{ent, ctx.Reqdata})
185
173
  }
186
174
  vs.DelProp(ent, "$KEY")
187
175
  out := vs.Clone(ent)
@@ -428,6 +428,7 @@ func TestFeatureCorpus(t *testing.T) {
428
428
  "feature": []any{map[string]any{"name": name, "active": true}},
429
429
  })
430
430
  if fcRecord(probe, name) == nil {
431
+ t.Logf("feature.%s: inert (this SDK does not generate the feature)", name)
431
432
  t.Skipf("this SDK was generated without the %s feature", name)
432
433
  }
433
434
 
@@ -5,6 +5,7 @@ import (
5
5
  "os"
6
6
  "reflect"
7
7
  "regexp"
8
+ "strconv"
8
9
  "strings"
9
10
  "testing"
10
11
  "time"
@@ -1042,6 +1043,59 @@ func TestFeaturePaging(t *testing.T) {
1042
1043
  }
1043
1044
  })
1044
1045
 
1046
+ t.Run("snake-case-signals-and-ctrl-write-back", func(t *testing.T) {
1047
+ rec := &fhRecorder{reply: func(n int, _ map[string]any) (any, error) {
1048
+ if n == 1 {
1049
+ return fhResponse(200, map[string]any{"has_more": true, "next_cursor": "c2"}, nil), nil
1050
+ }
1051
+ return fhResponse(200, map[string]any{"has_more": false}, nil), nil
1052
+ }}
1053
+ h := fhMake(rec.fetch, fhF(feat.NewPagingFeature(), nil))
1054
+ pg := map[string]any{}
1055
+ ctrl := map[string]any{"paging": pg}
1056
+ res := h.op(fhOpSpec{op: "list", path: "/w", ctrl: ctrl})
1057
+ if res.result.Paging["hasMore"] != true {
1058
+ t.Errorf("expected has_more read, got %v", res.result.Paging["hasMore"])
1059
+ }
1060
+ if res.result.Paging["cursor"] != "c2" {
1061
+ t.Errorf("expected next_cursor read, got %v", res.result.Paging["cursor"])
1062
+ }
1063
+ if pg["cursor"] != "c2" || pg["hasMore"] != true {
1064
+ t.Errorf("expected record written back into ctrl, got %v", pg)
1065
+ }
1066
+ h.op(fhOpSpec{op: "list", path: "/w", ctrl: ctrl})
1067
+ if !strings.Contains(rec.url(1), "cursor=c2") {
1068
+ t.Errorf("expected written-back cursor sent, got %s", rec.url(1))
1069
+ }
1070
+ if pg["hasMore"] != false || pg["cursor"] != nil {
1071
+ t.Errorf("expected ctrl to carry the last record, got %v", pg)
1072
+ }
1073
+ })
1074
+
1075
+ t.Run("continues-from-written-back-next-page", func(t *testing.T) {
1076
+ rec := &fhRecorder{reply: func(n int, _ map[string]any) (any, error) {
1077
+ body := map[string]any{}
1078
+ if n == 1 {
1079
+ body["next_page"] = 2
1080
+ }
1081
+ return fhResponse(200, body, map[string]any{"x-page": strconv.Itoa(n)}), nil
1082
+ }}
1083
+ h := fhMake(rec.fetch, fhF(feat.NewPagingFeature(), nil))
1084
+ pg := map[string]any{}
1085
+ ctrl := map[string]any{"paging": pg}
1086
+ h.op(fhOpSpec{op: "list", path: "/w", ctrl: ctrl})
1087
+ if pg["page"] != 1 || pg["nextPage"] != 2 || pg["hasMore"] != true {
1088
+ t.Errorf("expected next_page read and written back, got %v", pg)
1089
+ }
1090
+ h.op(fhOpSpec{op: "list", path: "/w", ctrl: ctrl})
1091
+ if !strings.Contains(rec.url(1), "page=2") {
1092
+ t.Errorf("expected written-back next page sent, got %s", rec.url(1))
1093
+ }
1094
+ if pg["hasMore"] != false {
1095
+ t.Errorf("expected no more pages, got %v", pg)
1096
+ }
1097
+ })
1098
+
1045
1099
  t.Run("non-list-not-paged", func(t *testing.T) {
1046
1100
  rec := &fhRecorder{}
1047
1101
  h := fhMake(rec.fetch, fhF(feat.NewPagingFeature(), nil))
@@ -6,12 +6,52 @@ import (
6
6
  "net/http"
7
7
  "net/url"
8
8
  "strings"
9
+ "sync"
9
10
 
10
11
  vs "github.com/voxgig/struct"
11
12
 
12
13
  "GOMODULE/core"
13
14
  )
14
15
 
16
+ // Proxied clients keyed by proxy URL. A client per request would open a
17
+ // fresh connection every call; a cached one pools like http.DefaultClient.
18
+ var proxyClients sync.Map
19
+
20
+ func clientFor(fetchdef map[string]any) *http.Client {
21
+ client := http.DefaultClient
22
+
23
+ if proxy, ok := fetchdef["proxy"].(string); ok && proxy != "" {
24
+ if cached, ok := proxyClients.Load(proxy); ok {
25
+ client = cached.(*http.Client)
26
+ } else if proxyURL, perr := url.Parse(proxy); perr == nil {
27
+ // http.DefaultTransport is a package variable the host program can
28
+ // replace, and an unchecked assertion on it panics the SDK inside
29
+ // whatever called it. Clone the real one where it is there, and
30
+ // build a plain transport where it is not.
31
+ var transport *http.Transport
32
+ if def, ok := http.DefaultTransport.(*http.Transport); ok {
33
+ transport = def.Clone()
34
+ } else {
35
+ transport = &http.Transport{}
36
+ }
37
+ transport.Proxy = http.ProxyURL(proxyURL)
38
+ cached, _ := proxyClients.LoadOrStore(proxy, &http.Client{Transport: transport})
39
+ client = cached.(*http.Client)
40
+ }
41
+ }
42
+
43
+ // A shallow copy shares the pooled Transport; only CheckRedirect differs.
44
+ if redirect, ok := fetchdef["redirect"].(string); ok && redirect == "manual" {
45
+ manual := *client
46
+ manual.CheckRedirect = func(req *http.Request, via []*http.Request) error {
47
+ return http.ErrUseLastResponse
48
+ }
49
+ client = &manual
50
+ }
51
+
52
+ return client
53
+ }
54
+
15
55
  func defaultHTTPFetch(fullurl string, fetchdef map[string]any) (map[string]any, error) {
16
56
  method, _ := fetchdef["method"].(string)
17
57
  if method == "" {
@@ -46,26 +86,7 @@ func defaultHTTPFetch(fullurl string, fetchdef map[string]any) (map[string]any,
46
86
  req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; ProjectNameSDK/1.0)")
47
87
  }
48
88
 
49
- // Honour a proxy annotation on the fetch definition (set by the proxy
50
- // feature): route the request through an http.Transport with Proxy set.
51
- client := http.DefaultClient
52
- if proxy, ok := fetchdef["proxy"].(string); ok && proxy != "" {
53
- if proxyURL, perr := url.Parse(proxy); perr == nil {
54
- client = &http.Client{
55
- Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
56
- }
57
- }
58
- }
59
-
60
- if redirect, ok := fetchdef["redirect"].(string); ok && redirect == "manual" {
61
- manual := *client
62
- manual.CheckRedirect = func(req *http.Request, via []*http.Request) error {
63
- return http.ErrUseLastResponse
64
- }
65
- client = &manual
66
- }
67
-
68
- resp, err := client.Do(req)
89
+ resp, err := clientFor(fetchdef).Do(req)
69
90
  if err != nil {
70
91
  return nil, err
71
92
  }
@@ -29,7 +29,7 @@ func prepareQueryUtil(ctx *core.Context) map[string]any {
29
29
  for _, item := range vs.Items(reqmatch) {
30
30
  key, _ := item[0].(string)
31
31
  val := item[1]
32
- if val != nil && !containsStr(params, key) {
32
+ if val != nil && key != "$action" && !containsStr(params, key) {
33
33
  out[key] = val
34
34
  }
35
35
  }
@@ -16,12 +16,12 @@ func transformRequestUtil(ctx *core.Context) any {
16
16
 
17
17
  transform := core.ToMapAny(vs.GetProp(point, "transform"))
18
18
  if transform == nil {
19
- return ctx.Reqdata
19
+ return stripAction(ctx.Reqdata)
20
20
  }
21
21
 
22
22
  reqform := vs.GetProp(transform, "req")
23
23
  if reqform == nil {
24
- return ctx.Reqdata
24
+ return stripAction(ctx.Reqdata)
25
25
  }
26
26
 
27
27
  reqdata, terr := vs.Transform(map[string]any{
@@ -36,5 +36,24 @@ func transformRequestUtil(ctx *core.Context) any {
36
36
  return terr
37
37
  }
38
38
 
39
- return reqdata
39
+ return stripAction(reqdata)
40
+ }
41
+
42
+ // `$action` selects the point (see makePointUtil); it is never an API field,
43
+ // so the body is a copy without it. The caller's map is left untouched.
44
+ func stripAction(reqdata any) any {
45
+ src, ok := reqdata.(map[string]any)
46
+ if !ok {
47
+ return reqdata
48
+ }
49
+ if _, has := src["$action"]; !has {
50
+ return reqdata
51
+ }
52
+ body := make(map[string]any, len(src))
53
+ for k, v := range src {
54
+ if k != "$action" {
55
+ body[k] = v
56
+ }
57
+ }
58
+ return body
40
59
  }
@@ -82,7 +82,8 @@ public class Context {
82
82
  this.ctrl = (Control) cv;
83
83
  }
84
84
  }
85
- else if (basectx != null && basectx.ctrl != null) {
85
+ else if (basectx != null && basectx.ctrl != null
86
+ && Helpers.getCtxProp(ctxmap, "opname") == null) {
86
87
  this.ctrl = basectx.ctrl;
87
88
  }
88
89
 
@@ -18,8 +18,8 @@ import JAVAPACKAGE.utility.struct.Struct;
18
18
  // stamps page/limit (or a cursor) into the request query; on the way back
19
19
  // (PreResult) it reads the server's pagination signals — a `Link:
20
20
  // rel="next"` header, `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
21
- // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body — and records
22
- // them on `ctx.result.paging`. A per-call cursor/page from ctrl takes
21
+ // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case
22
+ // forms too) — and records them on `ctx.result.paging` and `ctrl.paging`. A per-call cursor/page from ctrl takes
23
23
  // priority (used by auto-iteration). Parameter names (`pageParam`,
24
24
  // `limitParam`, `cursorParam`), the page size (`limit`) and the start page
25
25
  // (`startPage`, default 1) are configurable.
@@ -82,7 +82,12 @@ public class PagingFeature extends BaseFeature {
82
82
  spec.query.put(cursorParam, cursor);
83
83
  }
84
84
  else if (spec.query.get(pageParam) == null) {
85
- Object page = paging.get("page");
85
+ // A record written back by preResult holds the page just fetched as
86
+ // "page" and the one to fetch as "nextPage", so nextPage wins.
87
+ Object page = paging.get("nextPage");
88
+ if (page == null) {
89
+ page = paging.get("page");
90
+ }
86
91
  if (page != null) {
87
92
  spec.query.put(pageParam, page);
88
93
  }
@@ -206,18 +211,37 @@ public class PagingFeature extends BaseFeature {
206
211
  }
207
212
  }
208
213
 
209
- // Body-level cursors.
214
+ // Body-level signals; snake_case forms are read first so camelCase wins.
210
215
  if (body instanceof Map) {
211
216
  Map<String, Object> bm = (Map<String, Object>) body;
212
217
  if (bm.get("next") != null && paging.get("next") == null) {
213
218
  paging.put("next", bm.get("next"));
214
219
  }
220
+ if (bm.get("next_cursor") != null) {
221
+ paging.put("cursor", bm.get("next_cursor"));
222
+ }
215
223
  if (bm.get("cursor") != null) {
216
224
  paging.put("cursor", bm.get("cursor"));
217
225
  }
218
226
  if (bm.get("nextCursor") != null) {
219
227
  paging.put("cursor", bm.get("nextCursor"));
220
228
  }
229
+ if (paging.get("nextPage") == null) {
230
+ Object np = bm.get("nextPage");
231
+ if (np == null) {
232
+ np = bm.get("next_page");
233
+ }
234
+ if (np instanceof Number) {
235
+ paging.put("nextPage", ((Number) np).intValue());
236
+ }
237
+ else if (np instanceof String) {
238
+ paging.put("nextPage", np);
239
+ }
240
+ }
241
+ if (bm.get("has_more") instanceof Boolean) {
242
+ paging.put("hasMore", bm.get("has_more"));
243
+ explicitMore = true;
244
+ }
221
245
  if (bm.get("hasMore") instanceof Boolean) {
222
246
  paging.put("hasMore", bm.get("hasMore"));
223
247
  explicitMore = true;
@@ -237,6 +261,24 @@ public class PagingFeature extends BaseFeature {
237
261
 
238
262
  result.paging = paging;
239
263
  this.last = paging;
264
+
265
+ if (ctx.ctrl != null) {
266
+ // The Context shares the caller's paging map by reference, so refill
267
+ // it in place; an immutable map falls back to replacing the reference.
268
+ Map<String, Object> shared = ctx.ctrl.paging;
269
+ if (shared == null) {
270
+ ctx.ctrl.paging = paging;
271
+ }
272
+ else {
273
+ try {
274
+ shared.clear();
275
+ shared.putAll(paging);
276
+ }
277
+ catch (UnsupportedOperationException e) {
278
+ ctx.ctrl.paging = paging;
279
+ }
280
+ }
281
+ }
240
282
  }
241
283
 
242
284
  private boolean isList(Context ctx) {