@voxgig/sdkgen 4.32.1 → 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 (411) 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/feature/audit/AuditFeature.js +2 -2
  220. package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
  221. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
  222. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
  223. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
  224. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
  225. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
  226. package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
  227. package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
  228. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
  229. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
  230. package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
  231. package/project/.sdk/tm/js/test/feature/harness.js +11 -1
  232. package/project/.sdk/tm/js/test/feature.test.js +9 -2
  233. package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
  234. package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
  235. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  236. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
  237. package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
  238. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
  239. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
  240. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
  241. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
  242. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
  243. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
  244. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
  245. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
  246. package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
  247. package/project/.sdk/tm/lua/core/context.lua +43 -0
  248. package/project/.sdk/tm/lua/core/error.lua +36 -1
  249. package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
  250. package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
  251. package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
  252. package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
  253. package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
  254. package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
  255. package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
  256. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
  257. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
  258. package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
  259. package/project/.sdk/tm/lua/utility/clean.lua +426 -2
  260. package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
  261. package/project/.sdk/tm/lua/utility/done.lua +1 -7
  262. package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
  263. package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
  264. package/project/.sdk/tm/lua/utility/register.lua +4 -1
  265. package/project/.sdk/tm/ocaml/Makefile +5 -1
  266. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
  267. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
  268. package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
  269. package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
  270. package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
  271. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
  272. package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
  273. package/project/.sdk/tm/perl/core/context.pm +27 -0
  274. package/project/.sdk/tm/perl/core/error.pm +52 -5
  275. package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
  276. package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
  277. package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
  278. package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
  279. package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
  280. package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
  281. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
  282. package/project/.sdk/tm/perl/t/feature.t +4 -2
  283. package/project/.sdk/tm/perl/utility/clean.pm +345 -1
  284. package/project/.sdk/tm/perl/utility/done.pm +24 -6
  285. package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
  286. package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
  287. package/project/.sdk/tm/php/core/Context.php +24 -1
  288. package/project/.sdk/tm/php/core/Error.php +34 -3
  289. package/project/.sdk/tm/php/core/UtilityType.php +4 -0
  290. package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
  291. package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
  292. package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
  293. package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
  294. package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
  295. package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
  296. package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
  297. package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
  298. package/project/.sdk/tm/php/utility/Clean.php +438 -2
  299. package/project/.sdk/tm/php/utility/Done.php +14 -7
  300. package/project/.sdk/tm/php/utility/MakeError.php +9 -7
  301. package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
  302. package/project/.sdk/tm/php/utility/Register.php +2 -0
  303. package/project/.sdk/tm/py/pkg/core/context.py +17 -0
  304. package/project/.sdk/tm/py/pkg/core/error.py +42 -1
  305. package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
  306. package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
  307. package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
  308. package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
  309. package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
  310. package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
  311. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
  312. package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
  313. package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
  314. package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
  315. package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
  316. package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
  317. package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
  318. package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
  319. package/project/.sdk/tm/py/test/feature_harness.py +4 -0
  320. package/project/.sdk/tm/py/test/test_feature.py +2 -2
  321. package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
  322. package/project/.sdk/tm/rb/core/context.rb +28 -0
  323. package/project/.sdk/tm/rb/core/error.rb +30 -0
  324. package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
  325. package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
  326. package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
  327. package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
  328. package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
  329. package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
  330. package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
  331. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
  332. package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
  333. package/project/.sdk/tm/rb/utility/clean.rb +312 -1
  334. package/project/.sdk/tm/rb/utility/done.rb +15 -5
  335. package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
  336. package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
  337. package/project/.sdk/tm/rb/utility/register.rb +2 -0
  338. package/project/.sdk/tm/rust/core/context.rs +55 -0
  339. package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
  340. package/project/.sdk/tm/rust/feature/audit.rs +2 -0
  341. package/project/.sdk/tm/rust/feature/cost.rs +3 -2
  342. package/project/.sdk/tm/rust/feature/debug.rs +16 -16
  343. package/project/.sdk/tm/rust/feature/log.rs +42 -7
  344. package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
  345. package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
  346. package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
  347. package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
  348. package/project/.sdk/tm/rust/utility/clean.rs +446 -5
  349. package/project/.sdk/tm/rust/utility/done.rs +22 -12
  350. package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
  351. package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
  352. package/project/.sdk/tm/scala/Makefile +3 -1
  353. package/project/.sdk/tm/scala/core/Context.scala +16 -0
  354. package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
  355. package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
  356. package/project/.sdk/tm/scala/core/Types.scala +3 -0
  357. package/project/.sdk/tm/scala/core/Utility.scala +2 -0
  358. package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
  359. package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
  360. package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
  361. package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
  362. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
  363. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
  364. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
  365. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
  366. package/project/.sdk/tm/scala/utility/Make.scala +63 -20
  367. package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
  368. package/project/.sdk/tm/scala/utility/Register.scala +1 -0
  369. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
  370. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
  371. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
  372. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
  373. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
  374. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
  375. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
  376. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
  377. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
  378. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
  379. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
  380. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
  381. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
  382. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
  383. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
  384. package/project/.sdk/tm/ts/src/Context.ts +5 -1
  385. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
  386. package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
  387. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
  388. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
  389. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
  390. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
  391. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
  392. package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
  393. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
  394. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
  395. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
  396. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
  397. package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
  398. package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
  399. package/project/.sdk/tm/zig/core/context.zig +34 -0
  400. package/project/.sdk/tm/zig/core/error.zig +22 -1
  401. package/project/.sdk/tm/zig/core/utility.zig +403 -39
  402. package/project/.sdk/tm/zig/feature/audit.zig +4 -2
  403. package/project/.sdk/tm/zig/feature/cost.zig +3 -2
  404. package/project/.sdk/tm/zig/feature/debug.zig +20 -25
  405. package/project/.sdk/tm/zig/feature/log.zig +3 -1
  406. package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
  407. package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
  408. package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
  409. package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
  410. package/project/sdkgen-package.json +1 -1
  411. package/src/helpers/naming.ts +1 -1
@@ -0,0 +1,608 @@
1
+
2
+ import {
3
+ Content,
4
+ File,
5
+ cmp,
6
+ isAuthSuppressed,
7
+ isHttpBasicAuth,
8
+ resolveAuthIn,
9
+ resolveAuthName,
10
+ } from '@voxgig/sdkgen'
11
+
12
+
13
+ import type { Model } from '@voxgig/apidef'
14
+
15
+
16
+ // The canary sweep (test/clean.test.ts in the ts reference): canaries in
17
+ // every credential slot, every diagnostic feature on with a capturing sink,
18
+ // a real operation through every outcome, every string that leaves searched
19
+ // for the canaries and their encoded forms, and the negative control. A
20
+ // scala-cli main of its own, named in the Makefile's test target.
21
+ const TestClean = cmp(function TestClean(props: any) {
22
+ const model: Model = props.ctx$.model
23
+ const target = props.target
24
+ const scalapackage: string = props.scalapackage
25
+
26
+ const SDK = model.const.Name + 'SDK'
27
+
28
+ const auth = {
29
+ suppressed: isAuthSuppressed(model),
30
+ where: resolveAuthIn(model),
31
+ name: 'header' === resolveAuthIn(model)
32
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
33
+ basic: isHttpBasicAuth(model),
34
+ }
35
+
36
+ File({ name: 'SdkCleanTestMain.' + target.ext }, () => Content(render(scalapackage, SDK, auth)))
37
+ })
38
+
39
+
40
+ type AuthSpec = { suppressed: boolean, where: string, name: string, basic: boolean }
41
+
42
+
43
+ function render(scalapackage: string, SDK: string, auth: AuthSpec): string {
44
+ return `// The canary sweep: every credential slot holds a distinctive value, every
45
+ // diagnostic feature this SDK ships is switched on with a capturing sink, a
46
+ // real operation runs through every outcome, and every string that leaves
47
+ // the SDK is searched for the canaries and their encoded forms. It also
48
+ // proves its own sensitivity: with clean switched off the canary MUST show.
49
+ // Run: scala-cli run . --main-class SdkCleanTestMain
50
+
51
+ import java.io.{PrintWriter, StringWriter}
52
+ import java.lang.reflect.{Method, Modifier}
53
+ import java.net.URLEncoder
54
+ import java.nio.charset.StandardCharsets
55
+ import java.util.{ArrayList, Base64, LinkedHashMap, List => JList, Map => JMap}
56
+ import java.util.function.{Consumer, Supplier}
57
+ import java.util.logging.{Handler, Level, LogRecord, Logger}
58
+
59
+ import ${scalapackage}.core.{Config, Context, Helpers, Result, SdkEntity, SdkError, Spec, ${SDK}}
60
+ import ${scalapackage}.feature.BaseFeature
61
+ import ${scalapackage}.utility.struct.Struct
62
+
63
+ object SdkCleanTestMain {
64
+
65
+ // Generated: the credential's wire placement is fixed when the SDK is built.
66
+ private val AUTH_SUPPRESSED = ${auth.suppressed}
67
+ private val AUTH_WHERE = "${scalastr(auth.where)}"
68
+ private val AUTH_NAME = "${scalastr(auth.name)}"
69
+
70
+ private val CANARY_APIKEY = "CANARY-APIKEY-k9x2m7q4p1"
71
+ private val CANARY_SECRET = "CANARY-SECRET-w3e8r5t2y6"
72
+ private val CANARY_HEADER = "CANARY-HEADER-z1x4c7v0b3"
73
+ private val CANARY_VALUE = "CANARY-VALUE-n5m8b2v9c4"
74
+
75
+ private val MASK = "[redacted]"
76
+
77
+ private def b64(s: String): String =
78
+ Base64.getEncoder.encodeToString(s.getBytes(StandardCharsets.UTF_8))
79
+
80
+ // Every form a canary can travel in.
81
+ private val FORMS: List[String] =
82
+ List(CANARY_APIKEY, CANARY_SECRET, CANARY_HEADER, CANARY_VALUE)
83
+ .flatMap(v => List(v, b64(v), URLEncoder.encode(v, StandardCharsets.UTF_8))) :+
84
+ b64(CANARY_APIKEY + ":" + CANARY_SECRET)
85
+
86
+ final class Sink(val name: String, val text: String)
87
+
88
+ private def om(kv: (String, Object)*): JMap[String, Object] = SdkTestSupport.om(kv*)
89
+ private def I(n: Int): java.lang.Integer = java.lang.Integer.valueOf(n)
90
+ private def B(b: Boolean): java.lang.Boolean = java.lang.Boolean.valueOf(b)
91
+
92
+ private def hasFeature(name: String): Boolean = {
93
+ val fm = Helpers.toMapAny(Config.sharedConfig().get("feature"))
94
+ fm != null && fm.get(name) != null
95
+ }
96
+
97
+ // Header maps keep the caller's spelling; the assertion should not care.
98
+ private def header(map: Object, name: String): Object = {
99
+ val m = Helpers.toMapAny(map)
100
+ if (m == null) return null
101
+ val it = m.entrySet().iterator()
102
+ while (it.hasNext) {
103
+ val e = it.next()
104
+ if (e.getKey.toLowerCase == name.toLowerCase) return e.getValue
105
+ }
106
+ null
107
+ }
108
+
109
+ private def leaks(text: String): List[String] = FORMS.filter(f => text.contains(f))
110
+
111
+ // The SDK's own objects print their data, not a class name, so a raw spec
112
+ // handed back with clean off shows what it holds.
113
+ private def plain(v: Object): Object = v match {
114
+ case s: Spec => om("method" -> s.method, "url" -> s.url, "path" -> s.path,
115
+ "headers" -> s.headers, "query" -> s.query, "body" -> s.body)
116
+ case r: Result => om("status" -> I(r.status), "headers" -> r.headers,
117
+ "body" -> r.body, "resdata" -> r.resdata)
118
+ case e: SdkEntity => e.data()
119
+ case _ => v
120
+ }
121
+
122
+ private def stack(err: Throwable): String = {
123
+ val sw = new StringWriter()
124
+ err.printStackTrace(new PrintWriter(sw))
125
+ sw.toString
126
+ }
127
+
128
+ private def surfaces(name: String, v: Object): List[Sink] = {
129
+ val out = new ArrayList[Sink]()
130
+ def push(kind: String)(fn: => String): Unit =
131
+ try out.add(new Sink(name + ":" + kind, fn))
132
+ catch { case _: Throwable => }
133
+ push("json") { Struct.jsonify(plain(v)) }
134
+ push("string") { String.valueOf(v) }
135
+ v match {
136
+ case t: Throwable =>
137
+ push("message") { if (t.getMessage == null) "" else t.getMessage }
138
+ push("stack") { stack(t) }
139
+ case _ =>
140
+ }
141
+ v match {
142
+ case e: SdkError =>
143
+ push("map") { Struct.jsonify(e.toMap()) }
144
+ push("spec") { Struct.jsonify(plain(e.spec)) }
145
+ push("result") { Struct.jsonify(plain(e.result)) }
146
+ case _ =>
147
+ }
148
+ v match {
149
+ case c: Context => push("record") { Struct.jsonify(c.toMap()) }
150
+ case _ =>
151
+ }
152
+ out.toArray(new Array[Sink](0)).toList
153
+ }
154
+
155
+ private def collect(sinks: ArrayList[Sink], name: String, v: Object): Unit =
156
+ surfaces(name, v).foreach(s => sinks.add(s))
157
+
158
+ // Captures the serialised context from inside the pipeline: what a hook
159
+ // author would hand to a logger.
160
+ final class CaptureFeature(sinks: ArrayList[Sink]) extends BaseFeature("capture", "0.0.1", true) {
161
+ override def preRequest(ctx: Context): Unit = collect(sinks, "ctx@PreRequest", ctx)
162
+ override def preResponse(ctx: Context): Unit = collect(sinks, "ctx@PreResponse", ctx)
163
+ override def preUnexpected(ctx: Context): Unit = collect(sinks, "ctx@PreUnexpected", ctx)
164
+ }
165
+
166
+ // A feature that throws from inside the pipeline, quoting the request it
167
+ // saw: a plain Exception, which is not a RuntimeException. makeError fires
168
+ // PreUnexpected, so what the unexpected variant throws there escapes it.
169
+ final class ThrowFeature(unexpected: Boolean) extends BaseFeature("throwhook", "0.0.1", true) {
170
+ private def saw(ctx: Context): Exception = new Exception("hook saw " + Struct.jsonify(plain(ctx.spec)))
171
+ override def preResponse(ctx: Context): Unit = throw saw(ctx)
172
+ override def preUnexpected(ctx: Context): Unit = if (unexpected) throw saw(ctx)
173
+ }
174
+
175
+ // A stream that fails while the caller iterates it, quoting a credential.
176
+ final class StreamThrowFeature extends BaseFeature("streamthrow", "0.0.1", true) {
177
+ override def preDone(ctx: Context): Unit = {
178
+ val failing: Supplier[java.util.Iterator[Object]] = () => new java.util.Iterator[Object] {
179
+ override def hasNext: Boolean = throw new RuntimeException("stream saw " + CANARY_APIKEY)
180
+ override def next(): Object = throw new NoSuchElementException()
181
+ }
182
+ ctx.result.stream = failing
183
+ }
184
+ }
185
+
186
+ // A stream that succeeds, yielding the result's items.
187
+ final class StreamOkFeature extends BaseFeature("streamok", "0.0.1", true) {
188
+ override def preDone(ctx: Context): Unit = {
189
+ val items = new ArrayList[Object]()
190
+ ctx.result.resdata match {
191
+ case l: JList[_] => l.forEach(item => items.add(item.asInstanceOf[Object]))
192
+ case null =>
193
+ case other => items.add(other)
194
+ }
195
+ val ok: Supplier[java.util.Iterator[Object]] = () => items.iterator()
196
+ ctx.result.stream = ok
197
+ }
198
+ }
199
+
200
+ final class Scenario(val name: String, val respond: (String, JMap[String, Object]) => Object)
201
+
202
+ private def response(status: Int, data: Object, headers: JMap[String, Object]): JMap[String, Object] = {
203
+ val h = new LinkedHashMap[String, Object]()
204
+ h.put("content-type", "application/json")
205
+ if (headers != null) h.putAll(headers)
206
+ val js: Supplier[Object] = () => data
207
+ val out = new LinkedHashMap[String, Object]()
208
+ out.put("status", I(status))
209
+ out.put("statusText", if (status < 400) "OK" else "ERR")
210
+ out.put("headers", h)
211
+ out.put("json", js)
212
+ out.put("body", Struct.jsonify(data))
213
+ out
214
+ }
215
+
216
+ private val SCENARIOS: List[Scenario] = List(
217
+ new Scenario("ok", (_, _) => response(200, om("id" -> "i1", "name" -> "n1"),
218
+ om("x-session-token" -> "RESP-TOKEN-a1b2c3d4e5"))),
219
+ new Scenario("notfound", (_, _) => response(404, om("error" -> "no such record"), null)),
220
+ new Scenario("server", (_, _) => response(500, om("error" -> "boom"), null)),
221
+ new Scenario("transport", (url, _) =>
222
+ throw new RuntimeException("socket hang up (URL was: \\"" + url + "\\")")),
223
+ new Scenario("notjson", (_, _) => {
224
+ val js: Supplier[Object] = () => null
225
+ om("status" -> I(200), "statusText" -> "OK",
226
+ "headers" -> new LinkedHashMap[String, Object](), "json" -> js, "body" -> "<html>")
227
+ }),
228
+ )
229
+
230
+ private def makeSdk(scenario: Scenario, sinks: ArrayList[Sink], cleanopts: JMap[String, Object],
231
+ extra: BaseFeature = null): ${SDK} = {
232
+ def capture(name: String): Consumer[Object] = (rec: Object) => collect(sinks, name, rec)
233
+
234
+ val feature = new LinkedHashMap[String, Object]()
235
+ if (hasFeature("log")) {
236
+ val logger = Logger.getLogger("clean-sweep-" + System.nanoTime())
237
+ logger.setUseParentHandlers(false)
238
+ logger.setLevel(Level.ALL)
239
+ logger.addHandler(new Handler() {
240
+ override def publish(record: LogRecord): Unit = collect(sinks, "log", record.getMessage)
241
+ override def flush(): Unit = {}
242
+ override def close(): Unit = {}
243
+ })
244
+ feature.put("log", om("active" -> B(true), "logger" -> logger))
245
+ }
246
+ if (hasFeature("debug")) feature.put("debug", om("active" -> B(true), "onEntry" -> capture("debug")))
247
+ if (hasFeature("audit")) feature.put("audit", om("active" -> B(true), "sink" -> capture("audit")))
248
+ if (hasFeature("telemetry")) feature.put("telemetry", om("active" -> B(true), "exporter" -> capture("telemetry")))
249
+ if (hasFeature("cost")) feature.put("cost", om("active" -> B(true), "sink" -> capture("cost")))
250
+ if (hasFeature("metrics")) feature.put("metrics", om("active" -> B(true)))
251
+ if (hasFeature("clienttrack")) feature.put("clienttrack", om("active" -> B(true)))
252
+
253
+ val clean = new LinkedHashMap[String, Object]()
254
+ clean.put("values", CANARY_VALUE)
255
+ if (cleanopts != null) clean.putAll(cleanopts)
256
+
257
+ val fetcher: (Context, String, JMap[String, Object]) => Object =
258
+ (_, url, fetchdef) => scenario.respond(url, fetchdef)
259
+
260
+ val opts = new LinkedHashMap[String, Object]()
261
+ opts.put("apikey", CANARY_APIKEY)
262
+ opts.put("secret", CANARY_SECRET)
263
+ opts.put("headers", om("X-Custom-Token" -> CANARY_HEADER))
264
+ opts.put("clean", clean)
265
+ opts.put("feature", feature)
266
+ val extend = SdkTestSupport.jl(new CaptureFeature(sinks))
267
+ if (extra != null) extend.add(extra)
268
+ opts.put("extend", extend)
269
+ opts.put("utility", om("fetcher" -> fetcher))
270
+ new ${SDK}(opts)
271
+ }
272
+
273
+ final class Target(val accessor: Method, val op: String, val matchArgs: JMap[String, Object])
274
+
275
+ private def accessors(): List[Method] =
276
+ classOf[${SDK}].getMethods.toList
277
+ .filter(m => classOf[SdkEntity].isAssignableFrom(m.getReturnType) &&
278
+ m.getParameterCount == 1 && Modifier.isPublic(m.getModifiers))
279
+ .sortBy(m => m.getName)
280
+
281
+ private def entityOf(sdk: ${SDK}, m: Method): SdkEntity =
282
+ try m.invoke(sdk, Array[Object](null)*) match {
283
+ case e: SdkEntity => e
284
+ case _ => null
285
+ }
286
+ catch { case _: Throwable => null }
287
+
288
+ private def call(ent: SdkEntity, op: String, matchArgs: JMap[String, Object],
289
+ ctrl: JMap[String, Object]): Object = {
290
+ val args = new LinkedHashMap[String, Object](matchArgs)
291
+ op match {
292
+ case "list" => ent.list(args, ctrl)
293
+ case "load" => ent.load(args, ctrl)
294
+ case "create" => ent.create(args, ctrl)
295
+ case "update" => ent.update(args, ctrl)
296
+ case "remove" => ent.remove(args, ctrl)
297
+ case _ => throw new IllegalArgumentException("no such op: " + op)
298
+ }
299
+ }
300
+
301
+ // Every path parameter an op's points declare, filled in.
302
+ private def filled(opdef: JMap[String, Object]): JMap[String, Object] = {
303
+ val out = new LinkedHashMap[String, Object]()
304
+ Struct.getprop(opdef, "points") match {
305
+ case points: JList[_] =>
306
+ points.forEach { point =>
307
+ Struct.getpath(point, java.util.List.of("args", "params")) match {
308
+ case ps: JList[_] =>
309
+ ps.forEach { p =>
310
+ Struct.getprop(p, "name") match { case n: String => out.put(n, "p1"); case _ => }
311
+ }
312
+ case _ =>
313
+ }
314
+ }
315
+ case _ =>
316
+ }
317
+ out
318
+ }
319
+
320
+ // The first operation that completes against a plain 200: with no
321
+ // arguments, else with every path parameter its points declare filled in.
322
+ private def usableOp(): Target = {
323
+ val plainFetch: (Context, String, JMap[String, Object]) => Object =
324
+ (_, _, _) => response(200, om("id" -> "i1"), null)
325
+ val plain = new ${SDK}(om("apikey" -> CANARY_APIKEY, "utility" -> om("fetcher" -> plainFetch)))
326
+ val entities = Helpers.toMapAny(Config.sharedConfig().get("entity"))
327
+ if (entities == null) return null
328
+ val rank = Map("list" -> 0, "load" -> 1)
329
+ var found: Target = null
330
+ val mit = accessors().iterator
331
+ while (found == null && mit.hasNext) {
332
+ val m = mit.next()
333
+ val inst = entityOf(plain, m)
334
+ val ecfg = if (inst == null) null else Helpers.toMapAny(entities.get(inst.getName()))
335
+ val opmap = if (ecfg == null) null else Helpers.toMapAny(ecfg.get("op"))
336
+ val ops =
337
+ if (opmap == null) Nil
338
+ else opmap.keySet().toArray.toList.map(k => String.valueOf(k)).sortBy(op => rank.getOrElse(op, 2))
339
+ val oit = ops.iterator
340
+ while (found == null && oit.hasNext) {
341
+ val op = oit.next()
342
+ val matches = List(new LinkedHashMap[String, Object](), filled(Helpers.toMapAny(opmap.get(op))))
343
+ val kit = matches.iterator
344
+ while (found == null && kit.hasNext) {
345
+ val matchArgs = kit.next()
346
+ try {
347
+ call(entityOf(plain, m), op, matchArgs, null)
348
+ found = new Target(m, op, matchArgs)
349
+ }
350
+ catch { case _: Throwable => }
351
+ }
352
+ }
353
+ }
354
+ found
355
+ }
356
+
357
+ private val NO_OP = "no operation of this SDK completes against a plain 200; nothing to sweep"
358
+
359
+ private def drive(sdk: ${SDK}, target: Target, ctrl: JMap[String, Object], sinks: ArrayList[Sink]): Throwable = {
360
+ // A caller may keep the record it passed rather than read ctrl's entry.
361
+ val held = if (ctrl == null) null else ctrl.get("explain")
362
+ var out: Object = null
363
+ var err: Throwable = null
364
+ try out = call(entityOf(sdk, target.accessor), target.op, target.matchArgs, ctrl)
365
+ catch { case e: Throwable => err = e }
366
+ if (err != null) collect(sinks, "error", err)
367
+ if (out != null) collect(sinks, "result", out)
368
+ val explain = if (ctrl == null) null else ctrl.get("explain")
369
+ if (explain != null) collect(sinks, "explain", explain)
370
+ if (held != null && !(held eq explain)) collect(sinks, "explain:held", held)
371
+ err
372
+ }
373
+
374
+ private def sweep(rep: SdkTestReport): Unit = {
375
+ val target = usableOp()
376
+ if (target == null) {
377
+ println("clean: skipped: " + NO_OP)
378
+ return
379
+ }
380
+
381
+ val sinks = new ArrayList[Sink]()
382
+ val errors = new LinkedHashMap[String, Throwable]()
383
+ val explains = new LinkedHashMap[String, JMap[String, Object]]()
384
+
385
+ for (scenario <- SCENARIOS) {
386
+ for (variant <- List("throw", "explain", "nothrow")) {
387
+ val sdk = makeSdk(scenario, sinks, null)
388
+ val ctrl: JMap[String, Object] = variant match {
389
+ case "throw" => null
390
+ case "explain" => om("explain" -> new LinkedHashMap[String, Object]())
391
+ case _ => om("throw" -> B(false), "explain" -> new LinkedHashMap[String, Object]())
392
+ }
393
+ val err = drive(sdk, target, ctrl, sinks)
394
+ val key = scenario.name + "/" + variant
395
+ if (err != null) errors.put(key, err)
396
+ val explain = if (ctrl == null) null else Helpers.toMapAny(ctrl.get("explain"))
397
+ if (explain != null) explains.put(key, explain)
398
+ collect(sinks, "sdk", sdk)
399
+ }
400
+ }
401
+
402
+ // A credential mistyped as a map. Validation here collects its errors
403
+ // rather than throwing, so there is no rejection to sweep: sweep the
404
+ // client it built, an operation it runs, and a message quoting the value.
405
+ val fetch404: (Context, String, JMap[String, Object]) => Object =
406
+ (_, url, fetchdef) => SCENARIOS(1).respond(url, fetchdef)
407
+ val mistyped = new ${SDK}(om("apikey" -> om("value" -> CANARY_APIKEY),
408
+ "clean" -> om("values" -> CANARY_VALUE), "utility" -> om("fetcher" -> fetch404)))
409
+ collect(sinks, "mistyped", mistyped)
410
+ drive(mistyped, target, null, sinks)
411
+ collect(sinks, "mistyped:quoted",
412
+ mistyped.getUtility().clean(mistyped.getRootCtx(), "found map: " + CANARY_APIKEY))
413
+
414
+ // An exception a feature hook throws, quoting the request, skips makeError.
415
+ for (unexpected <- List(false, true)) {
416
+ val hooked = makeSdk(SCENARIOS.head, sinks, null, new ThrowFeature(unexpected))
417
+ val hookerr = drive(hooked, target, om("explain" -> new LinkedHashMap[String, Object]()), sinks)
418
+ rep.check("clean.hook-throws", hookerr != null, "the throwing hook should fail the operation")
419
+ }
420
+
421
+ // Iterating a stream runs inside the same catch path as the operation,
422
+ // and the explain record the caller passed is cleaned however it ends.
423
+ for ((name, extra) <- List[(String, BaseFeature)](
424
+ ("stream", new StreamThrowFeature()), ("stream-ok", new StreamOkFeature()), ("stream-plain", null))) {
425
+ val streaming = entityOf(makeSdk(SCENARIOS.head, sinks, null, extra), target.accessor)
426
+ val explain = new LinkedHashMap[String, Object]()
427
+ var streamerr: Throwable = null
428
+ try streaming.stream(target.op, om("reqmatch" -> new LinkedHashMap[String, Object](target.matchArgs)),
429
+ om("ctrl" -> om("explain" -> explain))).foreach(_ => ())
430
+ catch { case e: Throwable => streamerr = e }
431
+ rep.check("clean." + name + ".throws", ("stream" == name) == (streamerr != null),
432
+ name + ": only the failing stream throws")
433
+ if (streamerr != null) collect(sinks, name, streamerr)
434
+ rep.check("clean." + name + ".explain", !explain.isEmpty, name + ": the explain record was not filled")
435
+ collect(sinks, name + ":explain", explain)
436
+ }
437
+
438
+ // The raw path returns its failure rather than throwing it.
439
+ val raw = makeSdk(SCENARIOS(3), sinks, null).direct(om("path" -> "raw"))
440
+ rep.check("clean.direct-fails", java.lang.Boolean.FALSE == raw.get("ok") && raw.get("err") != null,
441
+ "a transport failure should fail direct()")
442
+ collect(sinks, "direct", raw.get("err"))
443
+
444
+ // A registered value used as a map key is masked; keys that mask alike
445
+ // are kept apart.
446
+ val probe = makeSdk(SCENARIOS.head, sinks, null)
447
+ val named = Helpers.toMapAny(probe.getUtility().clean(probe.getRootCtx(),
448
+ om(CANARY_VALUE -> I(1), CANARY_HEADER -> I(2), "plain" -> I(3))))
449
+ collect(sinks, "named", named)
450
+
451
+ // An error's code is cleaned like its message.
452
+ val coded = probe.getUtility().clean(probe.getRootCtx(), new SdkError("code_" + CANARY_VALUE, "coded", null))
453
+ collect(sinks, "coded", coded)
454
+
455
+ val all = sinks.toArray(new Array[Sink](0)).toList
456
+ val leaked = all.map(s => (s.name, leaks(s.text))).filter(l => l._2.nonEmpty)
457
+
458
+ println("clean: swept " + all.size + " surface(s), " + leaked.size + " leak(s)")
459
+
460
+ rep.check("clean.no-leak", leaked.isEmpty, "credential leaked through: " +
461
+ leaked.map(l => l._1 + " [" + l._2.mkString(", ") + "]").mkString("; "))
462
+
463
+ // The positive half: the slot the credential travelled in is masked,
464
+ // and an unregistered token in a response header is masked by name.
465
+ val notfound = errors.get("notfound/throw")
466
+ rep.check("clean.404-throws", notfound != null, "the 404 scenario must throw")
467
+ notfound match {
468
+ case nf: SdkError =>
469
+ rep.eqI("clean.404-status", 404, nf.status)
470
+ val specm = Helpers.toMapAny(nf.spec)
471
+ val spec = if (specm == null) new LinkedHashMap[String, Object]() else specm
472
+ if (!AUTH_SUPPRESSED) {
473
+ if ("query" == AUTH_WHERE) {
474
+ rep.eq("clean.query-masked", MASK, header(spec.get("query"), AUTH_NAME))
475
+ } else if ("cookie" == AUTH_WHERE) {
476
+ val cookie = String.valueOf(header(spec.get("headers"), "cookie"))
477
+ rep.check("clean.cookie-masked", cookie.contains(MASK), "cookie: " + cookie)
478
+ } else {
479
+ val cred = String.valueOf(header(spec.get("headers"), AUTH_NAME))
480
+ rep.check("clean.header-masked", cred.endsWith(MASK), AUTH_NAME + ": " + cred)
481
+ }
482
+ }
483
+ rep.eq("clean.custom-header-masked", MASK, header(spec.get("headers"), "x-custom-token"))
484
+ case other =>
485
+ rep.fail("clean.404-sdkerror", "the 404 scenario should throw an SdkError, got " + other)
486
+ }
487
+
488
+ val explained = explains.get("ok/explain")
489
+ val result = if (explained == null) null else Helpers.toMapAny(explained.get("result"))
490
+ rep.check("clean.explain-result", result != null, "the explain record should carry the result")
491
+ if (result != null) {
492
+ rep.eq("clean.response-header-masked", MASK, header(result.get("headers"), "x-session-token"))
493
+ }
494
+
495
+ rep.eq("clean.map-keys", om(MASK -> I(1), (MASK + "#1") -> I(2), "plain" -> I(3)), named)
496
+ coded match {
497
+ case e: SdkError => rep.eq("clean.code-masked", "code_" + MASK, e.code)
498
+ case other => rep.fail("clean.code-sdkerror", "clean should return the SdkError, got " + other)
499
+ }
500
+ }
501
+
502
+ private def sensitivity(rep: SdkTestReport): Unit = {
503
+ val target = usableOp()
504
+ if (target == null) {
505
+ println("clean: skipped: " + NO_OP)
506
+ return
507
+ }
508
+
509
+ val sinks = new ArrayList[Sink]()
510
+ val sdk = makeSdk(SCENARIOS(1), sinks, om("active" -> B(false)))
511
+ val err = drive(sdk, target, null, sinks)
512
+ rep.check("clean.off.throws", err != null, "the 404 scenario must throw")
513
+
514
+ // Explaining a failure must not cost it its error.
515
+ val explained = drive(makeSdk(SCENARIOS(1), new ArrayList[Sink](), om("active" -> B(false))), target,
516
+ om("explain" -> new LinkedHashMap[String, Object]()), new ArrayList[Sink]())
517
+ val errmsg = if (err == null) null else err.getMessage
518
+ val explainedmsg = if (explained == null) null else explained.getMessage
519
+ rep.check("clean.off.explain-keeps-error", errmsg == explainedmsg,
520
+ "with clean off, explain lost the error: expected " + errmsg + ", got " + explainedmsg)
521
+
522
+ val leaked = sinks.toArray(new Array[Sink](0)).toList.filter(s => leaks(s.text).nonEmpty)
523
+ rep.check("clean.off.shows-canary", leaked.nonEmpty,
524
+ "with clean off, nothing showed the canary: the sweep is blind")
525
+
526
+ if (!AUTH_SUPPRESSED) err match {
527
+ case e: SdkError =>
528
+ val text = Struct.jsonify(plain(e.spec))
529
+ rep.check("clean.off.raw-spec",
530
+ text.contains(CANARY_APIKEY) || text.contains(b64(CANARY_APIKEY + ":" + CANARY_SECRET)),
531
+ "the raw spec should carry the credential when clean is off")
532
+ case _ =>
533
+ }
534
+ }
535
+
536
+ // A feature's name is not a field name: only the sensitive names inside its
537
+ // settings register. An entity block, of per-entity settings or seeded
538
+ // records keyed by entity name and id, is not read at all.
539
+ private def featureNames(rep: SdkTestReport): Unit = {
540
+ val sdk = new ${SDK}(om(
541
+ "apikey" -> CANARY_APIKEY,
542
+ "feature" -> om(
543
+ "zzsecrets" -> om("active" -> B(false), "kind" -> "PLAINSETTING-q8w2e4r6"),
544
+ "zzfeat" -> om("active" -> B(false), "apitoken" -> "FEATTOKEN-z9y8x7w6"),
545
+ "test" -> om("active" -> B(false), "entity" -> om(
546
+ "zztoken" -> om("ZZTOKEN01" -> om("note" -> "PLAINRECORD-t5r3e1w9"))))),
547
+ "entity" -> om("zztoken" -> om("alias" -> om("zzkey" -> "PLAINALIAS-m2n4b6v8")))))
548
+ def clean(s: String): Object = sdk.getUtility().clean(sdk.getRootCtx(), s)
549
+
550
+ rep.eq("clean.feature.setting", "kind PLAINSETTING-q8w2e4r6", clean("kind PLAINSETTING-q8w2e4r6"))
551
+ rep.eq("clean.feature.token", "token " + MASK, clean("token FEATTOKEN-z9y8x7w6"))
552
+ rep.eq("clean.entity.record", "record PLAINRECORD-t5r3e1w9", clean("record PLAINRECORD-t5r3e1w9"))
553
+ rep.eq("clean.entity.alias", "alias PLAINALIAS-m2n4b6v8", clean("alias PLAINALIAS-m2n4b6v8"))
554
+ }
555
+
556
+ private def configBlock(rep: SdkTestReport): Unit = {
557
+ val utility = new ${SDK}(om()).getUtility()
558
+ val config = om("options" -> om("clean" -> om("keys" -> "zzsens", "values" -> "CONFIG-SEEDED-1")))
559
+ val ctx = utility.makeContext(om("utility" -> utility, "config" -> config,
560
+ "options" -> om("clean" -> om("values" -> "CALLER-SEEDED-2"))), null)
561
+ ctx.options = utility.makeOptions(ctx)
562
+
563
+ rep.eq("clean.config.values", "a " + MASK + " b " + MASK,
564
+ utility.clean(ctx, "a CONFIG-SEEDED-1 b CALLER-SEEDED-2"))
565
+ val masked = Helpers.toMapAny(utility.clean(ctx, om("my_zzsens" -> "x", "other" -> "y")))
566
+ rep.eq("clean.config.keys", om("my_zzsens" -> MASK, "other" -> "y"), masked)
567
+ rep.eq("clean.config.unchanged", "CONFIG-SEEDED-1",
568
+ Struct.getpath(config, java.util.List.of("options", "clean", "values")))
569
+ }
570
+
571
+ private def noBlock(rep: SdkTestReport): Unit = {
572
+ val utility = new ${SDK}(om()).getUtility()
573
+ val ctx = utility.makeContext(om("utility" -> utility,
574
+ "options" -> om("apikey" -> "NOBLOCK-APIKEY-k3j5h7")), null)
575
+ ctx.options = utility.makeOptions(ctx)
576
+
577
+ rep.eq("clean.no-block.values", "failed with " + MASK,
578
+ utility.clean(ctx, "failed with NOBLOCK-APIKEY-k3j5h7"))
579
+ val masked = Helpers.toMapAny(utility.clean(ctx, om("x-session-token" -> "RESP-TOKEN-a1b2c3d4e5")))
580
+ rep.eq("clean.no-block.keys", om("x-session-token" -> MASK), masked)
581
+ }
582
+
583
+ def main(args: Array[String]): Unit = {
584
+ val rep = new SdkTestReport()
585
+
586
+ rep.scope("clean-no-credential-leaves-the-sdk") { sweep(rep) }
587
+ rep.scope("clean-the-sweep-can-see-a-leak") { sensitivity(rep) }
588
+ rep.scope("clean-a-feature-name-does-not-make-its-settings-secret") { featureNames(rep) }
589
+ rep.scope("clean-the-config-clean-block-is-honoured") { configBlock(rep) }
590
+ rep.scope("clean-with-no-clean-block-the-schema-defaults-apply") { noBlock(rep) }
591
+
592
+ rep.finish("CLEAN")
593
+ }
594
+ }
595
+ `
596
+ }
597
+
598
+
599
+ // A Scala double-quoted string literal body: the auth name comes from the
600
+ // API's own securityScheme.
601
+ function scalastr(s: string): string {
602
+ return String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
603
+ }
604
+
605
+
606
+ export {
607
+ TestClean
608
+ }
@@ -15,6 +15,7 @@ import { cmp, each, Folder, File, Content, entityCollection,
15
15
 
16
16
  import { TestEntity } from './TestEntity_scala'
17
17
  import { TestDirect } from './TestDirect_scala'
18
+ import { TestClean } from './TestClean_scala'
18
19
  import { ReadmeExamplesTest } from './ReadmeExamplesTest_scala'
19
20
  import { scalaPackage } from './utility_scala'
20
21
 
@@ -35,6 +36,8 @@ const Test = cmp(function Test(props: any) {
35
36
  // Write-once: a project's edited control file survives regeneration.
36
37
  TestControl({ target, dir: 'sdktest' })
37
38
 
39
+ TestClean({ target, scalapackage })
40
+
38
41
  const entities: { Name: string; entity: boolean; direct: boolean }[] = []
39
42
 
40
43
  const entity = each(entityCollection(model))