@voxgig/sdkgen 1.5.1 → 2.0.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 (270) hide show
  1. package/dist/cmp/AgentGuideContent.js +5 -0
  2. package/dist/cmp/AgentGuideContent.js.map +1 -1
  3. package/dist/cmp/Feature.js +13 -0
  4. package/dist/cmp/Feature.js.map +1 -1
  5. package/dist/helpers/canonType.d.ts +3 -1
  6. package/dist/helpers/canonType.js +44 -1
  7. package/dist/helpers/canonType.js.map +1 -1
  8. package/dist/helpers/packageMeta.js +7 -0
  9. package/dist/helpers/packageMeta.js.map +1 -1
  10. package/dist/sdkgen.d.ts +3 -3
  11. package/dist/sdkgen.js +4 -1
  12. package/dist/sdkgen.js.map +1 -1
  13. package/dist/tsconfig.tsbuildinfo +1 -1
  14. package/package.json +3 -3
  15. package/project/.sdk/model/feature/paging.aontu +7 -0
  16. package/project/.sdk/model/target/py-data.aontu +64 -0
  17. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +89 -1
  18. package/project/.sdk/src/cmp/clojure/Main_clojure.ts +1 -0
  19. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +97 -0
  20. package/project/.sdk/src/cmp/dart/fragment/Main.fragment.dart +78 -0
  21. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +84 -0
  22. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +87 -0
  23. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +75 -0
  24. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +85 -0
  25. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +4 -0
  26. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +80 -0
  27. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +86 -0
  28. package/project/.sdk/src/cmp/py/Entity_py.ts +9 -2
  29. package/project/.sdk/src/cmp/py/MainEntity_py.ts +1 -1
  30. package/project/.sdk/src/cmp/py/Main_py.ts +34 -6
  31. package/project/.sdk/src/cmp/py/Package_py.ts +6 -9
  32. package/project/.sdk/src/cmp/py/TestDirect_py.ts +2 -2
  33. package/project/.sdk/src/cmp/py/TestEntity_py.ts +3 -3
  34. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +2 -2
  35. package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +2 -2
  36. package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +2 -2
  37. package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +2 -2
  38. package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +2 -2
  39. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +75 -8
  40. package/project/.sdk/src/cmp/py-data/Main_py-data.ts +987 -0
  41. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +71 -0
  42. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +95 -0
  43. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +86 -0
  44. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +75 -0
  45. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +95 -0
  46. package/project/.sdk/tm/c/core/sdk.h +7 -0
  47. package/project/.sdk/tm/c/feature/paging.c +141 -2
  48. package/project/.sdk/tm/c/utility/graphql.c +178 -0
  49. package/project/.sdk/tm/c/utility/make_options.c +1 -1
  50. package/project/.sdk/tm/c/utility/make_response.c +6 -0
  51. package/project/.sdk/tm/c/utility/make_spec.c +23 -3
  52. package/project/.sdk/tm/clojure/src/sdk/client.clj +64 -1
  53. package/project/.sdk/tm/clojure/src/sdk/core.clj +126 -3
  54. package/project/.sdk/tm/clojure/src/sdk/features.clj +80 -14
  55. package/project/.sdk/tm/cpp/core/types.hpp +83 -0
  56. package/project/.sdk/tm/cpp/feature/paging.hpp +103 -1
  57. package/project/.sdk/tm/cpp/utility/pipeline.hpp +152 -3
  58. package/project/.sdk/tm/csharp/core/Utility.cs +4 -0
  59. package/project/.sdk/tm/csharp/feature/PagingFeature.cs +118 -1
  60. package/project/.sdk/tm/csharp/utility/Graphql.cs +190 -0
  61. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +1 -1
  62. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +7 -0
  63. package/project/.sdk/tm/csharp/utility/MakeSpec.cs +21 -2
  64. package/project/.sdk/tm/csharp/utility/Register.cs +2 -0
  65. package/project/.sdk/tm/dart/lib/Point.dart +7 -0
  66. package/project/.sdk/tm/dart/lib/feature/paging/PagingFeature.dart +99 -4
  67. package/project/.sdk/tm/dart/lib/utility/GraphqlUtility.dart +162 -0
  68. package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +1 -1
  69. package/project/.sdk/tm/dart/lib/utility/MakeResponseUtility.dart +5 -0
  70. package/project/.sdk/tm/dart/lib/utility/MakeSpecUtility.dart +18 -2
  71. package/project/.sdk/tm/dart/lib/utility/PrepareMethodUtility.dart +6 -1
  72. package/project/.sdk/tm/dart/lib/utility/Utility.dart +9 -0
  73. package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +136 -13
  74. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +187 -3
  75. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  76. package/project/.sdk/tm/go/feature/paging_feature.go +87 -1
  77. package/project/.sdk/tm/go/utility/graphql.go +168 -0
  78. package/project/.sdk/tm/go/utility/make_options.go +1 -1
  79. package/project/.sdk/tm/go/utility/make_response.go +6 -0
  80. package/project/.sdk/tm/go/utility/make_spec.go +19 -2
  81. package/project/.sdk/tm/go/utility/register.go +2 -0
  82. package/project/.sdk/tm/haskell/src/SdkFeatures.hs +146 -7
  83. package/project/.sdk/tm/haskell/src/SdkRuntime.hs +153 -3
  84. package/project/.sdk/tm/java/core/SdkClient.java +93 -0
  85. package/project/.sdk/tm/java/core/Utility.java +4 -0
  86. package/project/.sdk/tm/java/feature/PagingFeature.java +100 -1
  87. package/project/.sdk/tm/java/utility/Graphql.java +191 -0
  88. package/project/.sdk/tm/java/utility/MakeOptions.java +1 -1
  89. package/project/.sdk/tm/java/utility/MakeResponse.java +6 -0
  90. package/project/.sdk/tm/java/utility/MakeSpec.java +17 -2
  91. package/project/.sdk/tm/java/utility/Register.java +2 -0
  92. package/project/.sdk/tm/js/src/Point.js +5 -0
  93. package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +82 -3
  94. package/project/.sdk/tm/js/src/feature/test/TestFeature.js +14 -2
  95. package/project/.sdk/tm/js/src/utility/GraphqlUtility.js +148 -0
  96. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +1 -1
  97. package/project/.sdk/tm/js/src/utility/MakeResponseUtility.js +7 -0
  98. package/project/.sdk/tm/js/src/utility/MakeSpecUtility.js +19 -2
  99. package/project/.sdk/tm/js/src/utility/Utility.js +4 -0
  100. package/project/.sdk/tm/kotlin/core/SdkClient.kt +84 -0
  101. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  102. package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +92 -1
  103. package/project/.sdk/tm/kotlin/utility/Graphql.kt +145 -0
  104. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +1 -1
  105. package/project/.sdk/tm/kotlin/utility/MakeReqRes.kt +6 -0
  106. package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +17 -2
  107. package/project/.sdk/tm/kotlin/utility/Register.kt +2 -0
  108. package/project/.sdk/tm/lean/src/SdkUtility.lean +134 -1
  109. package/project/.sdk/tm/lua/feature/paging_feature.lua +97 -2
  110. package/project/.sdk/tm/lua/utility/graphql.lua +163 -0
  111. package/project/.sdk/tm/lua/utility/make_options.lua +1 -1
  112. package/project/.sdk/tm/lua/utility/make_response.lua +6 -0
  113. package/project/.sdk/tm/lua/utility/make_spec.lua +18 -2
  114. package/project/.sdk/tm/lua/utility/register.lua +3 -0
  115. package/project/.sdk/tm/ocaml/sdk_features.ml +164 -20
  116. package/project/.sdk/tm/ocaml/sdk_runtime.ml +143 -4
  117. package/project/.sdk/tm/ocaml/sdk_types.ml +2 -0
  118. package/project/.sdk/tm/perl/feature/paging_feature.pm +91 -3
  119. package/project/.sdk/tm/perl/utility/graphql.pm +150 -0
  120. package/project/.sdk/tm/perl/utility/make_options.pm +1 -1
  121. package/project/.sdk/tm/perl/utility/make_response.pm +6 -0
  122. package/project/.sdk/tm/perl/utility/make_spec.pm +20 -2
  123. package/project/.sdk/tm/perl/utility/register.pm +1 -0
  124. package/project/.sdk/tm/php/core/UtilityType.php +2 -0
  125. package/project/.sdk/tm/php/feature/PagingFeature.php +106 -4
  126. package/project/.sdk/tm/php/utility/Graphql.php +176 -0
  127. package/project/.sdk/tm/php/utility/MakeOptions.php +1 -1
  128. package/project/.sdk/tm/php/utility/MakeResponse.php +7 -0
  129. package/project/.sdk/tm/php/utility/MakeSpec.php +20 -2
  130. package/project/.sdk/tm/php/utility/Register.php +3 -0
  131. package/project/.sdk/tm/py/pkg/core/__init__.py +0 -0
  132. package/project/.sdk/tm/py/{core → pkg/core}/context.py +8 -8
  133. package/project/.sdk/tm/py/{core → pkg/core}/operation.py +1 -1
  134. package/project/.sdk/tm/py/{core → pkg/core}/response.py +1 -1
  135. package/project/.sdk/tm/py/{core → pkg/core}/result.py +1 -1
  136. package/project/.sdk/tm/py/{core → pkg/core}/utility_type.py +2 -0
  137. package/project/.sdk/tm/py/pkg/entity/__init__.py +0 -0
  138. package/project/.sdk/tm/py/pkg/feature/__init__.py +0 -0
  139. package/project/.sdk/tm/py/{feature → pkg/feature}/audit_feature.py +1 -1
  140. package/project/.sdk/tm/py/{feature → pkg/feature}/cache_feature.py +1 -1
  141. package/project/.sdk/tm/py/{feature → pkg/feature}/clienttrack_feature.py +1 -1
  142. package/project/.sdk/tm/py/{feature → pkg/feature}/debug_feature.py +1 -1
  143. package/project/.sdk/tm/py/{feature → pkg/feature}/idempotency_feature.py +1 -1
  144. package/project/.sdk/tm/py/{feature → pkg/feature}/log_feature.py +1 -1
  145. package/project/.sdk/tm/py/{feature → pkg/feature}/metrics_feature.py +1 -1
  146. package/project/.sdk/tm/py/{feature → pkg/feature}/netsim_feature.py +1 -1
  147. package/project/.sdk/tm/py/{feature → pkg/feature}/paging_feature.py +87 -6
  148. package/project/.sdk/tm/py/{feature → pkg/feature}/proxy_feature.py +1 -1
  149. package/project/.sdk/tm/py/{feature → pkg/feature}/ratelimit_feature.py +1 -1
  150. package/project/.sdk/tm/py/{feature → pkg/feature}/rbac_feature.py +1 -1
  151. package/project/.sdk/tm/py/{feature → pkg/feature}/retry_feature.py +1 -1
  152. package/project/.sdk/tm/py/{feature → pkg/feature}/streaming_feature.py +1 -1
  153. package/project/.sdk/tm/py/{feature → pkg/feature}/telemetry_feature.py +1 -1
  154. package/project/.sdk/tm/py/{feature → pkg/feature}/test_feature.py +2 -2
  155. package/project/.sdk/tm/py/{feature → pkg/feature}/timeout_feature.py +1 -1
  156. package/project/.sdk/tm/py/pkg/utility/__init__.py +0 -0
  157. package/project/.sdk/tm/py/{utility → pkg/utility}/feature_init.py +1 -1
  158. package/project/.sdk/tm/py/{utility → pkg/utility}/fetcher.py +1 -1
  159. package/project/.sdk/tm/py/pkg/utility/graphql.py +145 -0
  160. package/project/.sdk/tm/py/{utility → pkg/utility}/make_context.py +1 -1
  161. package/project/.sdk/tm/py/{utility → pkg/utility}/make_error.py +5 -5
  162. package/project/.sdk/tm/py/{utility → pkg/utility}/make_fetch_def.py +2 -2
  163. package/project/.sdk/tm/py/{utility → pkg/utility}/make_options.py +2 -2
  164. package/project/.sdk/tm/py/{utility → pkg/utility}/make_point.py +2 -2
  165. package/project/.sdk/tm/py/{utility → pkg/utility}/make_request.py +2 -2
  166. package/project/.sdk/tm/py/{utility → pkg/utility}/make_response.py +6 -0
  167. package/project/.sdk/tm/py/{utility → pkg/utility}/make_spec.py +19 -4
  168. package/project/.sdk/tm/py/{utility → pkg/utility}/make_url.py +1 -1
  169. package/project/.sdk/tm/py/{utility → pkg/utility}/param.py +2 -2
  170. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_auth.py +1 -1
  171. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_headers.py +1 -1
  172. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_method.py +1 -1
  173. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_params.py +1 -1
  174. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_path.py +1 -1
  175. package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_query.py +1 -1
  176. package/project/.sdk/tm/py/pkg/utility/register.py +71 -0
  177. package/project/.sdk/tm/py/{utility → pkg/utility}/transform_request.py +2 -2
  178. package/project/.sdk/tm/py/{utility → pkg/utility}/transform_response.py +2 -2
  179. package/project/.sdk/tm/py/test/feature_harness.py +6 -6
  180. package/project/.sdk/tm/py/test/runner.py +1 -1
  181. package/project/.sdk/tm/py/test/struct_runner.py +1 -1
  182. package/project/.sdk/tm/py/test/test_pipeline.py +5 -5
  183. package/project/.sdk/tm/py/test/test_primary_utility.py +8 -8
  184. package/project/.sdk/tm/py/test/test_struct_utility.py +3 -3
  185. package/project/.sdk/tm/py-data/LICENSE +22 -0
  186. package/project/.sdk/tm/py-data/Makefile +57 -0
  187. package/project/.sdk/tm/py-data/pkg/auth.py +131 -0
  188. package/project/.sdk/tm/py-data/pkg/fetch.py +178 -0
  189. package/project/.sdk/tm/py-data/pkg/frames.py +236 -0
  190. package/project/.sdk/tm/py-data/src/feature/README.md +8 -0
  191. package/project/.sdk/tm/py-data/src/feature/debug/.gitkeep +0 -0
  192. package/project/.sdk/tm/py-data/src/feature/idempotency/.gitkeep +0 -0
  193. package/project/.sdk/tm/py-data/src/feature/log/.gitkeep +0 -0
  194. package/project/.sdk/tm/py-data/src/feature/metrics/.gitkeep +0 -0
  195. package/project/.sdk/tm/py-data/src/feature/netsim/.gitkeep +0 -0
  196. package/project/.sdk/tm/py-data/src/feature/paging/.gitkeep +0 -0
  197. package/project/.sdk/tm/py-data/src/feature/proxy/.gitkeep +0 -0
  198. package/project/.sdk/tm/py-data/src/feature/ratelimit/.gitkeep +0 -0
  199. package/project/.sdk/tm/py-data/src/feature/rbac/.gitkeep +0 -0
  200. package/project/.sdk/tm/py-data/src/feature/retry/.gitkeep +0 -0
  201. package/project/.sdk/tm/py-data/src/feature/streaming/.gitkeep +0 -0
  202. package/project/.sdk/tm/py-data/src/feature/telemetry/.gitkeep +0 -0
  203. package/project/.sdk/tm/py-data/src/feature/test/.gitkeep +0 -0
  204. package/project/.sdk/tm/py-data/src/feature/timeout/.gitkeep +0 -0
  205. package/project/.sdk/tm/py-data/test/__init__.py +0 -0
  206. package/project/.sdk/tm/py-data/test/test_auth.py +95 -0
  207. package/project/.sdk/tm/py-data/test/test_fetch.py +152 -0
  208. package/project/.sdk/tm/py-data/test/test_frames.py +250 -0
  209. package/project/.sdk/tm/rb/core/utility_type.rb +1 -0
  210. package/project/.sdk/tm/rb/feature/paging_feature.rb +89 -3
  211. package/project/.sdk/tm/rb/utility/graphql.rb +131 -0
  212. package/project/.sdk/tm/rb/utility/make_options.rb +1 -1
  213. package/project/.sdk/tm/rb/utility/make_response.rb +6 -0
  214. package/project/.sdk/tm/rb/utility/make_spec.rb +18 -2
  215. package/project/.sdk/tm/rb/utility/register.rb +3 -0
  216. package/project/.sdk/tm/rust/feature/paging.rs +124 -2
  217. package/project/.sdk/tm/rust/utility/graphql.rs +193 -0
  218. package/project/.sdk/tm/rust/utility/make_options.rs +1 -1
  219. package/project/.sdk/tm/rust/utility/make_response.rs +6 -0
  220. package/project/.sdk/tm/rust/utility/make_spec.rs +32 -4
  221. package/project/.sdk/tm/rust/utility/mod.rs +1 -0
  222. package/project/.sdk/tm/scala/core/SdkClient.scala +90 -0
  223. package/project/.sdk/tm/scala/core/Utility.scala +4 -0
  224. package/project/.sdk/tm/scala/feature/PagingFeature.scala +104 -3
  225. package/project/.sdk/tm/scala/utility/Graphql.scala +160 -0
  226. package/project/.sdk/tm/scala/utility/Make.scala +7 -1
  227. package/project/.sdk/tm/scala/utility/MakeSpec.scala +22 -2
  228. package/project/.sdk/tm/scala/utility/Register.scala +2 -0
  229. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +4 -0
  230. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +86 -1
  231. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Graphql.swift +142 -0
  232. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Make.swift +24 -2
  233. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +1 -1
  234. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +2 -0
  235. package/project/.sdk/tm/ts/src/Point.ts +7 -0
  236. package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +82 -3
  237. package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +14 -2
  238. package/project/.sdk/tm/ts/src/utility/GraphqlUtility.ts +152 -0
  239. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +1 -1
  240. package/project/.sdk/tm/ts/src/utility/MakeResponseUtility.ts +7 -0
  241. package/project/.sdk/tm/ts/src/utility/MakeSpecUtility.ts +19 -2
  242. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -0
  243. package/project/.sdk/tm/zig/core/utility.zig +198 -3
  244. package/project/.sdk/tm/zig/feature/paging.zig +128 -1
  245. package/src/cmp/AgentGuideContent.ts +5 -0
  246. package/src/cmp/Feature.ts +13 -0
  247. package/src/helpers/canonType.ts +46 -0
  248. package/src/helpers/packageMeta.ts +7 -0
  249. package/src/sdkgen.ts +6 -1
  250. package/project/.sdk/tm/py/utility/register.py +0 -68
  251. /package/project/.sdk/tm/py/{core → pkg/core}/control.py +0 -0
  252. /package/project/.sdk/tm/py/{core → pkg/core}/error.py +0 -0
  253. /package/project/.sdk/tm/py/{core → pkg/core}/helpers.py +0 -0
  254. /package/project/.sdk/tm/py/{core → pkg/core}/spec.py +0 -0
  255. /package/project/.sdk/tm/py/{feature → pkg/feature}/base_feature.py +0 -0
  256. /package/project/.sdk/tm/py/{utility → pkg/utility}/clean.py +0 -0
  257. /package/project/.sdk/tm/py/{utility → pkg/utility}/done.py +0 -0
  258. /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_add.py +0 -0
  259. /package/project/.sdk/tm/py/{utility → pkg/utility}/feature_hook.py +0 -0
  260. /package/project/.sdk/tm/py/{utility → pkg/utility}/make_result.py +0 -0
  261. /package/project/.sdk/tm/py/{utility → pkg/utility}/prepare_body.py +0 -0
  262. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_basic.py +0 -0
  263. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_body.py +0 -0
  264. /package/project/.sdk/tm/py/{utility → pkg/utility}/result_headers.py +0 -0
  265. /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/__init__.py +0 -0
  266. /package/project/.sdk/tm/py/{utility → pkg/utility}/voxgig_struct/voxgig_struct.py +0 -0
  267. /package/project/.sdk/tm/{py/core/__init__.py → py-data/src/feature/audit/.gitkeep} +0 -0
  268. /package/project/.sdk/tm/{py/entity/__init__.py → py-data/src/feature/base/.gitkeep} +0 -0
  269. /package/project/.sdk/tm/{py/feature/__init__.py → py-data/src/feature/cache/.gitkeep} +0 -0
  270. /package/project/.sdk/tm/{py/utility/__init__.py → py-data/src/feature/clienttrack/.gitkeep} +0 -0
@@ -0,0 +1,250 @@
1
+ # ProjectName Data — frames engine tests.
2
+ #
3
+ # These cover the runtime that is the same for every API, so they live in the
4
+ # template rather than being generated. The generated per-entity accessor
5
+ # tests are in test_entity_frames.py.
6
+
7
+ from __future__ import annotations
8
+
9
+ import dataclasses
10
+
11
+ import pandas as pd
12
+ import pytest
13
+
14
+ from projectname_data.frames import (
15
+ build_frame,
16
+ to_record,
17
+ to_records,
18
+ apply_dtypes,
19
+ apply_dates,
20
+ order_columns,
21
+ records_df,
22
+ to_series,
23
+ )
24
+
25
+
26
+ @dataclasses.dataclass
27
+ class Sample:
28
+ name: str
29
+ count: int
30
+ nested: dict
31
+
32
+
33
+ class FakeEntity:
34
+ """Stands in for a generated ProjectName<X>Entity.
35
+
36
+ The private attributes matter: an entity's record is NOT in its public
37
+ __dict__, so anything relying on attribute scraping returns {} here.
38
+ """
39
+
40
+ def __init__(self, rec):
41
+ self._name = "thing"
42
+ self._data = rec
43
+ self._client = object()
44
+
45
+ def data_get(self):
46
+ return dict(self._data)
47
+
48
+
49
+ class TestToRecords:
50
+
51
+ def test_entity_object_is_unwrapped_via_data_get(self):
52
+ # list() yields entity OBJECTS, not dicts. Missing this produced a
53
+ # frame with the right row count and zero columns.
54
+ rec = to_record(FakeEntity({"id": "earth", "name": "Earth"}))
55
+ assert rec == {"id": "earth", "name": "Earth"}
56
+
57
+ def test_entities_build_a_populated_frame(self):
58
+ df = build_frame([
59
+ FakeEntity({"id": "earth", "diameter": 12756}),
60
+ FakeEntity({"id": "mars", "diameter": 6792}),
61
+ ])
62
+ assert df.shape == (2, 2)
63
+ assert list(df["id"]) == ["earth", "mars"]
64
+
65
+ def test_entity_wins_over_the_dunder_dict_fallback(self):
66
+ rec = to_record(FakeEntity({"id": "x"}))
67
+ assert "_data" not in rec
68
+ assert rec != {}
69
+
70
+ def test_dataclass_becomes_dict(self):
71
+ rec = to_record(Sample(name="a", count=1, nested={"x": 2}))
72
+ assert rec == {"name": "a", "count": 1, "nested": {"x": 2}}
73
+
74
+ def test_dict_passes_through(self):
75
+ assert to_record({"a": 1}) == {"a": 1}
76
+
77
+ def test_none_is_none(self):
78
+ assert to_record(None) is None
79
+
80
+ def test_single_record_is_wrapped(self):
81
+ assert to_records({"a": 1}) == [{"a": 1}]
82
+
83
+ def test_none_is_empty(self):
84
+ assert to_records(None) == []
85
+
86
+ def test_list_of_dataclasses(self):
87
+ out = to_records([Sample("a", 1, {}), Sample("b", 2, {})])
88
+ assert [r["name"] for r in out] == ["a", "b"]
89
+
90
+
91
+ class TestFlatten:
92
+
93
+ def test_one_level_by_default(self):
94
+ df = build_frame([{"a": 1, "b": {"c": 2}}])
95
+ assert "b.c" in df.columns
96
+ assert "b" not in df.columns
97
+
98
+ def test_flatten_none_keeps_nesting(self):
99
+ df = build_frame([{"a": 1, "b": {"c": 2}}], flatten="none")
100
+ assert "b" in df.columns
101
+ assert df["b"].iloc[0] == {"c": 2}
102
+
103
+ def test_deep_nesting_stays_boxed_at_depth_one(self):
104
+ # The point of the depth-1 default: a deep payload must not explode
105
+ # into hundreds of columns.
106
+ df = build_frame([{"a": {"b": {"c": {"d": 1}}}}])
107
+ assert "a.b" in df.columns
108
+ assert isinstance(df["a.b"].iloc[0], dict)
109
+
110
+ def test_flatten_full_recurses(self):
111
+ df = build_frame([{"a": {"b": {"c": 1}}}], flatten="full")
112
+ assert "a.b.c" in df.columns
113
+
114
+
115
+ class TestDtypes:
116
+
117
+ def test_nullable_integer_survives_nulls(self):
118
+ # The whole reason for Int64 over int64: a null in an integer column
119
+ # must not silently turn the column into float64.
120
+ df = build_frame(
121
+ [{"n": 1}, {"n": None}, {"n": 3}],
122
+ dtypes={"n": "Int64"},
123
+ )
124
+ assert str(df["n"].dtype) == "Int64"
125
+ assert df["n"].iloc[0] == 1
126
+ assert pd.isna(df["n"].iloc[1])
127
+
128
+ def test_nullable_boolean_survives_nulls(self):
129
+ df = build_frame(
130
+ [{"b": True}, {"b": None}],
131
+ dtypes={"b": "boolean"},
132
+ )
133
+ assert str(df["b"].dtype) == "boolean"
134
+
135
+ def test_string_dtype_applied(self):
136
+ df = build_frame([{"s": "x"}], dtypes={"s": "string"})
137
+ assert str(df["s"].dtype) == "string"
138
+
139
+ def test_numeric_strings_are_rescued(self):
140
+ df = build_frame([{"n": "1"}, {"n": "2"}], dtypes={"n": "Int64"})
141
+ assert str(df["n"].dtype) == "Int64"
142
+ assert df["n"].iloc[1] == 2
143
+
144
+ def test_unconvertible_column_is_left_alone_not_raised(self):
145
+ # An analyst with a usable frame and one object column is far better
146
+ # served than one holding an exception.
147
+ df = build_frame([{"n": "not-a-number"}], dtypes={"n": "Int64"})
148
+ assert len(df) == 1
149
+ # And the VALUE must survive. to_numeric(errors="coerce") would have
150
+ # turned it into NA — a silent data loss dressed up as a successful
151
+ # conversion. The rescue is only allowed when it is lossless.
152
+ assert df["n"].iloc[0] == "not-a-number"
153
+
154
+ def test_partially_numeric_column_is_not_coerced(self):
155
+ # One bad value must not blank out the rest of the column.
156
+ df = build_frame(
157
+ [{"n": "1"}, {"n": "oops"}, {"n": "3"}],
158
+ dtypes={"n": "Int64"},
159
+ )
160
+ assert list(df["n"]) == ["1", "oops", "3"]
161
+
162
+ def test_numeric_rescue_still_applies_when_lossless(self):
163
+ # Nulls are not "lost" data, so a column of numeric strings with a
164
+ # None in it still converts.
165
+ df = build_frame(
166
+ [{"n": "1"}, {"n": None}, {"n": "3"}],
167
+ dtypes={"n": "Int64"},
168
+ )
169
+ assert str(df["n"].dtype) == "Int64"
170
+ assert df["n"].iloc[0] == 1
171
+ assert pd.isna(df["n"].iloc[1])
172
+
173
+ def test_missing_declared_column_is_ignored(self):
174
+ df = build_frame([{"a": 1}], dtypes={"absent": "Int64"})
175
+ assert "absent" not in df.columns
176
+
177
+ def test_dtype_false_skips_coercion(self):
178
+ df = build_frame([{"n": 1}], dtypes={"n": "string"}, dtype=False)
179
+ assert str(df["n"].dtype) != "string"
180
+
181
+
182
+ class TestOrder:
183
+
184
+ def test_declared_order_first_extras_appended(self):
185
+ df = build_frame(
186
+ [{"z": 1, "a": 2, "extra": 3}],
187
+ order=["a", "z"],
188
+ )
189
+ assert list(df.columns) == ["a", "z", "extra"]
190
+
191
+ def test_absent_declared_columns_are_skipped(self):
192
+ df = order_columns(pd.DataFrame({"a": [1]}), ["missing", "a"])
193
+ assert list(df.columns) == ["a"]
194
+
195
+
196
+ class TestEmpty:
197
+
198
+ def test_empty_result_keeps_columns_and_dtypes(self):
199
+ # A bare pd.DataFrame() would KeyError on the first column access;
200
+ # downstream code must behave the same whether or not rows came back.
201
+ df = build_frame([], order=["a", "b"], dtypes={"a": "Int64", "b": "string"})
202
+ assert list(df.columns) == ["a", "b"]
203
+ assert str(df["a"].dtype) == "Int64"
204
+ assert len(df) == 0
205
+ assert df.empty
206
+
207
+ def test_empty_without_model_is_still_a_frame(self):
208
+ df = build_frame([])
209
+ assert isinstance(df, pd.DataFrame)
210
+ assert len(df) == 0
211
+
212
+
213
+ class TestDates:
214
+
215
+ def test_parse_dates_is_explicit_and_utc(self):
216
+ df = build_frame([{"when": "2026-01-02T03:04:05Z"}], parse_dates=["when"])
217
+ assert str(df["when"].dtype).startswith("datetime64")
218
+ assert df["when"].iloc[0].year == 2026
219
+
220
+ def test_unparseable_date_becomes_nat_not_an_error(self):
221
+ df = build_frame([{"when": "nonsense"}], parse_dates=["when"])
222
+ assert pd.isna(df["when"].iloc[0])
223
+
224
+ def test_dates_are_never_inferred(self):
225
+ # No $DATE sentinel exists in the model, so a date-looking string must
226
+ # stay a string unless the caller asks for parsing.
227
+ df = build_frame([{"when": "2026-01-02T03:04:05Z"}])
228
+ assert not str(df["when"].dtype).startswith("datetime64")
229
+
230
+
231
+ class TestScalarsAndSeries:
232
+
233
+ def test_scalar_list_becomes_value_column(self):
234
+ df = build_frame(["a", "b"])
235
+ assert list(df.columns) == ["value"]
236
+ assert list(df["value"]) == ["a", "b"]
237
+
238
+ def test_to_series_from_one_record(self):
239
+ s = to_series({"a": 1, "b": 2})
240
+ assert isinstance(s, pd.Series)
241
+ assert s["a"] == 1
242
+
243
+ def test_to_series_empty(self):
244
+ s = to_series(None)
245
+ assert isinstance(s, pd.Series)
246
+ assert len(s) == 0
247
+
248
+ def test_records_df_is_the_public_escape_hatch(self):
249
+ df = records_df([{"a": 1}])
250
+ assert list(df.columns) == ["a"]
@@ -7,6 +7,7 @@ class ProjectNameUtility
7
7
  :make_point, :make_spec, :make_url, :param, :prepare_auth,
8
8
  :prepare_body, :prepare_headers, :prepare_method,
9
9
  :prepare_params, :prepare_path, :prepare_query,
10
+ :graphql_body, :graphql_errors,
10
11
  :result_basic, :result_body, :result_headers,
11
12
  :transform_request, :transform_response, :custom
12
13
 
@@ -45,6 +45,14 @@ class ProjectNamePagingFeature < ProjectNameBaseFeature
45
45
  paging = ctx.ctrl.paging
46
46
  end
47
47
 
48
+ # GraphQL paginates through operation VARIABLES, not the query string.
49
+ # This hook runs after make_spec, so spec.body already holds the
50
+ # { query, variables } envelope, and before make_fetch_def serialises it.
51
+ if "graphql" == VoxgigStruct.getprop(ctx.point, "kind")
52
+ _graphql_pre_request(ctx, paging)
53
+ return
54
+ end
55
+
48
56
  if !paging["cursor"].nil?
49
57
  spec.query[cursor_param] = paging["cursor"]
50
58
  elsif spec.query[page_param].nil?
@@ -57,6 +65,41 @@ class ProjectNamePagingFeature < ProjectNameBaseFeature
57
65
  end
58
66
  end
59
67
 
68
+ # Relay pagination: the cursor is the `after` variable (or whatever the
69
+ # model named it), and the page size is `first`.
70
+ def _graphql_pre_request(ctx, paging)
71
+ body = ctx.spec.body
72
+ return unless body.is_a?(Hash)
73
+
74
+ variables = body["variables"]
75
+ unless variables.is_a?(Hash)
76
+ variables = {}
77
+ body["variables"] = variables
78
+ end
79
+
80
+ after_var = @options["afterVar"] || "after"
81
+ first_var = @options["firstVar"] || "first"
82
+
83
+ # Only bind variables the operation actually declares, or the server
84
+ # rejects the document.
85
+ declared = {}
86
+ varlist = VoxgigStruct.getpath(ctx.point, "graphql.vars")
87
+ if varlist.is_a?(Array)
88
+ varlist.each do |v|
89
+ name = VoxgigStruct.getprop(v, "name")
90
+ declared[name] = true unless name.nil?
91
+ end
92
+ end
93
+
94
+ if !paging["cursor"].nil? && declared[after_var]
95
+ variables[after_var] = paging["cursor"]
96
+ end
97
+
98
+ if !@options["limit"].nil? && variables[first_var].nil? && declared[first_var]
99
+ variables[first_var] = @options["limit"]
100
+ end
101
+ end
102
+
60
103
  def PreResult(ctx)
61
104
  return unless @active
62
105
  return unless _list?(ctx)
@@ -75,6 +118,39 @@ class ProjectNamePagingFeature < ProjectNameBaseFeature
75
118
  "hasMore" => false,
76
119
  }
77
120
 
121
+ # Set when the response states hasMore outright, rather than leaving it
122
+ # to be inferred from the presence of a cursor.
123
+ explicit_more = false
124
+
125
+ # Relay connections carry the cursor in pageInfo, at the path the model
126
+ # recorded for this op.
127
+ page = VoxgigStruct.getpath(ctx.point, "graphql.page")
128
+ if page.is_a?(Hash) && body.is_a?(Hash)
129
+ # `connpath` locates the connection object inside the response envelope
130
+ # (data.<field>); the cursor/more paths are relative to it.
131
+ connpath = page["connpath"]
132
+ conn = body
133
+ if connpath.is_a?(String) && "" != connpath
134
+ sub = VoxgigStruct.getpath(body, connpath)
135
+ conn = sub unless sub.nil?
136
+ end
137
+
138
+ cursorpath = page["cursor"]
139
+ if cursorpath.is_a?(String) && "" != cursorpath
140
+ cursor = VoxgigStruct.getpath(conn, cursorpath)
141
+ paging["cursor"] = cursor unless cursor.nil?
142
+ end
143
+
144
+ morepath = page["more"]
145
+ if morepath.is_a?(String) && "" != morepath
146
+ more = VoxgigStruct.getpath(conn, morepath)
147
+ if more == true || more == false
148
+ paging["hasMore"] = more
149
+ explicit_more = true
150
+ end
151
+ end
152
+ end
153
+
78
154
  # Link: <...>; rel="next"
79
155
  link = _header(headers, "link")
80
156
  unless link.nil?
@@ -87,11 +163,21 @@ class ProjectNamePagingFeature < ProjectNameBaseFeature
87
163
  paging["next"] = paging["next"] || body["next"] unless body["next"].nil?
88
164
  paging["cursor"] = body["cursor"] unless body["cursor"].nil?
89
165
  paging["cursor"] = body["nextCursor"] unless body["nextCursor"].nil?
90
- paging["hasMore"] = body["hasMore"] if body["hasMore"] == true || body["hasMore"] == false
166
+ if body["hasMore"] == true || body["hasMore"] == false
167
+ paging["hasMore"] = body["hasMore"]
168
+ explicit_more = true
169
+ end
91
170
  end
92
171
 
93
- paging["hasMore"] = paging["hasMore"] ||
94
- !paging["next"].nil? || !paging["cursor"].nil? || !paging["nextPage"].nil?
172
+ # Cursor presence only INFERS another page. When the server stated the
173
+ # answer outright relay's `hasNextPage: false`, or a body `hasMore` —
174
+ # that wins: a final page normally carries both an end cursor and
175
+ # hasNextPage false, and inferring from the cursor there would send the
176
+ # caller back for a page that does not exist, forever.
177
+ unless explicit_more
178
+ paging["hasMore"] = paging["hasMore"] ||
179
+ !paging["next"].nil? || !paging["cursor"].nil? || !paging["nextPage"].nil?
180
+ end
95
181
 
96
182
  result.paging = paging
97
183
 
@@ -0,0 +1,131 @@
1
+ # ProjectName SDK utility: graphql
2
+ #
3
+ # GraphQL transport. API-INDEPENDENT: every GraphQL SDK this generator
4
+ # produces uses this file unchanged. The API-specific part — which
5
+ # operations exist and what each one's document is — is model data,
6
+ # computed once by apidef and emitted into Config.
7
+ #
8
+ # Two jobs:
9
+ #
10
+ # GraphqlBody — build { query, variables } for a point, binding the
11
+ # op's arguments to the document's declared variables.
12
+ #
13
+ # GraphqlErrors — lift a GraphQL failure into an SDK error. GraphQL
14
+ # reports failures as a top-level `errors` array under
15
+ # HTTP 200, so the status-driven path in result_basic
16
+ # never sees them.
17
+
18
+ require_relative 'struct/voxgig_struct'
19
+
20
+ module ProjectNameUtilities
21
+ # Content type every GraphQL-over-HTTP request uses.
22
+ GRAPHQL_CONTENT_TYPE = 'application/json'
23
+
24
+ # Map a GraphQL error to the same error codes the HTTP path produces, so
25
+ # a caller handles auth or rate limiting identically on both transports.
26
+ # Servers put the machine-readable code in `extensions.code`;
27
+ # Linear-style APIs use `extensions.type`.
28
+ GraphqlErrorCode = ->(gqlerr) {
29
+ ext = VoxgigStruct.getprop(gqlerr, 'extensions') || {}
30
+
31
+ raw = VoxgigStruct.getprop(ext, 'code') ||
32
+ VoxgigStruct.getprop(ext, 'type') || ''
33
+ raw = raw.to_s.upcase
34
+
35
+ if raw.include?('AUTH') || raw.include?('FORBIDDEN') ||
36
+ raw.include?('UNAUTHENTICATED')
37
+ next 'request_auth'
38
+ end
39
+ if raw.include?('RATELIMIT') || raw.include?('RATE_LIMIT') ||
40
+ raw.include?('TOO_MANY')
41
+ next 'request_ratelimit'
42
+ end
43
+ if raw.include?('BAD_USER_INPUT') || raw.include?('VALIDATION') ||
44
+ raw.include?('INVALID')
45
+ next 'request_invalid'
46
+ end
47
+
48
+ 'request_graphql'
49
+ }
50
+
51
+ # Build the request body for a GraphQL point.
52
+ #
53
+ # Variables come from the op's own arguments: a named variable binds to
54
+ # the like-named argument (`from`), and the input-object variable (empty
55
+ # `from`) takes the request data as a whole — which is what makes a
56
+ # generated create/update call look exactly like its REST equivalent.
57
+ GraphqlBody = ->(ctx) {
58
+ gql = VoxgigStruct.getprop(ctx.point, 'graphql')
59
+ next nil unless gql.is_a?(Hash)
60
+
61
+ # reqmatch/reqdata hold the caller's arguments for THIS call; data/match
62
+ # hold the entity's current state. Which pair depends on whether the op
63
+ # takes match or data input. A named variable falls back to the current
64
+ # state, so updating a loaded entity with just {title} still binds the
65
+ # stored id the mutation requires.
66
+ datainput = ctx.op && 'data' == ctx.op.input
67
+ reqsrc = datainput ? ctx.reqdata : ctx.reqmatch
68
+ datasrc = datainput ? ctx.data : ctx.match
69
+ reqsrc = {} unless reqsrc.is_a?(Hash)
70
+ datasrc = {} unless datasrc.is_a?(Hash)
71
+
72
+ variables = {}
73
+
74
+ varlist = VoxgigStruct.getprop(gql, 'vars')
75
+ varlist = [] unless varlist.is_a?(Array)
76
+
77
+ varlist.each do |spec|
78
+ next unless spec.is_a?(Hash)
79
+
80
+ name = VoxgigStruct.getprop(spec, 'name')
81
+ from = VoxgigStruct.getprop(spec, 'from')
82
+
83
+ if from.nil? || '' == from
84
+ # The input object IS the request body. Strip the action selector,
85
+ # which is an SDK-side point discriminator, not an API field.
86
+ body = {}
87
+ reqsrc.each { |k, v| body[k] = v unless '$action' == k }
88
+ variables[name] = body
89
+ next
90
+ end
91
+
92
+ # Only send variables the caller actually supplied: sending an
93
+ # explicit null would clear a field on many APIs.
94
+ val = VoxgigStruct.getprop(reqsrc, from)
95
+ val = VoxgigStruct.getprop(datasrc, from) if val.nil?
96
+ variables[name] = val unless val.nil?
97
+ end
98
+
99
+ {
100
+ 'query' => VoxgigStruct.getprop(gql, 'doc'),
101
+ 'variables' => variables
102
+ }
103
+ }
104
+
105
+ # Inspect a decoded GraphQL response body and record a failure when the
106
+ # server reported one. Returns true when an error was recorded.
107
+ #
108
+ # Partial data (`data` alongside `errors`) is treated as failure: the
109
+ # REST surface has no partial-success concept, and silently returning
110
+ # half an object would be worse than failing. The raw envelope stays
111
+ # available on the result for callers that need it.
112
+ GraphqlErrors = ->(ctx) {
113
+ result = ctx.result
114
+ point = ctx.point
115
+
116
+ next false if result.nil? || point.nil?
117
+ next false unless 'graphql' == VoxgigStruct.getprop(point, 'kind')
118
+
119
+ errors = VoxgigStruct.getprop(result.body, 'errors')
120
+ next false unless errors.is_a?(Array) && !errors.empty?
121
+
122
+ first = errors[0]
123
+ msg = VoxgigStruct.getprop(first, 'message') || 'graphql error'
124
+ msg = msg + ' (+' + (errors.length - 1).to_s + ' more)' if 1 < errors.length
125
+
126
+ result.err = ctx.make_error(GraphqlErrorCode.call(first), 'graphql: ' + msg)
127
+ result.ok = false
128
+
129
+ true
130
+ }
131
+ end
@@ -44,7 +44,7 @@ module ProjectNameUtilities
44
44
  "headers" => { "`$CHILD`" => "`$STRING`" },
45
45
  "allow" => {
46
46
  "method" => "GET,PUT,POST,PATCH,DELETE,OPTIONS",
47
- "op" => "create,update,load,list,remove,command,direct",
47
+ "op" => "create,update,load,list,remove,command,direct,graphql",
48
48
  },
49
49
  "entity" => { "`$CHILD`" => { "`$OPEN`" => true, "active" => false, "alias" => {} } },
50
50
  "feature" => { "`$CHILD`" => { "`$OPEN`" => true, "active" => false } },
@@ -15,6 +15,12 @@ module ProjectNameUtilities
15
15
  utility.result_basic.call(ctx)
16
16
  utility.result_headers.call(ctx)
17
17
  utility.result_body.call(ctx)
18
+
19
+ # GraphQL reports failures as a top-level `errors` array under HTTP
20
+ # 200, so result_basic's status check never sees them. Lift them here,
21
+ # before the response transform tries to unwrap data that is not there.
22
+ utility.graphql_errors.call(ctx)
23
+
18
24
  utility.transform_response.call(ctx)
19
25
 
20
26
  result.ok = true if result.err.nil?
@@ -1,5 +1,6 @@
1
1
  # ProjectName SDK utility: make_spec
2
2
  require_relative 'struct/voxgig_struct'
3
+ require_relative 'graphql'
3
4
  require_relative '../core/spec'
4
5
  module ProjectNameUtilities
5
6
  MakeSpec = ->(ctx) {
@@ -36,8 +37,23 @@ module ProjectNameUtilities
36
37
  ctx.spec.params = utility.prepare_params.call(ctx)
37
38
  ctx.spec.query = utility.prepare_query.call(ctx)
38
39
  ctx.spec.headers = utility.prepare_headers.call(ctx)
39
- ctx.spec.body = utility.prepare_body.call(ctx)
40
- ctx.spec.path = utility.prepare_path.call(ctx)
40
+
41
+ if 'graphql' == VoxgigStruct.getprop(point, 'kind')
42
+ # GraphQL addresses one endpoint: no path parts, no query string, and
43
+ # the body carries the operation. prepare_body is skipped
44
+ # deliberately — it only emits a body for data-input ops, whereas
45
+ # every GraphQL op posts one, including load/list/remove.
46
+ ctx.spec.body = utility.graphql_body.call(ctx)
47
+ ctx.spec.path = ''
48
+ # prepare_query already copied the op's match arguments into the
49
+ # query string. Those same values are bound as operation variables,
50
+ # so leaving them would send /graphql?id=i1.
51
+ ctx.spec.query = {}
52
+ ctx.spec.headers['content-type'] = GRAPHQL_CONTENT_TYPE
53
+ else
54
+ ctx.spec.body = utility.prepare_body.call(ctx)
55
+ ctx.spec.path = utility.prepare_path.call(ctx)
56
+ end
41
57
 
42
58
  ctx.ctrl.explain["spec"] = ctx.spec if ctx.ctrl.explain
43
59
 
@@ -24,6 +24,7 @@ require_relative 'prepare_method'
24
24
  require_relative 'prepare_params'
25
25
  require_relative 'prepare_path'
26
26
  require_relative 'prepare_query'
27
+ require_relative 'graphql'
27
28
  require_relative 'result_basic'
28
29
  require_relative 'result_body'
29
30
  require_relative 'result_headers'
@@ -55,6 +56,8 @@ ProjectNameUtility.registrar = ->(u) {
55
56
  u.prepare_params = ProjectNameUtilities::PrepareParams
56
57
  u.prepare_path = ProjectNameUtilities::PreparePath
57
58
  u.prepare_query = ProjectNameUtilities::PrepareQuery
59
+ u.graphql_body = ProjectNameUtilities::GraphqlBody
60
+ u.graphql_errors = ProjectNameUtilities::GraphqlErrors
58
61
  u.result_basic = ProjectNameUtilities::ResultBasic
59
62
  u.result_body = ProjectNameUtilities::ResultBody
60
63
  u.result_headers = ProjectNameUtilities::ResultHeaders