@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,666 @@
1
+ import {
2
+ cmp,
3
+ each,
4
+ File,
5
+ Content,
6
+ isAuthSuppressed,
7
+ isHttpBasicAuth,
8
+ resolveAuthIn,
9
+ resolveAuthName,
10
+ } from '@voxgig/sdkgen'
11
+
12
+
13
+ import {
14
+ elixirString,
15
+ } from './utility_elixir'
16
+
17
+
18
+ // The canary sweep, the elixir port of TestClean_ts.ts: see that component.
19
+ const TestClean = cmp(function TestClean(props: any) {
20
+ const { model } = props.ctx$
21
+ const { entity } = props
22
+
23
+ const auth = {
24
+ suppressed: isAuthSuppressed(model),
25
+ where: resolveAuthIn(model),
26
+ name: 'header' === resolveAuthIn(model)
27
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
28
+ basic: isHttpBasicAuth(model),
29
+ }
30
+
31
+ File({ name: 'clean_test.exs' }, () => Content(render(model, entity, auth)))
32
+ })
33
+
34
+
35
+ const OP_ORDER: Record<string, number> = { list: 0, load: 1 }
36
+ const OPS = ['list', 'load', 'create', 'update', 'remove']
37
+
38
+
39
+ // The path parameters an operation's points declare, as the runtime config
40
+ // carries them under points[].args.params.
41
+ function pointParams(opdef: any): string[] {
42
+ const names: string[] = []
43
+ for (const point of each(opdef?.points || [])) {
44
+ if (false === point?.a) continue
45
+ for (const arg of each(point?.g?.params || [])) {
46
+ if (false !== arg?.a && 'string' === typeof arg?.n && !names.includes(arg.n)) {
47
+ names.push(arg.n)
48
+ }
49
+ }
50
+ }
51
+ return names
52
+ }
53
+
54
+
55
+ // The operations to try, list and load first: a required path parameter is
56
+ // what usually stops a candidate, and the read ops need none.
57
+ function candidates(Name: string, entity: any[]): string {
58
+ const rows: { rank: number, text: string }[] = []
59
+ each(entity, (e: any) => {
60
+ for (const op of Object.keys(e.op || {})) {
61
+ if (!OPS.includes(op)) continue
62
+ rows.push({
63
+ rank: OP_ORDER[op] ?? 2,
64
+ text: ` {${elixirString(e.name + '.' + op)}, fn sdk -> ${Name}.${e.name}(sdk) end,
65
+ fn ent, match, ctrl -> ${Name}.Entity.${e.Name}.${op}(ent, args(match), ctrl) end,
66
+ [${pointParams(e.op[op]).map((p) => elixirString(p)).join(', ')}]}`,
67
+ })
68
+ }
69
+ })
70
+ rows.sort((a, b) => a.rank - b.rank)
71
+ return rows.map((r) => r.text).join(',\n')
72
+ }
73
+
74
+
75
+ function render(model: any, entity: any[], auth: {
76
+ suppressed: boolean, where: string, name: string, basic: boolean
77
+ }): string {
78
+ const Name = model.const.Name
79
+
80
+ return `# ${Name} SDK canary sweep (generated by @voxgig/sdkgen).
81
+ #
82
+ # Every credential slot holds a distinctive value, every diagnostic feature
83
+ # this SDK ships is switched on with a capturing sink, a real operation runs
84
+ # through every outcome, and every string that leaves the SDK is searched for
85
+ # the canaries and their encoded forms. It also proves its own sensitivity:
86
+ # with clean switched off the canary MUST show.
87
+ #
88
+ # A struct node inspects as a handle, so the SDK's own records (the error's
89
+ # result and spec, the explain record, every sink record, the context's
90
+ # to_data) are also read through the struct JSON; a raw client, entity or
91
+ # context node is not, since that is a dump of the heap rather than a
92
+ # serialisation the SDK performs.
93
+
94
+ defmodule ${Name}.CleanTest do
95
+ use ExUnit.Case
96
+
97
+ alias Voxgig.Struct, as: S
98
+ alias ${Name}.Helpers, as: H
99
+ alias ${Name}.FeatureHarness, as: FH
100
+
101
+ # Generated: the credential's wire placement is fixed when the SDK is built.
102
+ @auth %{suppressed: ${auth.suppressed}, where: ${elixirString(auth.where)},
103
+ name: ${elixirString(auth.name)}, basic: ${auth.basic}}
104
+
105
+ @canary %{
106
+ apikey: "CANARY-APIKEY-k9x2m7q4p1",
107
+ secret: "CANARY-SECRET-w3e8r5t2y6",
108
+ header: "CANARY-HEADER-z1x4c7v0b3",
109
+ value: "CANARY-VALUE-n5m8b2v9c4"
110
+ }
111
+
112
+ @mask "[redacted]"
113
+
114
+ # Every form a canary can travel in.
115
+ defp forms_of do
116
+ Enum.flat_map(Map.values(@canary), fn v -> [v, Base.encode64(v), S.escurl(v)] end) ++
117
+ [Base.encode64(@canary.apikey <> ":" <> @canary.secret)]
118
+ end
119
+
120
+ defp leaks(text), do: Enum.filter(forms_of(), &String.contains?(text, &1))
121
+
122
+ # Header maps keep the caller's spelling; the assertion should not care.
123
+ defp header(m, name) do
124
+ if S.ismap(m) do
125
+ Enum.find_value(H.entries(m), fn {k, v} ->
126
+ if String.downcase(to_string(k)) == String.downcase(name), do: v
127
+ end)
128
+ end
129
+ end
130
+
131
+ defp push(name, kind, f) do
132
+ try do
133
+ [%{name: name <> ":" <> kind, text: to_string(f.())}]
134
+ rescue
135
+ _ -> []
136
+ catch
137
+ _, _ -> []
138
+ end
139
+ end
140
+
141
+ # Every default print of a value, as a sink each.
142
+ defp forms(name, val) do
143
+ push(name, "inspect", fn -> inspect(val, limit: :infinity, printable_limit: :infinity) end) ++
144
+ push(name, "raw", fn -> inspect(val, structs: false, limit: :infinity, printable_limit: :infinity) end) ++
145
+ if is_exception(val) do
146
+ push(name, "message", fn -> Exception.message(val) end) ++
147
+ push(name, "format", fn -> Exception.format(:error, val) end) ++
148
+ push(name, "json", fn -> S.jsonify(val) end)
149
+ else
150
+ []
151
+ end
152
+ end
153
+
154
+ # The SDK's own data, through the struct JSON as well.
155
+ defp data_forms(name, node) do
156
+ forms(name, node) ++
157
+ push(name, "json", fn -> S.jsonify(node) end) ++
158
+ push(name, "stringify", fn -> S.stringify(node) end)
159
+ end
160
+
161
+ defp error_forms(e) do
162
+ forms("error", e) ++
163
+ if match?(%${Name}.Error{}, e) do
164
+ data_forms("error.result", e.result) ++ data_forms("error.spec", e.spec)
165
+ else
166
+ []
167
+ end
168
+ end
169
+
170
+ defp result_forms(out) do
171
+ cond do
172
+ S.ismap(out) and S.getprop(out, "_client") != nil ->
173
+ forms("result", out) ++ data_forms("result.data", S.getprop(out, "_data"))
174
+
175
+ S.islist(out) ->
176
+ forms("result", out)
177
+
178
+ true ->
179
+ data_forms("result", out)
180
+ end
181
+ end
182
+
183
+ defp add(sinks, items), do: Enum.each(items, fn s -> S.setprop(sinks, S.size(sinks), s) end)
184
+ defp sink_list(sinks), do: Enum.map(H.entries(sinks), &elem(&1, 1))
185
+
186
+ # Captures the serialised context from inside the pipeline: what a hook
187
+ # author would hand to a logger.
188
+ defp capture_feature(sinks) do
189
+ cap = fn hook ->
190
+ fn ctx ->
191
+ add(sinks, forms("ctx@" <> hook, ctx))
192
+ add(sinks, data_forms("ctxdata@" <> hook, ${Name}.Context.to_data(ctx)))
193
+ nil
194
+ end
195
+ end
196
+
197
+ S.jm([
198
+ "name", "capture", "version", "0.0.1", "active", true, "options", S.jm([]),
199
+ "init", fn _ctx, _opts -> nil end,
200
+ "PreRequest", cap.("PreRequest"),
201
+ "PreResponse", cap.("PreResponse"),
202
+ "PreUnexpected", cap.("PreUnexpected")
203
+ ])
204
+ end
205
+
206
+ defp response(status, data, headers) do
207
+ h = S.jm(["content-type", "application/json"])
208
+ Enum.each(headers, fn {k, v} -> S.setprop(h, k, v) end)
209
+
210
+ S.jm([
211
+ "status", status,
212
+ "statusText", if(status < 400, do: "OK", else: "ERR"),
213
+ "headers", h,
214
+ "body", S.jsonify(data),
215
+ "json", fn -> data end
216
+ ])
217
+ end
218
+
219
+ defp scenarios do
220
+ [
221
+ {"ok",
222
+ fn _url, _fd ->
223
+ {response(200, S.jm(["id", "i1", "name", "n1"]), [{"x-session-token", "RESP-TOKEN-a1b2c3d4e5"}]), nil}
224
+ end},
225
+ {"notfound", fn _url, _fd -> {response(404, S.jm(["error", "no such record"]), []), nil} end},
226
+ {"server", fn _url, _fd -> {response(500, S.jm(["error", "boom"]), []), nil} end},
227
+ {"transport",
228
+ fn url, _fd ->
229
+ {nil, ${Name}.Error.new("transport", "socket hang up (URL was: \\"" <> url <> "\\")")}
230
+ end},
231
+ {"notjson",
232
+ fn _url, _fd ->
233
+ {S.jm([
234
+ "status", 200, "statusText", "OK", "headers", S.jm([]), "body", "<html>",
235
+ "json", fn -> raise "Unexpected token < in JSON" end
236
+ ]), nil}
237
+ end}
238
+ ]
239
+ end
240
+
241
+ defp make_sdk(respond, sinks, cleanopts, extra \\\\ []) do
242
+ capture = fn name -> fn rec -> add(sinks, data_forms(name, rec)) end end
243
+ feature = S.jm([])
244
+
245
+ on = fn name, kvs ->
246
+ if FH.has_feature(name), do: S.setprop(feature, name, S.jm(["active", true] ++ kvs))
247
+ end
248
+
249
+ on.("log", ["logger", capture.("log")])
250
+ on.("debug", ["onEntry", capture.("debug")])
251
+ on.("audit", ["sink", capture.("audit")])
252
+ on.("telemetry", ["exporter", capture.("telemetry")])
253
+ on.("cost", ["sink", capture.("cost")])
254
+ on.("metrics", [])
255
+ on.("clienttrack", [])
256
+
257
+ clean = S.jm(["values", @canary.value])
258
+ Enum.each(cleanopts, fn {k, v} -> S.setprop(clean, k, v) end)
259
+
260
+ ${Name}.new(
261
+ S.jm([
262
+ "apikey", @canary.apikey,
263
+ "secret", @canary.secret,
264
+ "headers", S.jm(["X-Custom-Token", @canary.header]),
265
+ "clean", clean,
266
+ "feature", feature,
267
+ "extend", S.jt([capture_feature(sinks) | extra]),
268
+ "utility", S.jm(["fetcher", fn _ctx, url, fd -> respond.(url, fd) end])
269
+ ])
270
+ )
271
+ end
272
+
273
+ # A fresh struct node of the match, since an operation may keep what it is
274
+ # given.
275
+ defp args(match), do: S.jm(Enum.flat_map(match, fn {k, v} -> [k, v] end))
276
+
277
+ # The operations this SDK generated, read ops first.
278
+ defp candidates do
279
+ [
280
+ ${candidates(Name, entity)}
281
+ ]
282
+ end
283
+
284
+ # The first operation that completes against a plain 200: with no
285
+ # arguments, else with every path parameter its points declare filled in.
286
+ defp usable_op do
287
+ plain =
288
+ ${Name}.new(
289
+ S.jm([
290
+ "apikey", @canary.apikey,
291
+ "utility", S.jm(["fetcher", fn _c, _u, _f -> {response(200, S.jm(["id", "i1"]), []), nil} end])
292
+ ])
293
+ )
294
+
295
+ Enum.find_value(candidates(), fn {name, acc, op, params} ->
296
+ filled = Map.new(params, fn p -> {p, "p1"} end)
297
+
298
+ Enum.find_value([%{}, filled], fn match ->
299
+ try do
300
+ op.(acc.(plain), match, S.jm([]))
301
+ {name, acc, op, match}
302
+ rescue
303
+ _ -> nil
304
+ catch
305
+ _, _ -> nil
306
+ end
307
+ end)
308
+ end)
309
+ end
310
+
311
+ # A feature that raises from inside the pipeline, quoting the request it
312
+ # saw: an error make_error never handled.
313
+ defp throw_feature(unexpected) do
314
+ saw = fn ctx -> "hook saw " <> S.jsonify(S.getprop(ctx, "spec")) end
315
+
316
+ S.jm([
317
+ "name", "throwhook", "version", "0.0.1", "active", true, "options", S.jm([]),
318
+ "init", fn _ctx, _opts -> nil end,
319
+ "PreResponse", fn ctx -> raise saw.(ctx) end,
320
+ # Fired from the operation's rescue, before its cleaning.
321
+ "PreUnexpected", fn ctx -> if unexpected, do: raise(saw.(ctx)) end
322
+ ])
323
+ end
324
+
325
+ # A stream that fails while the caller iterates it, quoting a credential.
326
+ defp stream_feature do
327
+ S.jm([
328
+ "name", "streamthrow", "version", "0.0.1", "active", true, "options", S.jm([]),
329
+ "init", fn _ctx, _opts -> nil end,
330
+ "PreDone", fn ctx ->
331
+ S.setprop(S.getprop(ctx, "result"), "stream",
332
+ fn -> Stream.map([1], fn _ -> raise "stream saw " <> @canary.apikey end) end)
333
+ end
334
+ ])
335
+ end
336
+
337
+ # A stream that succeeds, yielding the result's items.
338
+ defp stream_ok_feature do
339
+ S.jm([
340
+ "name", "streamok", "version", "0.0.1", "active", true, "options", S.jm([]),
341
+ "init", fn _ctx, _opts -> nil end,
342
+ "PreDone", fn ctx ->
343
+ result = S.getprop(ctx, "result")
344
+ rd = S.getprop(result, "resdata")
345
+ items = if S.islist(rd), do: Enum.map(H.entries(rd), &elem(&1, 1)), else: List.wrap(rd)
346
+ S.setprop(result, "stream", fn -> items end)
347
+ end
348
+ ])
349
+ end
350
+
351
+ # The target operation, streamed through its entity.
352
+ defp stream_of(sdk, {name, acc, _op, match}, callopts) do
353
+ ent = acc.(sdk)
354
+ mod = S.getprop(ent, "_module")
355
+ mod.stream(ent, List.last(String.split(name, ".")), S.jm(["reqmatch", args(match)]), callopts)
356
+ end
357
+
358
+ # Features that fail the operation with the SDK's own error, whose code
359
+ # quotes a registered value: one refuses it as rbac does, and records the
360
+ # error PreUnexpected hands a hook; the other raises.
361
+ defp deny_feature(sinks) do
362
+ S.jm([
363
+ "name", "denyhook", "version", "0.0.1", "active", true, "options", S.jm([]),
364
+ "init", fn _ctx, _opts -> nil end,
365
+ "PrePoint", fn ctx ->
366
+ err = ${Name}.Context.make_error(ctx, "denied:" <> @canary.value, "denied")
367
+ S.setprop(S.getprop(ctx, "out"), "point", err)
368
+ end,
369
+ "PreUnexpected", fn ctx ->
370
+ add(sinks, error_forms(S.getprop(S.getprop(ctx, "ctrl"), "err")))
371
+ nil
372
+ end
373
+ ])
374
+ end
375
+
376
+ defp raise_feature do
377
+ S.jm([
378
+ "name", "raisehook", "version", "0.0.1", "active", true, "options", S.jm([]),
379
+ "init", fn _ctx, _opts -> nil end,
380
+ "PreResponse", fn _ctx -> raise ${Name}.Error.new("raised:" <> @canary.value, "raised") end
381
+ ])
382
+ end
383
+
384
+ defp drive(sdk, {_name, acc, op, match}, ctrl, sinks) do
385
+ ent = acc.(sdk)
386
+ # A caller may keep the record it passed rather than read ctrl.explain.
387
+ held = S.getprop(ctrl, "explain")
388
+
389
+ {out, err} =
390
+ try do
391
+ {op.(ent, match, ctrl), nil}
392
+ rescue
393
+ e -> {nil, e}
394
+ end
395
+
396
+ if err != nil, do: add(sinks, error_forms(err))
397
+ if out != nil, do: add(sinks, result_forms(out))
398
+ explain = S.getprop(ctrl, "explain")
399
+ if explain != nil, do: add(sinks, data_forms("explain", explain))
400
+ if held != nil and held != explain, do: add(sinks, data_forms("explain:held", held))
401
+ err
402
+ end
403
+
404
+ @no_target "no operation of this SDK completes against a plain 200; nothing to sweep"
405
+
406
+ # ExUnit has no runtime skip, so a sweep with nothing to drive says so.
407
+ test "no credential leaves the SDK in any form" do
408
+ case usable_op() do
409
+ nil -> IO.puts("SKIP no credential leaves the SDK in any form: " <> @no_target)
410
+ target -> sweep(target)
411
+ end
412
+ end
413
+
414
+ test "the sweep can see a leak: clean switched off shows the credential" do
415
+ case usable_op() do
416
+ nil -> IO.puts("SKIP the sweep can see a leak: " <> @no_target)
417
+ target -> sweep_blind(target)
418
+ end
419
+ end
420
+
421
+ defp sweep(target) do
422
+ sinks = S.jt([])
423
+
424
+ variants = [
425
+ {"throw", fn -> S.jm([]) end},
426
+ {"explain", fn -> S.jm(["explain", S.jm([])]) end},
427
+ {"nothrow", fn -> S.jm(["throw", false, "explain", S.jm([])]) end}
428
+ ]
429
+
430
+ {errors, explains} =
431
+ Enum.reduce(scenarios(), {%{}, %{}}, fn {sname, respond}, acc ->
432
+ Enum.reduce(variants, acc, fn {vname, mkctrl}, {errors, explains} ->
433
+ sdk = make_sdk(respond, sinks, [])
434
+ ctrl = mkctrl.()
435
+ err = drive(sdk, target, ctrl, sinks)
436
+ add(sinks, forms("sdk", sdk))
437
+ key = sname <> "/" <> vname
438
+ errors = if err != nil, do: Map.put(errors, key, err), else: errors
439
+ ex = S.getprop(ctrl, "explain")
440
+ explains = if ex != nil, do: Map.put(explains, key, ex), else: explains
441
+ {errors, explains}
442
+ end)
443
+ end)
444
+
445
+ # A credential mistyped as a map is rejected by validation, whose message
446
+ # quotes the value it rejected.
447
+ rejected =
448
+ try do
449
+ ${Name}.new(S.jm(["apikey", S.jm(["value", @canary.apikey]), "clean", S.jm(["values", @canary.value])]))
450
+ nil
451
+ rescue
452
+ e -> e
453
+ end
454
+
455
+ assert rejected != nil, "a credential mistyped as a map should be rejected"
456
+ add(sinks, forms("rejected", rejected))
457
+
458
+ # An error a feature hook raises, quoting the request, skips make_error.
459
+ [{_name, ok} | _] = scenarios()
460
+
461
+ for unexpected <- [false, true] do
462
+ hooked = make_sdk(ok, sinks, [], [throw_feature(unexpected)])
463
+ err = drive(hooked, target, S.jm(["explain", S.jm([])]), sinks)
464
+ assert err != nil, "the throwing hook should fail the operation"
465
+ end
466
+
467
+ # Iterating a stream runs through the same cleaning path as the operation,
468
+ # and the explain record the caller passed is cleaned however it ends.
469
+ for {name, extra} <- [{"stream", [stream_feature()]}, {"stream-ok", [stream_ok_feature()]}, {"stream-plain", []}] do
470
+ explain = S.jm([])
471
+ callopts = S.jm(["ctrl", S.jm(["explain", explain])])
472
+
473
+ streamerr =
474
+ try do
475
+ Enum.to_list(stream_of(make_sdk(ok, sinks, [], extra), target, callopts))
476
+ nil
477
+ rescue
478
+ e -> e
479
+ end
480
+
481
+ assert (name == "stream") == (streamerr != nil), name <> ": only the failing stream raises"
482
+ if streamerr != nil, do: add(sinks, forms(name, streamerr))
483
+ assert S.size(explain) > 0, name <> ": the explain record was not filled"
484
+ add(sinks, data_forms(name <> ":explain", explain))
485
+ end
486
+
487
+ # A feature's own error keeps its code, which is cleaned like the message:
488
+ # returned, handed to a hook, raised by a hook, and nested in a record.
489
+ denied = drive(make_sdk(ok, sinks, [], [deny_feature(sinks)]), target, S.jm([]), sinks)
490
+ assert denied != nil, "the refusing hook should fail the operation"
491
+ raised = drive(make_sdk(ok, sinks, [], [raise_feature()]), target, S.jm([]), sinks)
492
+ assert raised != nil, "the raising hook should fail the operation"
493
+
494
+ nested =
495
+ ${Name}.Utility.clean_impl(${Name}.get_root_ctx(make_sdk(ok, sinks, [])),
496
+ S.jm(["err", ${Name}.Error.new("nested:" <> @canary.value, "nested")]))
497
+
498
+ add(sinks, data_forms("nested", nested))
499
+
500
+ # A client given no clean block at all masks by the schema defaults.
501
+ [_ok, {_nf, notfound_respond} | _] = scenarios()
502
+
503
+ bare =
504
+ ${Name}.new(
505
+ S.jm([
506
+ "apikey", @canary.apikey,
507
+ "secret", @canary.secret,
508
+ "headers", S.jm(["X-Custom-Token", @canary.header]),
509
+ "utility", S.jm(["fetcher", fn _ctx, url, fd -> notfound_respond.(url, fd) end])
510
+ ])
511
+ )
512
+
513
+ barerr = drive(bare, target, S.jm([]), sinks)
514
+ assert barerr != nil, "the 404 scenario must fail without a clean block"
515
+
516
+ # The raw path returns its failure rather than raising it.
517
+ [_ok, _nf, _server, {_tr, transport_respond} | _] = scenarios()
518
+ direct = ${Name}.direct(make_sdk(transport_respond, sinks, []), S.jm(["path", "raw"]))
519
+ assert S.getprop(direct, "ok") == false, "a transport failure should fail direct()"
520
+ add(sinks, forms("direct", S.getprop(direct, "err")))
521
+
522
+ all = sink_list(sinks)
523
+ leaked = Enum.filter(all, fn s -> leaks(s.text) != [] end)
524
+
525
+ IO.puts("clean: swept #{length(all)} surface(s), #{length(leaked)} leak(s)")
526
+
527
+ assert leaked == [],
528
+ "credential leaked through: " <>
529
+ Enum.map_join(leaked, "; ", fn s -> s.name <> " [" <> Enum.join(leaks(s.text), ", ") <> "]" end)
530
+
531
+ # The positive half: the slot the credential travelled in is masked, and
532
+ # an unregistered token in a response header is masked by name.
533
+ notfound = errors["notfound/throw"]
534
+ assert notfound != nil, "the 404 scenario must throw"
535
+ assert match?(%${Name}.Error{}, notfound), "the 404 error is an SDK error"
536
+ assert ${Name}.Error.status(notfound) == 404
537
+ spec = notfound.spec
538
+
539
+ unless @auth.suppressed do
540
+ case @auth.where do
541
+ "query" ->
542
+ assert header(S.getprop(spec, "query"), @auth.name) == @mask
543
+
544
+ "cookie" ->
545
+ assert String.contains?(to_string(header(S.getprop(spec, "headers"), "cookie")), @mask)
546
+
547
+ _ ->
548
+ assert String.ends_with?(to_string(header(S.getprop(spec, "headers"), @auth.name)), @mask)
549
+ end
550
+ end
551
+
552
+ assert header(S.getprop(spec, "headers"), "x-custom-token") == @mask
553
+ assert denied.code == "denied:" <> @mask
554
+ assert raised.code == "raised:" <> @mask
555
+ assert S.getpath(nested, "err.code") == "nested:" <> @mask
556
+ assert header(S.getprop(barerr.spec, "headers"), "x-custom-token") == @mask
557
+
558
+ explained = explains["ok/explain"]
559
+ result = if explained != nil, do: S.getprop(explained, "result"), else: nil
560
+ assert S.ismap(result), "the explain record should carry the result"
561
+ assert header(S.getprop(result, "headers"), "x-session-token") == @mask
562
+ end
563
+
564
+ defp sweep_blind(target) do
565
+ sinks = S.jt([])
566
+ [_ok, {_name, notfound} | _] = scenarios()
567
+ sdk = make_sdk(notfound, sinks, [{"active", false}])
568
+ err = drive(sdk, target, S.jm([]), sinks)
569
+ assert err != nil
570
+
571
+ # Explaining a failure must not cost it its error.
572
+ explained =
573
+ drive(make_sdk(notfound, S.jt([]), [{"active", false}]), target, S.jm(["explain", S.jm([])]), S.jt([]))
574
+
575
+ assert explained != nil and Exception.message(explained) == Exception.message(err),
576
+ "with clean off, explain lost the error"
577
+
578
+ assert Enum.any?(sink_list(sinks), fn s -> leaks(s.text) != [] end),
579
+ "with clean off, nothing showed the canary: the sweep is blind"
580
+
581
+ unless @auth.suppressed do
582
+ text = S.jsonify(err.spec)
583
+
584
+ assert String.contains?(text, @canary.apikey) or
585
+ String.contains?(text, Base.encode64(@canary.apikey <> ":" <> @canary.secret)),
586
+ "the raw spec should carry the credential when clean is off"
587
+ end
588
+ end
589
+
590
+ test "a registered value used as a property name is masked, collisions kept" do
591
+ cfg = ${Name}.Utility.make_clean_config(S.jm(["keys", "key,secret,token"]))
592
+ ctx = S.jm(["options", S.jm(["__derived__", S.jm(["clean", cfg])])])
593
+ ${Name}.Utility.clean_add_impl(ctx, "ZZVAL-abc123")
594
+ ${Name}.Utility.clean_add_impl(ctx, "ZZVAL-xyz789")
595
+ out = ${Name}.Utility.clean_impl(ctx, S.jm(["ZZVAL-abc123", 1, "ZZVAL-xyz789", 2, "plain", 3]))
596
+ assert S.getprop(out, @mask) == 1
597
+ assert S.getprop(out, @mask <> "#1") == 2
598
+ assert S.getprop(out, "plain") == 3
599
+ assert "ZZVAL-abc123" not in S.keysof(out)
600
+ end
601
+
602
+ # A feature's name is not a field name: a feature called secrets does not
603
+ # make its settings secret, though a sensitive field inside it still is. An
604
+ # entity block, of entity settings or seeded records, is not read at all.
605
+ test "a feature's name is read as a name" do
606
+ record = S.jm(["zztoken", S.jm(["ZZTOKEN01", S.jm(["note", "PLAINRECORD-t5r3e1w9"])])])
607
+
608
+ client =
609
+ ${Name}.new(
610
+ S.jm([
611
+ "apikey", @canary.apikey,
612
+ "feature",
613
+ S.jm([
614
+ "secrets", S.jm(["active", false, "name", "ZZNAME-feat123", "token", "ZZTOKEN-feat456"]),
615
+ "test", S.jm(["active", false, "entity", record])
616
+ ]),
617
+ "entity", S.jm(["zztoken", S.jm(["alias", S.jm(["zzkey", "PLAINALIAS-m2n4b6v8"])])])
618
+ ])
619
+ )
620
+
621
+ ctx = ${Name}.get_root_ctx(client)
622
+ assert ${Name}.Utility.clean_impl(ctx, "ZZNAME-feat123 ZZTOKEN-feat456") == "ZZNAME-feat123 " <> @mask
623
+ assert ${Name}.Utility.clean_impl(ctx, "record PLAINRECORD-t5r3e1w9") == "record PLAINRECORD-t5r3e1w9"
624
+ assert ${Name}.Utility.clean_impl(ctx, "alias PLAINALIAS-m2n4b6v8") == "alias PLAINALIAS-m2n4b6v8"
625
+ end
626
+
627
+ test "the generated config's own clean block is honoured" do
628
+ config = S.jm(["options", S.jm(["clean", S.jm(["keys", "zzsens", "values", "CONFIG-SEEDED-1"])])])
629
+ ctx = S.jm(["config", config, "options", S.jm(["clean", S.jm(["values", "CALLER-SEEDED-2"])])])
630
+ cctx = S.jm(["options", ${Name}.Utility.make_options_impl(ctx)])
631
+
632
+ assert ${Name}.Utility.clean_impl(cctx, "a CONFIG-SEEDED-1 b CALLER-SEEDED-2") ==
633
+ "a " <> @mask <> " b " <> @mask
634
+
635
+ out = ${Name}.Utility.clean_impl(cctx, S.jm(["my_zzsens", "x", "other", "y"]))
636
+ assert S.getprop(out, "my_zzsens") == @mask
637
+ assert S.getprop(out, "other") == "y"
638
+ assert S.getpath(config, "options.clean.keys") == "zzsens"
639
+ assert S.getpath(config, "options.clean.values") == "CONFIG-SEEDED-1"
640
+ end
641
+
642
+ test "clean_add_sensitive registers every scalar under a sensitive name, at any depth" do
643
+ cfg = ${Name}.Utility.make_clean_config(S.jm(["keys", "key,secret,token"]))
644
+ ctx = S.jm(["options", S.jm(["__derived__", S.jm(["clean", cfg])])])
645
+
646
+ ${Name}.Utility.clean_add_sensitive(ctx, S.jm([
647
+ "apikey", S.jm(["value", "NESTED-SECRET-1"]),
648
+ "headers", S.jm(["X-Api-Token", S.jt(["LISTED-SECRET-2"])]),
649
+ "secret", 123456789,
650
+ "name", "not-a-secret"
651
+ ]))
652
+
653
+ values = Enum.map(H.entries(S.getprop(cfg, "values")), &elem(&1, 1))
654
+ assert "NESTED-SECRET-1" in values
655
+ assert "LISTED-SECRET-2" in values
656
+ assert "123456789" in values
657
+ refute "not-a-secret" in values
658
+ end
659
+ end
660
+ `
661
+ }
662
+
663
+
664
+ export {
665
+ TestClean
666
+ }
@@ -8,6 +8,7 @@ import { cmp, each, Folder, File, Content, entityCollection } from '@voxgig/sdkg
8
8
 
9
9
  import { TestEntity } from './TestEntity_elixir'
10
10
  import { TestDirect } from './TestDirect_elixir'
11
+ import { TestClean } from './TestClean_elixir'
11
12
  import { ReadmeExamplesTest } from './ReadmeExamplesTest_elixir'
12
13
 
13
14
 
@@ -39,6 +40,9 @@ end
39
40
  TestDirect({ target, entity })
40
41
  })
41
42
 
43
+ // The canary sweep (test/clean_test.exs), picked up by `mix test`.
44
+ TestClean({ target, entity })
45
+
42
46
  // Validate the documented elixir examples in the README/REFERENCE docs.
43
47
  ReadmeExamplesTest({ target })
44
48
  })
@@ -209,7 +209,7 @@ defmodule ProjectName do
209
209
 
210
210
  cond do
211
211
  fetch_err != nil ->
212
- S.jm(["ok", false, "err", fetch_err])
212
+ S.jm(["ok", false, "err", Utility.clean(ctx, fetch_err)])
213
213
 
214
214
  fetched == nil ->
215
215
  S.jm(["ok", false, "err", Context.make_error(ctx, "direct_no_response", "response: undefined")])