@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
@@ -68,16 +68,27 @@ private:
68
68
  Value restf = getp(tm, "res");
69
69
  if (!restf.is_string()) return data;
70
70
  std::string spec = restf.as_string();
71
- // Exactly `body.<key>`; a deeper path is not an envelope this mock can
72
- // synthesise, so it is left alone rather than guessed at.
71
+ // Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
72
+ // GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
73
73
  if (spec.size() < 8) return data;
74
74
  if (0 != spec.compare(0, 6, "`body.")) return data;
75
75
  if ('`' != spec[spec.size() - 1]) return data;
76
76
  std::string inner = spec.substr(6, spec.size() - 7);
77
- if (inner.empty() || std::string::npos != inner.find('.')) return data;
78
- Value wrapped = vmap();
79
- map_put(wrapped, inner, data);
80
- return wrapped;
77
+ if (inner.empty()) return data;
78
+ std::vector<std::string> segs;
79
+ for (size_t at = 0;;) {
80
+ size_t dot = inner.find('.', at);
81
+ if (std::string::npos == dot) { segs.push_back(inner.substr(at)); break; }
82
+ segs.push_back(inner.substr(at, dot - at));
83
+ at = dot + 1;
84
+ }
85
+ Value out = data;
86
+ for (size_t i = segs.size(); i > 0; i--) {
87
+ Value wrapped = vmap();
88
+ map_put(wrapped, segs[i - 1], out);
89
+ out = wrapped;
90
+ }
91
+ return out;
81
92
  }
82
93
 
83
94
  Value respond(CtxPtr ctx, int status, const Value& data, const Value& extra) {
@@ -159,14 +170,10 @@ private:
159
170
  Value args = buildArgs(ctx, op, updateMatch);
160
171
  std::vector<Value> found = Struct::select(entmap, args);
161
172
  Value ent = found.empty() ? Value::undef() : found[0];
162
- if (is_nullish(ent) && entmap.is_map()) {
163
- for (const auto& kv : *entmap.as_map()) {
164
- if (kv.second.is_map()) { ent = kv.second; break; }
165
- }
166
- }
173
+ // update miss: 404, never another record
167
174
  if (is_nullish(ent)) return respond(ctx, 404, Value(nullptr), extra1("statusText", Value("Not found")));
168
175
  if (ent.is_map() && ctx->reqdata.is_map()) {
169
- for (const auto& kv : *ctx->reqdata.as_map()) map_put(ent, kv.first, kv.second);
176
+ Struct::merge(vlist({ent, ctx->reqdata}));
170
177
  }
171
178
  Struct::delprop(ent, Value("$KEY"));
172
179
  Value out = Struct::clone(ent);
@@ -261,19 +268,51 @@ private:
261
268
  fopt::foptSleep(net)(ms);
262
269
  }
263
270
 
271
+ static bool pointTerminal(const Value& p) {
272
+ Value parts = getp(p, "parts");
273
+ if (!parts.is_list() || parts.as_list()->empty()) return false;
274
+ const Value& last = parts.as_list()->back();
275
+ return last.is_string() && 0 == last.as_string().rfind("{", 0);
276
+ }
277
+
278
+ static size_t pointDepth(const Value& p) {
279
+ Value parts = getp(p, "parts");
280
+ return parts.is_list() ? parts.as_list()->size() : 0;
281
+ }
282
+
283
+ // The entity's own endpoint: a terminal `{param}` marks a record route, and
284
+ // among equals the shallower path wins (the same rule as makePoint).
285
+ static Value pickPoint(const Value& points) {
286
+ if (!points.is_list() || points.as_list()->empty()) return Value::undef();
287
+ Value point = (*points.as_list())[0];
288
+ for (const Value& cand : *points.as_list()) {
289
+ if (pointTerminal(cand) != pointTerminal(point)) {
290
+ if (pointTerminal(cand)) point = cand;
291
+ } else if (pointDepth(cand) < pointDepth(point)) {
292
+ point = cand;
293
+ }
294
+ }
295
+ return point;
296
+ }
297
+
264
298
  Value buildArgs(CtxPtr ctx, OperationPtr op, const Value& args) {
265
299
  std::string opname = op->name;
266
300
 
267
301
  Value points = Struct::getpath(ctx->config,
268
302
  {"entity", ctx->entity == nullptr ? std::string("") : ctx->entity->getName(),
269
303
  "op", opname, "points"});
270
- Value point = Struct::getelem(points, -1);
271
-
272
- Value paramsPath = Struct::getpath(point, {"args", "params"});
273
- std::vector<Value> reqdParamsSel = Struct::select(paramsPath, vmap({{"reqd", Value(true)}}));
274
- Value reqdParams = vlist();
275
- for (auto& p : reqdParamsSel) reqdParams.as_list()->push_back(p);
276
- Value reqd = Struct::transform(reqdParams, vlist({Value("`$EACH`"), Value(""), Value("`$KEY.name`")}));
304
+ Value point = pickPoint(points);
305
+
306
+ // Path AND query: a path-only read misses a query-addressed record
307
+ // (e.g. GET /result?trace_id=), which has no path param at all.
308
+ Value reqdArgs = vlist();
309
+ for (const char* kind : {"params", "query"}) {
310
+ Value argsPath = Struct::getpath(point, {"args", kind});
311
+ for (auto& p : Struct::select(argsPath, vmap({{"reqd", Value(true)}}))) {
312
+ reqdArgs.as_list()->push_back(p);
313
+ }
314
+ }
315
+ Value reqd = Struct::transform(reqdArgs, vlist({Value("`$EACH`"), Value(""), Value("`$KEY.name`")}));
277
316
 
278
317
  Value qand = vlist();
279
318
  Value q = vmap({{"`$AND`", qand}});
@@ -1026,7 +1026,7 @@ inline Value prepareQuery(CtxPtr ctx) {
1026
1026
  for (const auto& item : Struct::items(reqmatch)) {
1027
1027
  std::string key = as_str(pair_key(item));
1028
1028
  Value val = pair_val(item);
1029
- if (!is_nullish(val) && !contains_str(params, key)) {
1029
+ if (!is_nullish(val) && "$action" != key && !contains_str(params, key)) {
1030
1030
  map_put(out, key, val);
1031
1031
  }
1032
1032
  }
@@ -1050,18 +1050,30 @@ inline std::string preparePath(CtxPtr ctx) {
1050
1050
 
1051
1051
  // ---- transformRequest -------------------------------------------------
1052
1052
 
1053
+ // `$action` selects the point (see makePoint); it is never an API field, so
1054
+ // the body is a copy without it. The caller's map is left untouched.
1055
+ inline Value stripAction(const Value& reqdata) {
1056
+ if (!map_contains(reqdata, "$action")) return reqdata;
1057
+ Value body = vmap();
1058
+ for (const auto& item : Struct::items(reqdata)) {
1059
+ std::string key = as_str(pair_key(item));
1060
+ if ("$action" != key) map_put(body, key, pair_val(item));
1061
+ }
1062
+ return body;
1063
+ }
1064
+
1053
1065
  inline Value transformRequest(CtxPtr ctx) {
1054
1066
  if (ctx->spec) ctx->spec->step = "reqform";
1055
1067
 
1056
1068
  Value transform = Helpers::toMapAny(getp(ctx->point, "transform"));
1057
- if (!transform.is_map()) return ctx->reqdata;
1069
+ if (!transform.is_map()) return stripAction(ctx->reqdata);
1058
1070
 
1059
1071
  Value reqform = getp(transform, "req");
1060
- if (is_nullish(reqform)) return ctx->reqdata;
1072
+ if (is_nullish(reqform)) return stripAction(ctx->reqdata);
1061
1073
 
1062
1074
  Value data = vmap();
1063
1075
  map_put(data, "reqdata", ctx->reqdata);
1064
- return Struct::transform(data, reqform);
1076
+ return stripAction(Struct::transform(data, reqform));
1065
1077
  }
1066
1078
 
1067
1079
  // ---- makeOptions ------------------------------------------------------
@@ -78,7 +78,7 @@ public class Context
78
78
  {
79
79
  Ctrl = ctrl;
80
80
  }
81
- else if (basectx?.Ctrl != null)
81
+ else if (basectx?.Ctrl != null && Helpers.GetCtxProp(ctxmap, "opname") == null)
82
82
  {
83
83
  Ctrl = basectx.Ctrl;
84
84
  }
@@ -2,8 +2,8 @@
2
2
  // stamps page/limit (or a cursor) into the request query; on the way back
3
3
  // (PreResult) it reads the server's pagination signals - a `Link:
4
4
  // rel="next"` header, `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
5
- // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body - and records
6
- // them on `ctx.Result.Paging`. A per-call cursor/page from ctrl takes
5
+ // `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case
6
+ // forms too) - and records them on `ctx.Result.Paging` and `Ctrl.Paging`. A per-call cursor/page from ctrl takes
7
7
  // priority (used by auto-iteration). Parameter names (`pageParam`,
8
8
  // `limitParam`, `cursorParam`), the page size (`limit`) and the start page
9
9
  // (`startPage`, default 1) are configurable.
@@ -79,8 +79,12 @@ public class PagingFeature : BaseFeature
79
79
  }
80
80
  else if (!spec.Query.TryGetValue(pageParam, out var existing) || existing == null)
81
81
  {
82
+ // A record written back by PreResult holds the page just fetched
83
+ // as "page" and the one to fetch as "nextPage", so nextPage wins.
82
84
  object? page = null;
83
- var hasPage = paging != null && paging.TryGetValue("page", out page) && page != null;
85
+ var hasPage = paging != null &&
86
+ ((paging.TryGetValue("nextPage", out page) && page != null) ||
87
+ (paging.TryGetValue("page", out page) && page != null));
84
88
  spec.Query[pageParam] = hasPage ? page : FoptInt(_options, "startPage", 1);
85
89
  }
86
90
 
@@ -224,7 +228,7 @@ public class PagingFeature : BaseFeature
224
228
  }
225
229
  }
226
230
 
227
- // Body-level cursors.
231
+ // Body-level signals; snake_case forms are read first so camelCase wins.
228
232
  if (body is Dictionary<string, object?> bm)
229
233
  {
230
234
  if (bm.TryGetValue("next", out var next) && next != null &&
@@ -232,6 +236,10 @@ public class PagingFeature : BaseFeature
232
236
  {
233
237
  paging["next"] = next;
234
238
  }
239
+ if (bm.TryGetValue("next_cursor", out var snakeCursor) && snakeCursor != null)
240
+ {
241
+ paging["cursor"] = snakeCursor;
242
+ }
235
243
  if (bm.TryGetValue("cursor", out var cursor) && cursor != null)
236
244
  {
237
245
  paging["cursor"] = cursor;
@@ -240,6 +248,34 @@ public class PagingFeature : BaseFeature
240
248
  {
241
249
  paging["cursor"] = nextCursor;
242
250
  }
251
+ if (!paging.TryGetValue("nextPage", out var np0) || np0 == null)
252
+ {
253
+ bm.TryGetValue("nextPage", out var np);
254
+ if (np == null)
255
+ {
256
+ bm.TryGetValue("next_page", out np);
257
+ }
258
+ switch (np)
259
+ {
260
+ case int n:
261
+ paging["nextPage"] = n;
262
+ break;
263
+ case long n:
264
+ paging["nextPage"] = (int)n;
265
+ break;
266
+ case double n:
267
+ paging["nextPage"] = (int)n;
268
+ break;
269
+ case string s:
270
+ paging["nextPage"] = s;
271
+ break;
272
+ }
273
+ }
274
+ if (bm.TryGetValue("has_more", out var snakeMore) && snakeMore is bool smb)
275
+ {
276
+ paging["hasMore"] = smb;
277
+ explicitMore = true;
278
+ }
243
279
  if (bm.TryGetValue("hasMore", out var hasMore) && hasMore is bool hmb)
244
280
  {
245
281
  paging["hasMore"] = hmb;
@@ -262,6 +298,24 @@ public class PagingFeature : BaseFeature
262
298
 
263
299
  result.Paging = paging;
264
300
  Last = paging;
301
+
302
+ if (ctx.Ctrl != null)
303
+ {
304
+ // The Context shares the caller's paging map by reference, so
305
+ // refill it in place; a fresh map on Ctrl never reaches the caller.
306
+ if (ctx.Ctrl.Paging != null)
307
+ {
308
+ ctx.Ctrl.Paging.Clear();
309
+ foreach (var kv in paging)
310
+ {
311
+ ctx.Ctrl.Paging[kv.Key] = kv.Value;
312
+ }
313
+ }
314
+ else
315
+ {
316
+ ctx.Ctrl.Paging = paging;
317
+ }
318
+ }
265
319
  }
266
320
 
267
321
  private bool IsList(Context ctx)
@@ -59,15 +59,21 @@ public class TestFeature : BaseFeature
59
59
  if (data == null || ctx2.Point == null) { return data; }
60
60
  var tm = StructUtils.GetProp(ctx2.Point, "transform");
61
61
  if (StructUtils.GetProp(tm, "res") is not string spec) { return data; }
62
- // Exactly `body.<key>`; a deeper path is not an envelope this
63
- // mock can synthesise, so it is left alone.
62
+ // Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
63
+ // GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
64
64
  if (!spec.StartsWith("`body.") || !spec.EndsWith("`") || spec.Length < 8)
65
65
  {
66
66
  return data;
67
67
  }
68
68
  var inner = spec.Substring(6, spec.Length - 7);
69
- if (inner.Length == 0 || inner.Contains('.')) { return data; }
70
- return new Dictionary<string, object?> { [inner] = data };
69
+ if (inner.Length == 0) { return data; }
70
+ var segs = inner.Split('.');
71
+ object? built = data;
72
+ for (var i = segs.Length - 1; 0 <= i; i--)
73
+ {
74
+ built = new Dictionary<string, object?> { [segs[i]] = built };
75
+ }
76
+ return built;
71
77
  }
72
78
 
73
79
  Dictionary<string, object?> Respond(int status, object? data,
@@ -182,30 +188,17 @@ public class TestFeature : BaseFeature
182
188
  var args = BuildArgs(ctx2, op, updateMatch);
183
189
  var found = StructUtils.Select(entmap, args);
184
190
  var ent = StructUtils.GetElem(found, 0);
185
- if (ent == null && entmap != null)
186
- {
187
- foreach (var e in entmap.Values)
188
- {
189
- if (e is Dictionary<string, object?>)
190
- {
191
- ent = e;
192
- break;
193
- }
194
- }
195
- }
196
191
  if (ent == null)
197
192
  {
193
+ // update miss: 404, never another record
198
194
  return Respond(404, null, new Dictionary<string, object?>
199
195
  {
200
196
  ["statusText"] = "Not found",
201
197
  });
202
198
  }
203
- if (ent is Dictionary<string, object?> entm && ctx2.Reqdata != null)
199
+ if (ent is Dictionary<string, object?> && ctx2.Reqdata != null)
204
200
  {
205
- foreach (var kv in ctx2.Reqdata)
206
- {
207
- entm[kv.Key] = kv.Value;
208
- }
201
+ StructUtils.Merge(new List<object?> { ent, ctx2.Reqdata });
209
202
  }
210
203
  StructUtils.DelProp(ent, "$KEY");
211
204
  var outval = StructUtils.Clone(ent);
@@ -378,11 +371,16 @@ public class TestFeature : BaseFeature
378
371
  }
379
372
  }
380
373
 
381
- // Get required params.
382
- var paramsPath = StructUtils.GetPath(point, StructUtils.Jt("args", "params"));
383
- var reqdParams = StructUtils.Select(paramsPath,
384
- new Dictionary<string, object?> { ["reqd"] = true });
385
- var reqd = StructUtils.Transform(reqdParams,
374
+ // Path AND query: a path-only read misses a query-addressed record
375
+ // (e.g. GET /result?trace_id=), which has no path param at all.
376
+ var reqdArgs = new List<object?>();
377
+ foreach (var kind in new[] { "params", "query" })
378
+ {
379
+ var argsPath = StructUtils.GetPath(point, StructUtils.Jt("args", kind));
380
+ reqdArgs.AddRange(StructUtils.Select(argsPath,
381
+ new Dictionary<string, object?> { ["reqd"] = true }));
382
+ }
383
+ var reqd = StructUtils.Transform(reqdArgs,
386
384
  StructUtils.Jt("`$EACH`", "", "`$KEY.name`"));
387
385
 
388
386
  var qand = new List<object?>();
@@ -11,7 +11,19 @@ namespace ProjectNameSdk.Util;
11
11
 
12
12
  public static partial class SdkUtility
13
13
  {
14
- private static readonly HttpClient DefaultHttpClient = new();
14
+ // Cookies OFF on every handler. The clients are process-wide, so a
15
+ // CookieContainer would send one call's Set-Cookie on the next, under a
16
+ // different credential — and .NET ADDS container cookies to a request
17
+ // that already carries a Cookie header, which an `apiKey in: cookie`
18
+ // scheme does. Pooling is the handler's own and is unaffected.
19
+ private static HttpClientHandler CookielessHandler(bool allowRedirect) =>
20
+ new HttpClientHandler
21
+ {
22
+ AllowAutoRedirect = allowRedirect,
23
+ UseCookies = false,
24
+ };
25
+
26
+ private static readonly HttpClient DefaultHttpClient = new(CookielessHandler(true));
15
27
 
16
28
  // Non-following twin of DefaultHttpClient. The station feature's
17
29
  // middleware sets `redirect: manual` on the fetch definition under a
@@ -20,11 +32,8 @@ public static partial class SdkUtility
20
32
  // to a Location no policy approved (the ts donor's fetch honours the
21
33
  // same key natively; redirect policy is per-handler in .NET, hence a
22
34
  // second client).
23
- private static readonly HttpClient ManualRedirectHttpClient = new(
24
- new HttpClientHandler
25
- {
26
- AllowAutoRedirect = false,
27
- });
35
+ private static readonly HttpClient ManualRedirectHttpClient =
36
+ new(CookielessHandler(false));
28
37
 
29
38
  // Proxy-routed clients, cached per proxy URL and redirect policy (see
30
39
  // the proxy feature's fetchdef annotation).
@@ -43,12 +52,10 @@ public static partial class SdkUtility
43
52
  var key = (manual ? "manual|" : "auto|") + proxy;
44
53
  if (!ProxyClients.TryGetValue(key, out var client))
45
54
  {
46
- client = new HttpClient(new HttpClientHandler
47
- {
48
- Proxy = new System.Net.WebProxy(proxy),
49
- UseProxy = true,
50
- AllowAutoRedirect = !manual,
51
- });
55
+ var handler = CookielessHandler(!manual);
56
+ handler.Proxy = new System.Net.WebProxy(proxy);
57
+ handler.UseProxy = true;
58
+ client = new HttpClient(handler);
52
59
  ProxyClients[key] = client;
53
60
  }
54
61
  return client;
@@ -24,7 +24,7 @@ public static partial class SdkUtility
24
24
  {
25
25
  var key = item[0] as string ?? "";
26
26
  var val = item[1];
27
- if (val != null && !ContainsStr(paramnames, key))
27
+ if (val != null && "$action" != key && !ContainsStr(paramnames, key))
28
28
  {
29
29
  query[key] = val;
30
30
  }
@@ -20,13 +20,13 @@ public static partial class SdkUtility
20
20
  var transform = Helpers.ToMapAny(StructUtils.GetProp(point, "transform"));
21
21
  if (transform == null)
22
22
  {
23
- return ctx.Reqdata;
23
+ return StripAction(ctx.Reqdata);
24
24
  }
25
25
 
26
26
  var reqform = StructUtils.GetProp(transform, "req");
27
27
  if (reqform == null)
28
28
  {
29
- return ctx.Reqdata;
29
+ return StripAction(ctx.Reqdata);
30
30
  }
31
31
 
32
32
  var reqdata = StructUtils.Transform(new Dictionary<string, object?>
@@ -34,6 +34,26 @@ public static partial class SdkUtility
34
34
  ["reqdata"] = ctx.Reqdata,
35
35
  }, reqform);
36
36
 
37
- return reqdata;
37
+ return StripAction(reqdata);
38
+ }
39
+
40
+ // `$action` selects the point (see MakePointUtil); it is never an API
41
+ // field, so the body is a copy without it. The caller's map is left
42
+ // untouched.
43
+ private static object? StripAction(object? reqdata)
44
+ {
45
+ if (reqdata is not IDictionary<string, object?> src || !src.ContainsKey("$action"))
46
+ {
47
+ return reqdata;
48
+ }
49
+ var body = new Dictionary<string, object?>();
50
+ foreach (var kv in src)
51
+ {
52
+ if ("$action" != kv.Key)
53
+ {
54
+ body[kv.Key] = kv.Value;
55
+ }
56
+ }
57
+ return body;
38
58
  }
39
59
  }
@@ -57,7 +57,7 @@ defmodule ProjectName.Context do
57
57
  if S.ismap(pg), do: S.setprop(ctrl, "paging", pg)
58
58
  S.setprop(ctx, "ctrl", ctrl)
59
59
 
60
- basectx != nil and bp.("ctrl") != nil ->
60
+ basectx != nil and bp.("ctrl") != nil and gp.("opname") == nil ->
61
61
  S.setprop(ctx, "ctrl", bp.("ctrl"))
62
62
 
63
63
  true ->
@@ -4,8 +4,8 @@
4
4
  # stamps page/limit (or a cursor) into the request query; on the way back
5
5
  # (PreResult) it reads the server's pagination signals — a `Link: rel="next"`
6
6
  # header, `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
7
- # `next`/`cursor`/`nextCursor`/`hasMore` fields in the body — and records them
8
- # on `ctx.result.paging`. A per-call cursor/page supplied via ctrl paging
7
+ # `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case forms
8
+ # too) — and records them on `ctx.result.paging` and the caller's ctrl paging. A per-call cursor/page supplied via ctrl paging
9
9
  # takes priority (used by auto-iteration). Parameter names
10
10
  # (`pageParam`/`limitParam`/`cursorParam`), `startPage` and page size
11
11
  # (`limit`) are configurable.
@@ -67,7 +67,10 @@ defmodule ProjectName.Feature.Paging do
67
67
  S.setprop(query, cursor_param, S.getprop(paging, "cursor"))
68
68
 
69
69
  S.getprop(query, page_param) == nil ->
70
- page = S.getprop(paging, "page")
70
+ # A record written back by pre_result holds the page just fetched
71
+ # as "page" and the one to fetch as "nextPage", so nextPage wins.
72
+ page = S.getprop(paging, "nextPage")
73
+ page = if page == nil, do: S.getprop(paging, "page"), else: page
71
74
  page = if page == nil, do: por(S.getprop(opts, "startPage"), 1), else: page
72
75
  S.setprop(query, page_param, page)
73
76
 
@@ -182,18 +185,16 @@ defmodule ProjectName.Feature.Paging do
182
185
  bnext -> por(next_from_link, bnext)
183
186
  end
184
187
 
188
+ # snake_case forms rank below the camelCase ones.
185
189
  c =
186
190
  cond do
187
191
  S.getprop(body, "nextCursor") != nil -> S.getprop(body, "nextCursor")
188
192
  S.getprop(body, "cursor") != nil -> S.getprop(body, "cursor")
193
+ S.getprop(body, "next_cursor") != nil -> S.getprop(body, "next_cursor")
189
194
  true -> nil
190
195
  end
191
196
 
192
- hm =
193
- case S.getprop(body, "hasMore") do
194
- v when is_boolean(v) -> v
195
- _ -> false
196
- end
197
+ {hm, _} = body_more(body)
197
198
 
198
199
  {n, c, hm}
199
200
  else
@@ -239,10 +240,19 @@ defmodule ProjectName.Feature.Paging do
239
240
  # No usable relay `more` path, but a top-level body hasMore is
240
241
  # still an outright statement — keep it explicit, or cursor
241
242
  # inference below would flip an explicit false to true.
242
- {c, has_more, is_boolean(S.getprop(body, "hasMore"))}
243
+ {c, has_more, elem(body_more(body), 1)}
243
244
  end
244
245
  else
245
- {cursor_val, has_more, is_boolean(S.getprop(body, "hasMore"))}
246
+ {cursor_val, has_more, elem(body_more(body), 1)}
247
+ end
248
+
249
+ next_page =
250
+ if next_page == nil and S.ismap(body) do
251
+ np = S.getprop(body, "nextPage")
252
+ np = if np == nil, do: S.getprop(body, "next_page"), else: np
253
+ if is_number(np) or is_binary(np), do: np, else: nil
254
+ else
255
+ next_page
246
256
  end
247
257
 
248
258
  # Cursor presence only INFERS another page. When the server stated the
@@ -268,6 +278,7 @@ defmodule ProjectName.Feature.Paging do
268
278
  ])
269
279
 
270
280
  S.setprop(result, "paging", paging)
281
+ write_back(S.getprop(ctx, "ctrl"), paging)
271
282
  S.setprop(S.getprop(f, "client"), "_paging", S.jm(["last", paging]))
272
283
  end
273
284
  end
@@ -275,6 +286,37 @@ defmodule ProjectName.Feature.Paging do
275
286
  nil
276
287
  end
277
288
 
289
+ # The Context shares the caller's paging map by reference, so refill it in
290
+ # place; a fresh map on ctrl never reaches the caller.
291
+ defp write_back(ctrl, paging) do
292
+ shared = if ctrl == nil, do: nil, else: S.getprop(ctrl, "paging")
293
+
294
+ cond do
295
+ ctrl == nil ->
296
+ nil
297
+
298
+ S.ismap(shared) ->
299
+ Enum.each(S.keysof(shared), fn k -> S.delprop(shared, k) end)
300
+ Enum.each(S.keysof(paging), fn k -> S.setprop(shared, k, S.getprop(paging, k)) end)
301
+
302
+ true ->
303
+ S.setprop(ctrl, "paging", paging)
304
+ end
305
+
306
+ nil
307
+ end
308
+
309
+ # Body `hasMore`, or `has_more` when the camelCase form is absent: {value,
310
+ # stated outright}.
311
+ defp body_more(body) do
312
+ cond do
313
+ not S.ismap(body) -> {false, false}
314
+ is_boolean(S.getprop(body, "hasMore")) -> {S.getprop(body, "hasMore"), true}
315
+ is_boolean(S.getprop(body, "has_more")) -> {S.getprop(body, "has_more"), true}
316
+ true -> {false, false}
317
+ end
318
+ end
319
+
278
320
  defp is_list_op(f, ctx) do
279
321
  ops = opt_list(S.getprop(F.opts(f), "ops"), ["list"])
280
322
  op = S.getprop(ctx, "op")