@voxgig/sdkgen 4.32.0 → 4.33.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 (415) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/helpers/naming.js +1 -1
  3. package/dist/helpers/naming.js.map +1 -1
  4. package/dist/tsconfig.tsbuildinfo +1 -1
  5. package/model/sdkgen.aontu +7 -1
  6. package/package.json +1 -1
  7. package/project/.sdk/model/feature/debug.aontu +3 -1
  8. package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
  9. package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
  10. package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
  11. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
  12. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
  13. package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
  14. package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
  15. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
  16. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
  17. package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
  18. package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
  19. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
  20. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
  21. package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
  22. package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
  23. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
  24. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
  25. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
  26. package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
  27. package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
  28. package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
  29. package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
  30. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
  31. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
  32. package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
  33. package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
  34. package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
  35. package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
  36. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
  37. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
  38. package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
  39. package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
  40. package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
  41. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
  42. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
  43. package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
  44. package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
  45. package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
  46. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
  47. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
  48. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
  49. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
  50. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
  51. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
  52. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
  53. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
  54. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
  55. package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
  56. package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
  57. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
  58. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
  59. package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
  60. package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
  61. package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
  62. package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
  63. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
  64. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
  65. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
  66. package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
  67. package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
  68. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
  69. package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
  70. package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
  71. package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
  72. package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
  73. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
  74. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
  75. package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
  76. package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
  77. package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
  78. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
  79. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
  80. package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
  81. package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
  82. package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
  83. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
  84. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
  85. package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
  86. package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
  87. package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
  88. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
  89. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
  90. package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
  91. package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
  92. package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
  93. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
  94. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
  95. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
  96. package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
  97. package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
  98. package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
  99. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
  100. package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
  101. package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
  102. package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
  103. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
  104. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
  105. package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
  106. package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
  107. package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
  108. package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
  109. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
  110. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
  111. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
  112. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
  113. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
  114. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
  115. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
  116. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
  117. package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
  118. package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
  119. package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
  120. package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
  121. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
  122. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
  123. package/project/.sdk/tm/c/core/context.c +25 -0
  124. package/project/.sdk/tm/c/core/error.c +16 -0
  125. package/project/.sdk/tm/c/core/sdk.h +22 -0
  126. package/project/.sdk/tm/c/feature/audit.c +2 -0
  127. package/project/.sdk/tm/c/feature/cost.c +1 -0
  128. package/project/.sdk/tm/c/feature/debug.c +19 -29
  129. package/project/.sdk/tm/c/feature/log.c +21 -2
  130. package/project/.sdk/tm/c/feature/proxy.c +55 -3
  131. package/project/.sdk/tm/c/feature/secrets.c +7 -0
  132. package/project/.sdk/tm/c/feature/telemetry.c +2 -0
  133. package/project/.sdk/tm/c/tests/feature_test.c +2 -2
  134. package/project/.sdk/tm/c/utility/clean.c +530 -8
  135. package/project/.sdk/tm/c/utility/done.c +28 -12
  136. package/project/.sdk/tm/c/utility/make_error.c +4 -3
  137. package/project/.sdk/tm/c/utility/make_options.c +71 -45
  138. package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
  139. package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
  140. package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
  141. package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
  142. package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
  143. package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
  144. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
  145. package/project/.sdk/tm/cpp/core/types.hpp +93 -3
  146. package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
  147. package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
  148. package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
  149. package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
  150. package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
  151. package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
  152. package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
  153. package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
  154. package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
  155. package/project/.sdk/tm/csharp/core/Context.cs +32 -0
  156. package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
  157. package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
  158. package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
  159. package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
  160. package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
  161. package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
  162. package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
  163. package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
  164. package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
  165. package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
  166. package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
  167. package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
  168. package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
  169. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
  170. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
  171. package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
  172. package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
  173. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
  174. package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
  175. package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
  176. package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
  177. package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
  178. package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
  179. package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
  180. package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
  181. package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
  182. package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
  183. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
  184. package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
  185. package/project/.sdk/tm/go/core/context.go +42 -0
  186. package/project/.sdk/tm/go/core/error.go +30 -10
  187. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  188. package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
  189. package/project/.sdk/tm/go/feature/base_feature.go +12 -0
  190. package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
  191. package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
  192. package/project/.sdk/tm/go/feature/log_feature.go +13 -8
  193. package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
  194. package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
  195. package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
  196. package/project/.sdk/tm/go/test/feature_test.go +2 -2
  197. package/project/.sdk/tm/go/utility/clean.go +585 -2
  198. package/project/.sdk/tm/go/utility/done.go +29 -9
  199. package/project/.sdk/tm/go/utility/make_error.go +51 -16
  200. package/project/.sdk/tm/go/utility/make_options.go +77 -36
  201. package/project/.sdk/tm/go/utility/register.go +12 -0
  202. package/project/.sdk/tm/java/core/Context.java +29 -0
  203. package/project/.sdk/tm/java/core/SdkClient.java +4 -2
  204. package/project/.sdk/tm/java/core/Utility.java +7 -0
  205. package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
  206. package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
  207. package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
  208. package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
  209. package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
  210. package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
  211. package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
  212. package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
  213. package/project/.sdk/tm/java/utility/Clean.java +519 -1
  214. package/project/.sdk/tm/java/utility/Done.java +1 -1
  215. package/project/.sdk/tm/java/utility/MakeError.java +5 -1
  216. package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
  217. package/project/.sdk/tm/java/utility/Register.java +4 -0
  218. package/project/.sdk/tm/js/src/Context.js +5 -1
  219. package/project/.sdk/tm/js/src/Response.js +14 -1
  220. package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
  221. package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
  222. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
  223. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
  224. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
  225. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
  226. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
  227. package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
  228. package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
  229. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
  230. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
  231. package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
  232. package/project/.sdk/tm/js/test/feature/harness.js +11 -1
  233. package/project/.sdk/tm/js/test/feature.test.js +9 -2
  234. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +25 -0
  235. package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
  236. package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
  237. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  238. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
  239. package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
  240. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
  241. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
  242. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
  243. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
  244. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
  245. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
  246. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
  247. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
  248. package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
  249. package/project/.sdk/tm/lua/core/context.lua +43 -0
  250. package/project/.sdk/tm/lua/core/error.lua +36 -1
  251. package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
  252. package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
  253. package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
  254. package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
  255. package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
  256. package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
  257. package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
  258. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
  259. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
  260. package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
  261. package/project/.sdk/tm/lua/utility/clean.lua +426 -2
  262. package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
  263. package/project/.sdk/tm/lua/utility/done.lua +1 -7
  264. package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
  265. package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
  266. package/project/.sdk/tm/lua/utility/register.lua +4 -1
  267. package/project/.sdk/tm/ocaml/Makefile +5 -1
  268. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
  269. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
  270. package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
  271. package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
  272. package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
  273. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
  274. package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
  275. package/project/.sdk/tm/perl/core/context.pm +27 -0
  276. package/project/.sdk/tm/perl/core/error.pm +52 -5
  277. package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
  278. package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
  279. package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
  280. package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
  281. package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
  282. package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
  283. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
  284. package/project/.sdk/tm/perl/t/feature.t +4 -2
  285. package/project/.sdk/tm/perl/utility/clean.pm +345 -1
  286. package/project/.sdk/tm/perl/utility/done.pm +24 -6
  287. package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
  288. package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
  289. package/project/.sdk/tm/php/core/Context.php +24 -1
  290. package/project/.sdk/tm/php/core/Error.php +34 -3
  291. package/project/.sdk/tm/php/core/UtilityType.php +4 -0
  292. package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
  293. package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
  294. package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
  295. package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
  296. package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
  297. package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
  298. package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
  299. package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
  300. package/project/.sdk/tm/php/utility/Clean.php +438 -2
  301. package/project/.sdk/tm/php/utility/Done.php +14 -7
  302. package/project/.sdk/tm/php/utility/MakeError.php +9 -7
  303. package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
  304. package/project/.sdk/tm/php/utility/Register.php +2 -0
  305. package/project/.sdk/tm/py/pkg/core/context.py +17 -0
  306. package/project/.sdk/tm/py/pkg/core/error.py +42 -1
  307. package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
  308. package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
  309. package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
  310. package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
  311. package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
  312. package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
  313. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
  314. package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
  315. package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
  316. package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
  317. package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
  318. package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
  319. package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
  320. package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
  321. package/project/.sdk/tm/py/test/feature_harness.py +4 -0
  322. package/project/.sdk/tm/py/test/test_feature.py +2 -2
  323. package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
  324. package/project/.sdk/tm/rb/core/context.rb +28 -0
  325. package/project/.sdk/tm/rb/core/error.rb +30 -0
  326. package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
  327. package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
  328. package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
  329. package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
  330. package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
  331. package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
  332. package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
  333. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
  334. package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
  335. package/project/.sdk/tm/rb/utility/clean.rb +312 -1
  336. package/project/.sdk/tm/rb/utility/done.rb +15 -5
  337. package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
  338. package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
  339. package/project/.sdk/tm/rb/utility/register.rb +2 -0
  340. package/project/.sdk/tm/rust/core/context.rs +55 -0
  341. package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
  342. package/project/.sdk/tm/rust/feature/audit.rs +2 -0
  343. package/project/.sdk/tm/rust/feature/cost.rs +3 -2
  344. package/project/.sdk/tm/rust/feature/debug.rs +16 -16
  345. package/project/.sdk/tm/rust/feature/log.rs +42 -7
  346. package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
  347. package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
  348. package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
  349. package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
  350. package/project/.sdk/tm/rust/utility/clean.rs +446 -5
  351. package/project/.sdk/tm/rust/utility/done.rs +22 -12
  352. package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
  353. package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
  354. package/project/.sdk/tm/scala/Makefile +3 -1
  355. package/project/.sdk/tm/scala/core/Context.scala +16 -0
  356. package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
  357. package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
  358. package/project/.sdk/tm/scala/core/Types.scala +3 -0
  359. package/project/.sdk/tm/scala/core/Utility.scala +2 -0
  360. package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
  361. package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
  362. package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
  363. package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
  364. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
  365. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
  366. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
  367. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
  368. package/project/.sdk/tm/scala/utility/Make.scala +63 -20
  369. package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
  370. package/project/.sdk/tm/scala/utility/Register.scala +1 -0
  371. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
  372. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
  373. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
  374. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
  375. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
  376. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
  377. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
  378. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
  379. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
  380. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
  381. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
  382. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
  383. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
  384. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
  385. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
  386. package/project/.sdk/tm/ts/src/Context.ts +5 -1
  387. package/project/.sdk/tm/ts/src/Response.ts +14 -1
  388. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
  389. package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
  390. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
  391. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
  392. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
  393. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
  394. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
  395. package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
  396. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
  397. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
  398. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
  399. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
  400. package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
  401. package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
  402. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +25 -0
  403. package/project/.sdk/tm/zig/core/context.zig +34 -0
  404. package/project/.sdk/tm/zig/core/error.zig +22 -1
  405. package/project/.sdk/tm/zig/core/utility.zig +403 -39
  406. package/project/.sdk/tm/zig/feature/audit.zig +4 -2
  407. package/project/.sdk/tm/zig/feature/cost.zig +3 -2
  408. package/project/.sdk/tm/zig/feature/debug.zig +20 -25
  409. package/project/.sdk/tm/zig/feature/log.zig +3 -1
  410. package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
  411. package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
  412. package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
  413. package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
  414. package/project/sdkgen-package.json +1 -1
  415. package/src/helpers/naming.ts +1 -1
@@ -0,0 +1,809 @@
1
+ import {
2
+ cmp,
3
+ File,
4
+ Content,
5
+ isAuthSuppressed,
6
+ isHttpBasicAuth,
7
+ resolveAuthIn,
8
+ resolveAuthName,
9
+ } from '@voxgig/sdkgen'
10
+
11
+
12
+ // The canary sweep, as TestClean_ts emits it: every credential slot holds a
13
+ // distinctive value, every diagnostic feature this SDK ships is switched on
14
+ // with a capturing sink, a real operation runs through every outcome, and
15
+ // every string that leaves the SDK is searched for the canaries and their
16
+ // encoded forms. With clean switched off the canary MUST show.
17
+ const TestClean = cmp(function TestClean(props: any) {
18
+ const { model } = props.ctx$
19
+ const { target } = props
20
+
21
+ const auth = {
22
+ suppressed: isAuthSuppressed(model),
23
+ where: resolveAuthIn(model),
24
+ name: 'header' === resolveAuthIn(model)
25
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
26
+ basic: isHttpBasicAuth(model),
27
+ }
28
+
29
+ File({ name: 'CleanTest.' + target.ext }, () => Content(render(model.const.Name, auth)))
30
+ })
31
+
32
+
33
+ function phpstr(s: string): string {
34
+ return "'" + String(s).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'"
35
+ }
36
+
37
+
38
+ function render(Name: string, auth: {
39
+ suppressed: boolean, where: string, name: string, basic: boolean
40
+ }): string {
41
+ const lower = Name.toLowerCase()
42
+
43
+ return `<?php
44
+ declare(strict_types=1);
45
+
46
+ // ${Name} SDK clean test
47
+ //
48
+ // The canary sweep: every credential slot holds a distinctive value, every
49
+ // diagnostic feature this SDK ships is switched on with a capturing sink, a
50
+ // real operation runs through every outcome, and every string that leaves
51
+ // the SDK is searched for the canaries and their encoded forms. It also
52
+ // proves its own sensitivity: with clean switched off the canary MUST show.
53
+
54
+ require_once __DIR__ . '/../${lower}_sdk.php';
55
+
56
+ use PHPUnit\\Framework\\TestCase;
57
+
58
+ class CleanTest extends TestCase
59
+ {
60
+ // Generated: the credential's wire placement is fixed when the SDK is
61
+ // built.
62
+ private const AUTH = [
63
+ 'suppressed' => ${auth.suppressed ? 'true' : 'false'},
64
+ 'where' => ${phpstr(auth.where)},
65
+ 'name' => ${phpstr(auth.name)},
66
+ 'basic' => ${auth.basic ? 'true' : 'false'},
67
+ ];
68
+
69
+ private const CANARY = [
70
+ 'apikey' => 'CANARY-APIKEY-k9x2m7q4p1',
71
+ 'secret' => 'CANARY-SECRET-w3e8r5t2y6',
72
+ 'header' => 'CANARY-HEADER-z1x4c7v0b3',
73
+ 'value' => 'CANARY-VALUE-n5m8b2v9c4',
74
+ 'config' => 'CANARY-CONFIG-h6j3k8l2m5',
75
+ ];
76
+
77
+ private const MASK = '[redacted]';
78
+
79
+ // Every form a canary can travel in.
80
+ private static function forms(): array
81
+ {
82
+ $out = [];
83
+ foreach (self::CANARY as $v) {
84
+ $out[] = $v;
85
+ $out[] = base64_encode($v);
86
+ $out[] = rawurlencode($v);
87
+ }
88
+ $out[] = base64_encode(self::CANARY['apikey'] . ':' . self::CANARY['secret']);
89
+ return $out;
90
+ }
91
+
92
+ // Header maps keep the caller's spelling; the assertion should not care.
93
+ private static function header(mixed $map, string $name): mixed
94
+ {
95
+ if (is_object($map)) {
96
+ $map = get_object_vars($map);
97
+ }
98
+ if (!is_array($map)) {
99
+ return null;
100
+ }
101
+ foreach ($map as $k => $v) {
102
+ if (strtolower((string)$k) === strtolower($name)) {
103
+ return $v;
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+
109
+ private static function leaks(string $text): array
110
+ {
111
+ $found = [];
112
+ foreach (self::forms() as $f) {
113
+ if (str_contains($text, $f)) {
114
+ $found[] = $f;
115
+ }
116
+ }
117
+ return $found;
118
+ }
119
+
120
+ // Every way a caller renders a value: json and print_r for all of them,
121
+ // var_export where it walks the whole graph (a record, an error), and
122
+ // the error's own message and string form.
123
+ public static function surfaces(string $name, mixed $val): array
124
+ {
125
+ // Xdebug's develop mode writes every frame's arguments onto the
126
+ // exception at the throw; that is a debugger's view, like err.ctx.
127
+ for ($e = $val instanceof \\Throwable ? $val : null; null !== $e; $e = $e->getPrevious()) {
128
+ if (property_exists($e, 'xdebug_message')) {
129
+ unset($e->xdebug_message);
130
+ }
131
+ }
132
+
133
+ $out = [];
134
+ $push = function (string $kind, callable $fn) use (&$out, $name): void {
135
+ try {
136
+ $text = $fn();
137
+ if (is_string($text)) {
138
+ $out[] = ['name' => $name . ':' . $kind, 'text' => $text];
139
+ }
140
+ } catch (\\Throwable $_e) {
141
+ // A renderer that refuses the value is not a surface.
142
+ }
143
+ };
144
+ $push('json', fn () => json_encode($val, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
145
+ $push('print_r', fn () => print_r($val, true));
146
+ if (is_array($val) || $val instanceof \\Throwable) {
147
+ $push('var_export', fn () => var_export($val, true));
148
+ }
149
+ if ($val instanceof \\Throwable) {
150
+ $push('message', fn () => $val->getMessage());
151
+ $push('string', fn () => (string)$val);
152
+ }
153
+ return $out;
154
+ }
155
+
156
+ private static function response(int $status, mixed $data, array $headers = []): array
157
+ {
158
+ $h = ['content-type' => 'application/json'];
159
+ foreach ($headers as $k => $v) {
160
+ $h[strtolower((string)$k)] = $v;
161
+ }
162
+ return [
163
+ 'status' => $status,
164
+ 'statusText' => $status < 400 ? 'OK' : 'ERR',
165
+ 'headers' => $h,
166
+ 'json' => function () use ($data) { return $data; },
167
+ 'body' => json_encode($data),
168
+ ];
169
+ }
170
+
171
+ // Each scenario is a transport answering the [response, err] pair the
172
+ // fetcher contract names.
173
+ private static function scenarios(): array
174
+ {
175
+ return [
176
+ 'ok' => function (string $_url, array $_fetchdef): array {
177
+ return [self::response(200, ['id' => 'i1', 'name' => 'n1'],
178
+ ['x-session-token' => 'RESP-TOKEN-a1b2c3d4e5']), null];
179
+ },
180
+ 'notfound' => function (string $_url, array $_fetchdef): array {
181
+ return [self::response(404, ['error' => 'no such record']), null];
182
+ },
183
+ 'server' => function (string $_url, array $_fetchdef): array {
184
+ return [self::response(500, ['error' => 'boom']), null];
185
+ },
186
+ // A transport failure quotes the URL, query credential included.
187
+ 'transport' => function (string $url, array $_fetchdef): array {
188
+ return [null, new \\RuntimeException('socket hang up (URL was: "' . $url . '")')];
189
+ },
190
+ // The SDK's own error, its code quoting a registered value.
191
+ 'coded' => function (string $_url, array $_fetchdef): array {
192
+ return [null, new ${Name}Error('denied_' . self::CANARY['apikey'], 'coded failure')];
193
+ },
194
+ // A body that is not JSON: the fetcher answers no parsed body.
195
+ 'notjson' => function (string $_url, array $_fetchdef): array {
196
+ return [[
197
+ 'status' => 200,
198
+ 'statusText' => 'OK',
199
+ 'headers' => [],
200
+ 'json' => function () { return null; },
201
+ 'body' => '<html>',
202
+ ], null];
203
+ },
204
+ ];
205
+ }
206
+
207
+ // True when this SDK was generated with the named feature.
208
+ private static function has_feature(string $name): bool
209
+ {
210
+ $config = ${Name}Config::shared_config();
211
+ $f = $config['feature'] ?? [];
212
+ return is_array($f) && isset($f[$name]);
213
+ }
214
+
215
+ // Captures the serialised context from inside the pipeline: what a hook
216
+ // author would hand to a logger. It also keeps the operation context,
217
+ // the one place the explain record can be read back from.
218
+ // What the watchers capture, kept out of the SDK's object graph: with
219
+ // clean off, var_export of an error walks into the watcher, and text it
220
+ // held would be rendered again on every later capture.
221
+ public static array $captures = [];
222
+
223
+ private static function capture_feature(\\ArrayObject $sinks): ${Name}BaseFeature
224
+ {
225
+ $key = count(self::$captures);
226
+ self::$captures[$key] = $sinks;
227
+ return new class ($key) extends ${Name}BaseFeature {
228
+ public mixed $last = null;
229
+
230
+ public function __construct(private int $sinkkey)
231
+ {
232
+ parent::__construct();
233
+ $this->name = 'capture';
234
+ $this->version = '0.0.1';
235
+ $this->active = true;
236
+ }
237
+
238
+ private function take(string $name, mixed $val): void
239
+ {
240
+ $sinks = CleanTest::$captures[$this->sinkkey];
241
+ foreach (CleanTest::surfaces($name, $val) as $s) {
242
+ $sinks[] = $s;
243
+ }
244
+ }
245
+
246
+ public function PrePoint(${Name}Context $ctx): void
247
+ {
248
+ $this->last = $ctx;
249
+ }
250
+
251
+ public function PreRequest(${Name}Context $ctx): void
252
+ {
253
+ $this->take('ctx@PreRequest', $ctx);
254
+ }
255
+
256
+ public function PreResponse(${Name}Context $ctx): void
257
+ {
258
+ $this->take('ctx@PreResponse', $ctx);
259
+ }
260
+
261
+ // The SDK's own error as a hook reads it, which an observability
262
+ // feature logs.
263
+ public function PreUnexpected(${Name}Context $ctx): void
264
+ {
265
+ $this->take('ctx@PreUnexpected', $ctx);
266
+ if ($ctx->ctrl->err instanceof ${Name}Error) {
267
+ $this->take('ctrl.err@PreUnexpected', $ctx->ctrl->err);
268
+ }
269
+ }
270
+ };
271
+ }
272
+
273
+ // A feature that throws from inside the pipeline, quoting the request
274
+ // it saw: an error make_error never handled.
275
+ // Its PreUnexpected variant throws where that hook fires: make_error.
276
+ private static function throw_feature(bool $response = true, bool $unexpected = false): ${Name}BaseFeature
277
+ {
278
+ return new class ($response, $unexpected) extends ${Name}BaseFeature {
279
+ public function __construct(private bool $response, private bool $unexpected)
280
+ {
281
+ parent::__construct();
282
+ $this->name = 'throwhook';
283
+ $this->version = '0.0.1';
284
+ $this->active = true;
285
+ }
286
+
287
+ public function PreResponse(${Name}Context $ctx): void
288
+ {
289
+ if ($this->response) {
290
+ throw new \\RuntimeException('hook saw ' . json_encode($ctx->spec));
291
+ }
292
+ }
293
+
294
+ public function PreUnexpected(${Name}Context $ctx): void
295
+ {
296
+ if ($this->unexpected) {
297
+ throw new \\RuntimeException('hook saw ' . json_encode($ctx->spec));
298
+ }
299
+ }
300
+ };
301
+ }
302
+
303
+ // A feature that throws a foreign exception whose string code, as some
304
+ // drivers set one, quotes a registered value.
305
+ private static function coded_throw_feature(string $failcode): ${Name}BaseFeature
306
+ {
307
+ return new class ($failcode) extends ${Name}BaseFeature {
308
+ public function __construct(private string $failcode)
309
+ {
310
+ parent::__construct();
311
+ $this->name = 'codedhook';
312
+ $this->version = '0.0.1';
313
+ $this->active = true;
314
+ }
315
+
316
+ public function PreResponse(${Name}Context $ctx): void
317
+ {
318
+ throw new class ('coded hook failure', $this->failcode) extends \\RuntimeException {
319
+ public function __construct(string $msg, string $code)
320
+ {
321
+ parent::__construct($msg);
322
+ $this->code = $code;
323
+ }
324
+ };
325
+ }
326
+ };
327
+ }
328
+
329
+ // A feature whose stream fails while the caller iterates it, quoting a
330
+ // credential.
331
+ private static function stream_throw_feature(string $key): ${Name}BaseFeature
332
+ {
333
+ return new class ($key) extends ${Name}BaseFeature {
334
+ public function __construct(private string $key)
335
+ {
336
+ parent::__construct();
337
+ $this->name = 'streamthrow';
338
+ $this->version = '0.0.1';
339
+ $this->active = true;
340
+ }
341
+
342
+ public function PreDone(${Name}Context $ctx): void
343
+ {
344
+ $key = $this->key;
345
+ $ctx->result->stream = function () use ($key): \\Generator {
346
+ throw new \\RuntimeException('stream saw ' . $key);
347
+ yield null;
348
+ };
349
+ }
350
+ };
351
+ }
352
+
353
+ // A stream that succeeds, so the pipeline's terminal step never runs.
354
+ private static function stream_ok_feature(): ${Name}BaseFeature
355
+ {
356
+ return new class () extends ${Name}BaseFeature {
357
+ public function __construct()
358
+ {
359
+ parent::__construct();
360
+ $this->name = 'streamok';
361
+ $this->version = '0.0.1';
362
+ $this->active = true;
363
+ }
364
+
365
+ public function PreDone(${Name}Context $ctx): void
366
+ {
367
+ $data = $ctx->result->resdata;
368
+ $items = is_array($data) && array_is_list($data) ? $data : (null === $data ? [] : [$data]);
369
+ $ctx->result->stream = function () use ($items): \\Generator {
370
+ yield from $items;
371
+ };
372
+ }
373
+ };
374
+ }
375
+
376
+ private static function make_sdk(
377
+ callable $respond, \\ArrayObject $sinks, ?array $cleanopts = null, array $extra = []
378
+ ): array
379
+ {
380
+ $capture = function (string $name) use ($sinks): callable {
381
+ return function (mixed $rec) use ($name, $sinks): void {
382
+ foreach (self::surfaces($name, $rec) as $s) {
383
+ $sinks[] = $s;
384
+ }
385
+ };
386
+ };
387
+
388
+ $feature = [];
389
+ if (self::has_feature('log')) {
390
+ $feature['log'] = ['active' => true, 'logger' => $capture('log')];
391
+ }
392
+ if (self::has_feature('debug')) {
393
+ $feature['debug'] = ['active' => true, 'onEntry' => $capture('debug')];
394
+ }
395
+ if (self::has_feature('audit')) {
396
+ $feature['audit'] = ['active' => true, 'sink' => $capture('audit')];
397
+ }
398
+ if (self::has_feature('telemetry')) {
399
+ $feature['telemetry'] = ['active' => true, 'exporter' => $capture('telemetry')];
400
+ }
401
+ if (self::has_feature('cost')) {
402
+ $feature['cost'] = ['active' => true, 'sink' => $capture('cost')];
403
+ }
404
+ if (self::has_feature('metrics')) {
405
+ $feature['metrics'] = ['active' => true];
406
+ }
407
+ if (self::has_feature('clienttrack')) {
408
+ $feature['clienttrack'] = ['active' => true];
409
+ }
410
+
411
+ $watcher = self::capture_feature($sinks);
412
+
413
+ $opts = [
414
+ 'apikey' => self::CANARY['apikey'],
415
+ 'secret' => self::CANARY['secret'],
416
+ 'headers' => ['X-Custom-Token' => self::CANARY['header']],
417
+ 'clean' => array_merge(['values' => self::CANARY['value']], $cleanopts ?? []),
418
+ 'extend' => array_merge([$watcher], $extra),
419
+ 'utility' => [
420
+ 'fetcher' => function (${Name}Context $_ctx, string $url, array $fetchdef) use ($respond): array {
421
+ return $respond($url, $fetchdef);
422
+ },
423
+ ],
424
+ ];
425
+ if (0 < count($feature)) {
426
+ $opts['feature'] = $feature;
427
+ }
428
+
429
+ return [new ${Name}SDK($opts), $watcher];
430
+ }
431
+
432
+ // The first operation that completes against a plain 200: with no
433
+ // arguments, else with every path parameter its points declare filled
434
+ // in. An entity accessor is a capitalised client method whose result
435
+ // answers get_name(), as the feature corpus runner finds them.
436
+ private static function usable_op(): ?array
437
+ {
438
+ $plain = new ${Name}SDK([
439
+ 'apikey' => self::CANARY['apikey'],
440
+ 'utility' => [
441
+ 'fetcher' => function (${Name}Context $_ctx, string $_url, array $_fetchdef): array {
442
+ return [self::response(200, ['id' => 'i1']), null];
443
+ },
444
+ ],
445
+ ]);
446
+
447
+ $found = [];
448
+ foreach (get_class_methods($plain) as $m) {
449
+ if (!preg_match('/^[A-Z]/', $m)) {
450
+ continue;
451
+ }
452
+ try {
453
+ $ent = $plain->$m();
454
+ } catch (\\Throwable $_e) {
455
+ continue;
456
+ }
457
+ if (!is_object($ent) || !method_exists($ent, 'get_name')) {
458
+ continue;
459
+ }
460
+ $found[$ent->get_name()] = $m;
461
+ }
462
+ ksort($found);
463
+
464
+ $rank = ['list' => 0, 'load' => 1];
465
+ $entities = ${Name}Config::shared_config()['entity'] ?? [];
466
+ foreach ($found as $entname => $accessor) {
467
+ $ent = $plain->$accessor();
468
+ $ops = array_values(array_filter(['list', 'load', 'create', 'update', 'remove'],
469
+ function (string $op) use ($ent): bool {
470
+ return method_exists($ent, $op);
471
+ }));
472
+ usort($ops, function (string $a, string $b) use ($rank): int {
473
+ return ($rank[$a] ?? 2) <=> ($rank[$b] ?? 2);
474
+ });
475
+ foreach ($ops as $op) {
476
+ $filled = [];
477
+ foreach ((array)($entities[$entname]['op'][$op]['points'] ?? []) as $point) {
478
+ foreach ((array)($point['args']['params'] ?? []) as $p) {
479
+ if (is_string($p['name'] ?? null)) {
480
+ $filled[$p['name']] = 'p1';
481
+ }
482
+ }
483
+ }
484
+ foreach ([[], $filled] as $match) {
485
+ try {
486
+ $plain->$accessor()->$op($match, []);
487
+ return ['accessor' => $accessor, 'op' => $op, 'match' => $match];
488
+ } catch (\\Throwable $_e) {
489
+ continue;
490
+ }
491
+ }
492
+ }
493
+ }
494
+ return null;
495
+ }
496
+
497
+ private static function drive(object $sdk, object $watcher, array $target, array $ctrl, \\ArrayObject $sinks): array
498
+ {
499
+ // What the caller passed and keeps; an array, so the call cannot
500
+ // change it, but it is searched like the record the watcher reads.
501
+ $held = $ctrl['explain'] ?? null;
502
+ $out = null;
503
+ $err = null;
504
+ try {
505
+ $accessor = $target['accessor'];
506
+ $op = $target['op'];
507
+ $out = $sdk->$accessor()->$op($target['match'], $ctrl);
508
+ } catch (\\Throwable $e) {
509
+ $err = $e;
510
+ }
511
+
512
+ if (null !== $err) {
513
+ foreach (self::surfaces('error', $err) as $s) {
514
+ $sinks[] = $s;
515
+ }
516
+ }
517
+ if (null !== $out) {
518
+ foreach (self::surfaces('result', $out) as $s) {
519
+ $sinks[] = $s;
520
+ }
521
+ }
522
+
523
+ $explain = null;
524
+ $last = $watcher->last;
525
+ if (null !== $last && is_array($last->ctrl->explain)) {
526
+ $explain = $last->ctrl->explain;
527
+ foreach (self::surfaces('explain', $explain) as $s) {
528
+ $sinks[] = $s;
529
+ }
530
+ }
531
+ if (null !== $held && $held !== $explain) {
532
+ foreach (self::surfaces('explain:held', $held) as $s) {
533
+ $sinks[] = $s;
534
+ }
535
+ }
536
+
537
+ return [$err, $explain];
538
+ }
539
+
540
+ public function test_no_credential_leaves_the_sdk_in_any_form(): void
541
+ {
542
+ // Frameworks turn every notice into an exception (PHPUnit 8 did too);
543
+ // one thrown mid-pipeline must still leave clean.
544
+ set_error_handler(static function (int $no, string $str, string $file, int $line): bool {
545
+ throw new \\ErrorException($str, 0, $no, $file, $line);
546
+ });
547
+ try {
548
+ $this->sweep();
549
+ } finally {
550
+ restore_error_handler();
551
+ }
552
+ }
553
+
554
+ private function sweep(): void
555
+ {
556
+ $target = self::usable_op();
557
+ if (null === $target) {
558
+ $this->markTestSkipped('no operation of this SDK completes against a plain 200; nothing to sweep');
559
+ }
560
+
561
+ $sinks = new \\ArrayObject();
562
+ $errors = [];
563
+ $explains = [];
564
+
565
+ $variants = [
566
+ 'throw' => [],
567
+ 'explain' => ['explain' => ['on' => true]],
568
+ 'nothrow' => ['throw' => false, 'explain' => ['on' => true]],
569
+ ];
570
+
571
+ foreach (self::scenarios() as $sname => $respond) {
572
+ foreach ($variants as $vname => $ctrl) {
573
+ [$sdk, $watcher] = self::make_sdk($respond, $sinks);
574
+ [$err, $explain] = self::drive($sdk, $watcher, $target, $ctrl, $sinks);
575
+ $key = $sname . '/' . $vname;
576
+ if (null !== $err) {
577
+ $errors[$key] = $err;
578
+ }
579
+ if (null !== $explain) {
580
+ $explains[$key] = $explain;
581
+ }
582
+ foreach (self::surfaces('sdk', $sdk) as $s) {
583
+ $sinks[] = $s;
584
+ }
585
+ }
586
+ }
587
+
588
+ // A credential mistyped as a map is rejected by validation, whose
589
+ // message quotes the value it rejected.
590
+ $rejected = null;
591
+ try {
592
+ new ${Name}SDK([
593
+ 'apikey' => ['value' => self::CANARY['apikey']],
594
+ 'clean' => ['values' => self::CANARY['value']],
595
+ ]);
596
+ } catch (\\Throwable $e) {
597
+ $rejected = $e;
598
+ }
599
+ $this->assertNotNull($rejected, 'a credential mistyped as a map should be rejected');
600
+ foreach (self::surfaces('rejected', $rejected) as $s) {
601
+ $sinks[] = $s;
602
+ }
603
+
604
+ // An error a feature hook throws, quoting the request, skips make_error.
605
+ // PreUnexpected fires only in make_error, which the variant throwing
606
+ // there alone reaches through a 404.
607
+ foreach ([['ok', self::throw_feature()], ['ok', self::throw_feature(true, true)],
608
+ ['notfound', self::throw_feature(false, true)]] as [$sname, $hook]) {
609
+ [$hooked, $hwatcher] = self::make_sdk(self::scenarios()[$sname], $sinks, null, [$hook]);
610
+ [$hookerr, $_hexplain] = self::drive($hooked, $hwatcher, $target, ['explain' => ['on' => true]], $sinks);
611
+ $this->assertNotNull($hookerr, 'the throwing hook should fail the operation');
612
+ }
613
+
614
+ // Iterating a stream runs inside the same catch path as the operation,
615
+ // and the explain record is cleaned however it ends. The caller's copy
616
+ // is its own, so the record is read back as the watcher saw it.
617
+ foreach ([['stream', [self::stream_throw_feature(self::CANARY['apikey'])]],
618
+ ['stream-ok', [self::stream_ok_feature()]], ['stream-plain', []]] as [$name, $extra]) {
619
+ [$streamed, $swatcher] = self::make_sdk(self::scenarios()['ok'], $sinks, null, $extra);
620
+ $streamerr = null;
621
+ try {
622
+ $accessor = $target['accessor'];
623
+ foreach ($streamed->$accessor()->stream($target['op'], ['reqmatch' => $target['match']],
624
+ ['ctrl' => ['explain' => ['on' => true]]]) as $_item) {
625
+ }
626
+ } catch (\\Throwable $e) {
627
+ $streamerr = $e;
628
+ }
629
+ $this->assertSame('stream' === $name, null !== $streamerr, $name . ': only the failing stream throws');
630
+ if (null !== $streamerr) {
631
+ foreach (self::surfaces($name, $streamerr) as $s) {
632
+ $sinks[] = $s;
633
+ }
634
+ }
635
+ $explain = $swatcher->last->ctrl->explain ?? [];
636
+ $this->assertGreaterThan(1, count((array)$explain), $name . ': the explain record was not filled');
637
+ foreach (self::surfaces($name . ':explain', $explain) as $s) {
638
+ $sinks[] = $s;
639
+ }
640
+ }
641
+
642
+ // A registered value used as a property name is masked; names that
643
+ // mask alike are all kept.
644
+ $named = ($hooked->get_utility()->clean)($hooked->get_root_ctx(),
645
+ [self::CANARY['header'] => 1, self::CANARY['value'] => 2, 'plain' => 3]);
646
+ $this->assertSame([self::MASK => 1, self::MASK . '#1' => 2, 'plain' => 3], $named);
647
+ foreach (self::surfaces('named', $named) as $s) {
648
+ $sinks[] = $s;
649
+ }
650
+
651
+ // A foreign exception a hook throws, its string code quoting the key.
652
+ [$codedhook, $cwatcher] = self::make_sdk(self::scenarios()['ok'], $sinks, null,
653
+ [self::coded_throw_feature('denied_' . self::CANARY['apikey'])]);
654
+ [$codederr, $_cexplain] = self::drive($codedhook, $cwatcher, $target, [], $sinks);
655
+ $this->assertNotNull($codederr, 'the coded hook should fail the operation');
656
+
657
+ // The generated config's own clean block is read beside the caller's,
658
+ // and is not changed by it.
659
+ $config = ['options' => ['clean' => ['keys' => 'zzsens', 'values' => self::CANARY['config']]]];
660
+ $util = $hooked->get_utility();
661
+ $built = ($util->make_options)(new ${Name}Context([
662
+ 'utility' => $util,
663
+ 'config' => $config,
664
+ 'options' => ['clean' => ['values' => self::CANARY['value']]],
665
+ ], null));
666
+ $cfgctx = new ${Name}Context(['options' => $built], null);
667
+ $seeded = ($util->clean)($cfgctx, 'config ' . self::CANARY['config'] . ' caller ' . self::CANARY['value']);
668
+ $sinks[] = ['name' => 'config-clean', 'text' => (string)$seeded];
669
+ $this->assertSame('config ' . self::MASK . ' caller ' . self::MASK, $seeded);
670
+ $this->assertSame(['my_zzsens' => self::MASK, 'other' => 'y'],
671
+ ($util->clean)($cfgctx, ['my_zzsens' => 'x', 'other' => 'y']));
672
+ $this->assertSame(['keys' => 'zzsens', 'values' => self::CANARY['config']],
673
+ $config['options']['clean']);
674
+
675
+ // With no clean option at all, the schema defaults still apply.
676
+ $respond404 = self::scenarios()['notfound'];
677
+ $bwatcher = self::capture_feature($sinks);
678
+ $bare = new ${Name}SDK([
679
+ 'apikey' => self::CANARY['apikey'],
680
+ 'secret' => self::CANARY['secret'],
681
+ 'headers' => ['X-Custom-Token' => self::CANARY['header']],
682
+ 'extend' => [$bwatcher],
683
+ 'utility' => [
684
+ 'fetcher' => function (${Name}Context $_ctx, string $url, array $fetchdef) use ($respond404): array {
685
+ return $respond404($url, $fetchdef);
686
+ },
687
+ ],
688
+ ]);
689
+ [$bareerr, $_bexplain] = self::drive($bare, $bwatcher, $target, ['explain' => ['on' => true]], $sinks);
690
+ $this->assertNotNull($bareerr, 'the 404 should fail');
691
+
692
+ // A feature's name is not a field name: only the sensitive names
693
+ // inside its settings register. An entity block, of per-entity
694
+ // settings or seeded records keyed by entity name and id, is not read.
695
+ $featured = new ${Name}SDK([
696
+ 'apikey' => self::CANARY['apikey'],
697
+ 'feature' => [
698
+ 'zzsecrets' => ['active' => false, 'kind' => 'PLAINSETTING-q8w2e4r6'],
699
+ 'zzfeat' => ['active' => false, 'apitoken' => 'FEATTOKEN-z9y8x7w6'],
700
+ 'test' => ['active' => false, 'entity' => [
701
+ 'zztoken' => ['ZZTOKEN01' => ['note' => 'PLAINRECORD-t5r3e1w9']]]],
702
+ ],
703
+ 'entity' => ['zztoken' => ['alias' => ['zzkey' => 'PLAINALIAS-m2n4b6v8']]],
704
+ ]);
705
+ $fclean = $featured->get_utility()->clean;
706
+ $fplain = $fclean($featured->get_root_ctx(), 'kind PLAINSETTING-q8w2e4r6');
707
+ $ftoken = $fclean($featured->get_root_ctx(), 'token FEATTOKEN-z9y8x7w6');
708
+ $frecord = $fclean($featured->get_root_ctx(), 'record PLAINRECORD-t5r3e1w9');
709
+ $falias = $fclean($featured->get_root_ctx(), 'alias PLAINALIAS-m2n4b6v8');
710
+
711
+ $leaked = [];
712
+ $excerpt = '';
713
+ foreach ($sinks as $s) {
714
+ $found = self::leaks($s['text']);
715
+ if (0 < count($found)) {
716
+ $leaked[] = $s['name'] . ' [' . implode(', ', $found) . ']';
717
+ if ('' === $excerpt) {
718
+ // Where the first leak sits, so a failure names its path.
719
+ $at = strpos($s['text'], $found[0]);
720
+ $excerpt = "\\n" . $s['name'] . ' near the leak: ' .
721
+ substr($s['text'], max(0, $at - 600), 700);
722
+ }
723
+ }
724
+ }
725
+
726
+ // The one line the generator's compile lane reads.
727
+ fwrite(STDERR, sprintf("clean: swept %d surface(s), %d leak(s)\\n",
728
+ count($sinks), count($leaked)));
729
+
730
+ $this->assertSame([], $leaked, 'credential leaked through: ' . implode('; ', $leaked) . $excerpt);
731
+
732
+ // The positive half: the slot the credential travelled in is masked,
733
+ // and an unregistered token in a response header is masked by name.
734
+ $notfound = $errors['notfound/throw'] ?? null;
735
+ $this->assertInstanceOf(${Name}Error::class, $notfound, 'the 404 scenario must throw');
736
+ $this->assertSame(404, $notfound->status);
737
+ $spec = $notfound->spec;
738
+ if (!self::AUTH['suppressed']) {
739
+ if ('query' === self::AUTH['where']) {
740
+ $this->assertSame(self::MASK,
741
+ self::header(self::header($spec, 'query'), self::AUTH['name']));
742
+ } elseif ('cookie' === self::AUTH['where']) {
743
+ $this->assertStringContainsString(self::MASK,
744
+ (string)self::header(self::header($spec, 'headers'), 'cookie'));
745
+ } else {
746
+ $this->assertStringEndsWith(self::MASK,
747
+ (string)self::header(self::header($spec, 'headers'), self::AUTH['name']));
748
+ }
749
+ }
750
+ $this->assertSame(self::MASK, self::header(self::header($spec, 'headers'), 'x-custom-token'));
751
+
752
+ $coded = $errors['coded/throw'] ?? null;
753
+ $this->assertInstanceOf(${Name}Error::class, $coded, 'the coded scenario must throw');
754
+ $this->assertSame('denied_' . self::MASK, $coded->sdk_code);
755
+ $this->assertSame('denied_' . self::MASK, $codederr->getCode());
756
+
757
+ $this->assertSame('kind PLAINSETTING-q8w2e4r6', $fplain);
758
+ $this->assertSame('token ' . self::MASK, $ftoken);
759
+ $this->assertSame('record PLAINRECORD-t5r3e1w9', $frecord);
760
+ $this->assertSame('alias PLAINALIAS-m2n4b6v8', $falias);
761
+
762
+ $explained = $explains['ok/explain'] ?? [];
763
+ $this->assertNotNull($explained['result'] ?? null, 'the explain record should carry the result');
764
+ $this->assertSame(self::MASK,
765
+ self::header(self::header($explained['result'], 'headers'), 'x-session-token'));
766
+ }
767
+
768
+ public function test_the_sweep_can_see_a_leak_clean_switched_off_shows_the_credential(): void
769
+ {
770
+ $target = self::usable_op();
771
+ if (null === $target) {
772
+ $this->markTestSkipped('no operation of this SDK completes against a plain 200; nothing to sweep');
773
+ }
774
+
775
+ $sinks = new \\ArrayObject();
776
+ [$sdk, $watcher] = self::make_sdk(self::scenarios()['notfound'], $sinks, ['active' => false]);
777
+ [$err, $_explain] = self::drive($sdk, $watcher, $target, [], $sinks);
778
+ $this->assertNotNull($err);
779
+
780
+ // Explaining a failure must not cost it its error.
781
+ $discard = new \\ArrayObject();
782
+ [$esdk, $ewatcher] = self::make_sdk(self::scenarios()['notfound'], $discard, ['active' => false]);
783
+ [$explained, $_eexplain] = self::drive($esdk, $ewatcher, $target, ['explain' => ['on' => true]], $discard);
784
+ $this->assertSame($err->getMessage(), $explained?->getMessage(), 'with clean off, explain lost the error');
785
+
786
+ $leaked = 0;
787
+ foreach ($sinks as $s) {
788
+ if (0 < count(self::leaks($s['text']))) {
789
+ $leaked++;
790
+ }
791
+ }
792
+ $this->assertGreaterThan(0, $leaked, 'with clean off, nothing showed the canary: the sweep is blind');
793
+
794
+ if (!self::AUTH['suppressed']) {
795
+ $text = (string)json_encode($err instanceof ${Name}Error ? $err->spec : null);
796
+ $this->assertTrue(
797
+ str_contains($text, self::CANARY['apikey'])
798
+ || str_contains($text, base64_encode(self::CANARY['apikey'] . ':' . self::CANARY['secret'])),
799
+ 'the raw spec should carry the credential when clean is off');
800
+ }
801
+ }
802
+ }
803
+ `
804
+ }
805
+
806
+
807
+ export {
808
+ TestClean
809
+ }