@voxgig/sdkgen 4.32.0 → 4.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (415) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/helpers/naming.js +1 -1
  3. package/dist/helpers/naming.js.map +1 -1
  4. package/dist/tsconfig.tsbuildinfo +1 -1
  5. package/model/sdkgen.aontu +7 -1
  6. package/package.json +1 -1
  7. package/project/.sdk/model/feature/debug.aontu +3 -1
  8. package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
  9. package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
  10. package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
  11. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
  12. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
  13. package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
  14. package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
  15. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
  16. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
  17. package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
  18. package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
  19. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
  20. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
  21. package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
  22. package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
  23. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
  24. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
  25. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
  26. package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
  27. package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
  28. package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
  29. package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
  30. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
  31. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
  32. package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
  33. package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
  34. package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
  35. package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
  36. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
  37. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
  38. package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
  39. package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
  40. package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
  41. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
  42. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
  43. package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
  44. package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
  45. package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
  46. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
  47. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
  48. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
  49. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
  50. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
  51. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
  52. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
  53. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
  54. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
  55. package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
  56. package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
  57. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
  58. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
  59. package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
  60. package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
  61. package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
  62. package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
  63. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
  64. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
  65. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
  66. package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
  67. package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
  68. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
  69. package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
  70. package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
  71. package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
  72. package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
  73. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
  74. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
  75. package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
  76. package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
  77. package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
  78. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
  79. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
  80. package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
  81. package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
  82. package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
  83. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
  84. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
  85. package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
  86. package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
  87. package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
  88. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
  89. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
  90. package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
  91. package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
  92. package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
  93. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
  94. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
  95. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
  96. package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
  97. package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
  98. package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
  99. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
  100. package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
  101. package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
  102. package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
  103. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
  104. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
  105. package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
  106. package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
  107. package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
  108. package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
  109. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
  110. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
  111. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
  112. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
  113. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
  114. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
  115. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
  116. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
  117. package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
  118. package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
  119. package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
  120. package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
  121. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
  122. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
  123. package/project/.sdk/tm/c/core/context.c +25 -0
  124. package/project/.sdk/tm/c/core/error.c +16 -0
  125. package/project/.sdk/tm/c/core/sdk.h +22 -0
  126. package/project/.sdk/tm/c/feature/audit.c +2 -0
  127. package/project/.sdk/tm/c/feature/cost.c +1 -0
  128. package/project/.sdk/tm/c/feature/debug.c +19 -29
  129. package/project/.sdk/tm/c/feature/log.c +21 -2
  130. package/project/.sdk/tm/c/feature/proxy.c +55 -3
  131. package/project/.sdk/tm/c/feature/secrets.c +7 -0
  132. package/project/.sdk/tm/c/feature/telemetry.c +2 -0
  133. package/project/.sdk/tm/c/tests/feature_test.c +2 -2
  134. package/project/.sdk/tm/c/utility/clean.c +530 -8
  135. package/project/.sdk/tm/c/utility/done.c +28 -12
  136. package/project/.sdk/tm/c/utility/make_error.c +4 -3
  137. package/project/.sdk/tm/c/utility/make_options.c +71 -45
  138. package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
  139. package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
  140. package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
  141. package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
  142. package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
  143. package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
  144. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
  145. package/project/.sdk/tm/cpp/core/types.hpp +93 -3
  146. package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
  147. package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
  148. package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
  149. package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
  150. package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
  151. package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
  152. package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
  153. package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
  154. package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
  155. package/project/.sdk/tm/csharp/core/Context.cs +32 -0
  156. package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
  157. package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
  158. package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
  159. package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
  160. package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
  161. package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
  162. package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
  163. package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
  164. package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
  165. package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
  166. package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
  167. package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
  168. package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
  169. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
  170. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
  171. package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
  172. package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
  173. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
  174. package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
  175. package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
  176. package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
  177. package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
  178. package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
  179. package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
  180. package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
  181. package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
  182. package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
  183. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
  184. package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
  185. package/project/.sdk/tm/go/core/context.go +42 -0
  186. package/project/.sdk/tm/go/core/error.go +30 -10
  187. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  188. package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
  189. package/project/.sdk/tm/go/feature/base_feature.go +12 -0
  190. package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
  191. package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
  192. package/project/.sdk/tm/go/feature/log_feature.go +13 -8
  193. package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
  194. package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
  195. package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
  196. package/project/.sdk/tm/go/test/feature_test.go +2 -2
  197. package/project/.sdk/tm/go/utility/clean.go +585 -2
  198. package/project/.sdk/tm/go/utility/done.go +29 -9
  199. package/project/.sdk/tm/go/utility/make_error.go +51 -16
  200. package/project/.sdk/tm/go/utility/make_options.go +77 -36
  201. package/project/.sdk/tm/go/utility/register.go +12 -0
  202. package/project/.sdk/tm/java/core/Context.java +29 -0
  203. package/project/.sdk/tm/java/core/SdkClient.java +4 -2
  204. package/project/.sdk/tm/java/core/Utility.java +7 -0
  205. package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
  206. package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
  207. package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
  208. package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
  209. package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
  210. package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
  211. package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
  212. package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
  213. package/project/.sdk/tm/java/utility/Clean.java +519 -1
  214. package/project/.sdk/tm/java/utility/Done.java +1 -1
  215. package/project/.sdk/tm/java/utility/MakeError.java +5 -1
  216. package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
  217. package/project/.sdk/tm/java/utility/Register.java +4 -0
  218. package/project/.sdk/tm/js/src/Context.js +5 -1
  219. package/project/.sdk/tm/js/src/Response.js +14 -1
  220. package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
  221. package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
  222. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
  223. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
  224. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
  225. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
  226. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
  227. package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
  228. package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
  229. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
  230. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
  231. package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
  232. package/project/.sdk/tm/js/test/feature/harness.js +11 -1
  233. package/project/.sdk/tm/js/test/feature.test.js +9 -2
  234. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +25 -0
  235. package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
  236. package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
  237. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  238. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
  239. package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
  240. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
  241. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
  242. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
  243. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
  244. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
  245. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
  246. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
  247. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
  248. package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
  249. package/project/.sdk/tm/lua/core/context.lua +43 -0
  250. package/project/.sdk/tm/lua/core/error.lua +36 -1
  251. package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
  252. package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
  253. package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
  254. package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
  255. package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
  256. package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
  257. package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
  258. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
  259. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
  260. package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
  261. package/project/.sdk/tm/lua/utility/clean.lua +426 -2
  262. package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
  263. package/project/.sdk/tm/lua/utility/done.lua +1 -7
  264. package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
  265. package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
  266. package/project/.sdk/tm/lua/utility/register.lua +4 -1
  267. package/project/.sdk/tm/ocaml/Makefile +5 -1
  268. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
  269. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
  270. package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
  271. package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
  272. package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
  273. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
  274. package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
  275. package/project/.sdk/tm/perl/core/context.pm +27 -0
  276. package/project/.sdk/tm/perl/core/error.pm +52 -5
  277. package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
  278. package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
  279. package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
  280. package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
  281. package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
  282. package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
  283. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
  284. package/project/.sdk/tm/perl/t/feature.t +4 -2
  285. package/project/.sdk/tm/perl/utility/clean.pm +345 -1
  286. package/project/.sdk/tm/perl/utility/done.pm +24 -6
  287. package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
  288. package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
  289. package/project/.sdk/tm/php/core/Context.php +24 -1
  290. package/project/.sdk/tm/php/core/Error.php +34 -3
  291. package/project/.sdk/tm/php/core/UtilityType.php +4 -0
  292. package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
  293. package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
  294. package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
  295. package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
  296. package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
  297. package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
  298. package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
  299. package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
  300. package/project/.sdk/tm/php/utility/Clean.php +438 -2
  301. package/project/.sdk/tm/php/utility/Done.php +14 -7
  302. package/project/.sdk/tm/php/utility/MakeError.php +9 -7
  303. package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
  304. package/project/.sdk/tm/php/utility/Register.php +2 -0
  305. package/project/.sdk/tm/py/pkg/core/context.py +17 -0
  306. package/project/.sdk/tm/py/pkg/core/error.py +42 -1
  307. package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
  308. package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
  309. package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
  310. package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
  311. package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
  312. package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
  313. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
  314. package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
  315. package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
  316. package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
  317. package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
  318. package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
  319. package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
  320. package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
  321. package/project/.sdk/tm/py/test/feature_harness.py +4 -0
  322. package/project/.sdk/tm/py/test/test_feature.py +2 -2
  323. package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
  324. package/project/.sdk/tm/rb/core/context.rb +28 -0
  325. package/project/.sdk/tm/rb/core/error.rb +30 -0
  326. package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
  327. package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
  328. package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
  329. package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
  330. package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
  331. package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
  332. package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
  333. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
  334. package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
  335. package/project/.sdk/tm/rb/utility/clean.rb +312 -1
  336. package/project/.sdk/tm/rb/utility/done.rb +15 -5
  337. package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
  338. package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
  339. package/project/.sdk/tm/rb/utility/register.rb +2 -0
  340. package/project/.sdk/tm/rust/core/context.rs +55 -0
  341. package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
  342. package/project/.sdk/tm/rust/feature/audit.rs +2 -0
  343. package/project/.sdk/tm/rust/feature/cost.rs +3 -2
  344. package/project/.sdk/tm/rust/feature/debug.rs +16 -16
  345. package/project/.sdk/tm/rust/feature/log.rs +42 -7
  346. package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
  347. package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
  348. package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
  349. package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
  350. package/project/.sdk/tm/rust/utility/clean.rs +446 -5
  351. package/project/.sdk/tm/rust/utility/done.rs +22 -12
  352. package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
  353. package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
  354. package/project/.sdk/tm/scala/Makefile +3 -1
  355. package/project/.sdk/tm/scala/core/Context.scala +16 -0
  356. package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
  357. package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
  358. package/project/.sdk/tm/scala/core/Types.scala +3 -0
  359. package/project/.sdk/tm/scala/core/Utility.scala +2 -0
  360. package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
  361. package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
  362. package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
  363. package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
  364. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
  365. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
  366. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
  367. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
  368. package/project/.sdk/tm/scala/utility/Make.scala +63 -20
  369. package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
  370. package/project/.sdk/tm/scala/utility/Register.scala +1 -0
  371. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
  372. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
  373. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
  374. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
  375. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
  376. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
  377. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
  378. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
  379. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
  380. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
  381. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
  382. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
  383. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
  384. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
  385. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
  386. package/project/.sdk/tm/ts/src/Context.ts +5 -1
  387. package/project/.sdk/tm/ts/src/Response.ts +14 -1
  388. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
  389. package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
  390. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
  391. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
  392. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
  393. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
  394. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
  395. package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
  396. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
  397. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
  398. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
  399. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
  400. package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
  401. package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
  402. package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +25 -0
  403. package/project/.sdk/tm/zig/core/context.zig +34 -0
  404. package/project/.sdk/tm/zig/core/error.zig +22 -1
  405. package/project/.sdk/tm/zig/core/utility.zig +403 -39
  406. package/project/.sdk/tm/zig/feature/audit.zig +4 -2
  407. package/project/.sdk/tm/zig/feature/cost.zig +3 -2
  408. package/project/.sdk/tm/zig/feature/debug.zig +20 -25
  409. package/project/.sdk/tm/zig/feature/log.zig +3 -1
  410. package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
  411. package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
  412. package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
  413. package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
  414. package/project/sdkgen-package.json +1 -1
  415. package/src/helpers/naming.ts +1 -1
@@ -0,0 +1,881 @@
1
+ import type {
2
+ ModelEntity
3
+ } from '@voxgig/apidef'
4
+
5
+ import {
6
+ cmp,
7
+ configDefinition,
8
+ each,
9
+ File,
10
+ Content,
11
+ entityCollection,
12
+ targetFeatures,
13
+ isAuthSuppressed,
14
+ isHttpBasicAuth,
15
+ resolveAuthIn,
16
+ resolveAuthName,
17
+ } from '@voxgig/sdkgen'
18
+
19
+
20
+ import { rustMethodName } from './utility_rust'
21
+
22
+
23
+ // A custom action is not a trait method the sweep can call by name.
24
+ const CRUD = ['list', 'load', 'create', 'update', 'remove']
25
+
26
+ const DIAGNOSTIC = ['log', 'debug', 'audit', 'telemetry', 'cost', 'metrics', 'clienttrack']
27
+
28
+
29
+ // The canary sweep (twin of TestClean_ts). Rust is statically typed, so the
30
+ // operation candidates the ts sweep finds by reflection are enumerated here
31
+ // at generation time, each with the path parameters its config points
32
+ // declare; the sweep still DRIVES them to find the first that completes.
33
+ const TestClean = cmp(function TestClean(props: any) {
34
+ const { model } = props.ctx$
35
+ const { target, rustcrate } = props
36
+
37
+ const Name = model.const.Name
38
+
39
+ const auth = {
40
+ suppressed: isAuthSuppressed(model),
41
+ where: resolveAuthIn(model),
42
+ name: 'header' === resolveAuthIn(model)
43
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
44
+ basic: isHttpBasicAuth(model),
45
+ }
46
+
47
+ const features = Object.keys(targetFeatures(model, target))
48
+ .filter((name) => DIAGNOSTIC.includes(name))
49
+ .sort()
50
+
51
+ const configEntity = configDefinition(model, target.name).def.entity || {}
52
+
53
+ const candidates: Candidate[] = []
54
+ const entities = each(entityCollection(model)).filter((e: any) => false !== e.active)
55
+ each(entities, (entity: ModelEntity) => {
56
+ const method = rustMethodName(entity.name)
57
+ const ops = Object.keys((entity as any).op || {})
58
+ .filter((op) => CRUD.includes(op))
59
+ .sort((a, b) => CRUD.indexOf(a) - CRUD.indexOf(b))
60
+ for (const op of ops) {
61
+ candidates.push({
62
+ name: entity.name + '.' + op, fn: 'drive_' + method + '_' + op,
63
+ sfn: 'stream_' + method + '_' + op, method, op,
64
+ params: pointParams(configEntity[entity.name]?.op?.[op]),
65
+ })
66
+ }
67
+ })
68
+
69
+ File({ name: 'clean_test.' + target.ext }, () => {
70
+ Content(render({ Name, rustcrate, auth, features, candidates }))
71
+ })
72
+ })
73
+
74
+
75
+ type Candidate = {
76
+ name: string, fn: string, sfn: string, method: string, op: string, params: string[]
77
+ }
78
+
79
+
80
+ // Every path parameter an operation's points declare, as the generated
81
+ // config carries them (points[].args.params[].name).
82
+ function pointParams(opdef: any): string[] {
83
+ const names: string[] = []
84
+ for (const point of opdef?.points || []) {
85
+ for (const p of point?.args?.params || []) {
86
+ if ('string' === typeof p?.name && !names.includes(p.name)) names.push(p.name)
87
+ }
88
+ }
89
+ return names
90
+ }
91
+
92
+
93
+ function render(spec: {
94
+ Name: string,
95
+ rustcrate: string,
96
+ auth: { suppressed: boolean, where: string, name: string, basic: boolean },
97
+ features: string[],
98
+ candidates: Candidate[],
99
+ }): string {
100
+ const { Name, rustcrate, auth, features, candidates } = spec
101
+
102
+ const drivers = candidates.map((c) => 'list' === c.op
103
+ ? `fn ${c.fn}(sdk: &Rc<${Name}SDK>, mtch: Value, ctrl: Value) -> Result<Value, ${Name}Error> {
104
+ sdk.${c.method}(Value::Noval)
105
+ .list(mtch, ctrl)
106
+ .map(|items| Value::list(items.iter().map(|e| e.data(None)).collect()))
107
+ }
108
+ `
109
+ : `fn ${c.fn}(sdk: &Rc<${Name}SDK>, mtch: Value, ctrl: Value) -> Result<Value, ${Name}Error> {
110
+ sdk.${c.method}(Value::Noval)
111
+ .${c.op}(mtch, ctrl)
112
+ .map(|e| e.data(None))
113
+ }
114
+ `).join('\n') + '\n' + candidates.map((c) =>
115
+ `fn ${c.sfn}(sdk: &Rc<${Name}SDK>, mtch: Value, callopts: Value) -> Result<Vec<Value>, ${Name}Error> {
116
+ sdk.${c.method}(Value::Noval).stream("${c.op}", mtch, callopts).map(|items| items.collect())
117
+ }
118
+ `).join('\n')
119
+
120
+ const table = candidates.map((c) => ` ("${c.name}", ${c.fn}, ${c.sfn}, &[${
121
+ c.params.map((p) => '"' + ruststr(p) + '"').join(', ')}]),`).join('\n')
122
+
123
+ return `// Generated canary sweep (see TestClean_rust): no credential leaves the
124
+ // SDK in any form, and the sweep can see one when clean is switched off.
125
+
126
+ #![allow(dead_code, unused_imports)]
127
+
128
+ use std::cell::RefCell;
129
+ use std::rc::Rc;
130
+
131
+ use ${rustcrate}::core::helpers::{getp, getpath, jo, json_thunk, setp, vfn};
132
+ use ${rustcrate}::core::types::OutVal;
133
+ use ${rustcrate}::utility::clean;
134
+ use ${rustcrate}::utility::voxgigstruct as vs;
135
+ use ${rustcrate}::{
136
+ Context, CtxSpec, Entity, Feature, FeatureRef, ${Name}Entity, ${Name}Error, ${Name}SDK, Value,
137
+ };
138
+
139
+ // Generated: the credential's wire placement is fixed when the SDK is built.
140
+ const AUTH_SUPPRESSED: bool = ${auth.suppressed};
141
+ const AUTH_WHERE: &str = "${ruststr(auth.where)}";
142
+ const AUTH_NAME: &str = "${ruststr(auth.name)}";
143
+ const AUTH_BASIC: bool = ${auth.basic};
144
+
145
+ // The diagnostic features this SDK ships.
146
+ const FEATURES: &[&str] = &[${features.map((f) => '"' + f + '"').join(', ')}];
147
+
148
+ const CANARY_APIKEY: &str = "CANARY-APIKEY-k9x2m7q4p1";
149
+ const CANARY_SECRET: &str = "CANARY-SECRET-w3e8r5t2y6";
150
+ const CANARY_HEADER: &str = "CANARY-HEADER-z1x4c7v0b3";
151
+ const CANARY_VALUE: &str = "CANARY-VALUE-n5m8b2v9c4";
152
+
153
+ const MASK: &str = "[redacted]";
154
+
155
+ // The sweep's own encoders: a leak of an encoded form must not hide behind
156
+ // the SDK's encoder.
157
+ fn b64(input: &str) -> String {
158
+ const ALPHABET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
159
+ let bytes = input.as_bytes();
160
+ let mut out = String::new();
161
+ for chunk in bytes.chunks(3) {
162
+ let b0 = chunk[0] as usize;
163
+ let b1 = *chunk.get(1).unwrap_or(&0) as usize;
164
+ let b2 = *chunk.get(2).unwrap_or(&0) as usize;
165
+ out.push(ALPHABET[b0 >> 2] as char);
166
+ out.push(ALPHABET[((b0 & 0x03) << 4) | (b1 >> 4)] as char);
167
+ out.push(if 1 < chunk.len() { ALPHABET[((b1 & 0x0f) << 2) | (b2 >> 6)] as char } else { '=' });
168
+ out.push(if 2 < chunk.len() { ALPHABET[b2 & 0x3f] as char } else { '=' });
169
+ }
170
+ out
171
+ }
172
+
173
+ fn pct(input: &str) -> String {
174
+ let mut out = String::new();
175
+ for b in input.bytes() {
176
+ let c = b as char;
177
+ if c.is_ascii_alphanumeric() || "-_.!~*'()".contains(c) {
178
+ out.push(c);
179
+ } else {
180
+ out.push_str(&format!("%{:02X}", b));
181
+ }
182
+ }
183
+ out
184
+ }
185
+
186
+ // Every form a canary can travel in.
187
+ fn forms() -> Vec<String> {
188
+ let mut out: Vec<String> = Vec::new();
189
+ for v in [CANARY_APIKEY, CANARY_SECRET, CANARY_HEADER, CANARY_VALUE] {
190
+ out.push(v.to_string());
191
+ out.push(b64(v));
192
+ out.push(pct(v));
193
+ }
194
+ out.push(b64(&format!("{}:{}", CANARY_APIKEY, CANARY_SECRET)));
195
+ out
196
+ }
197
+
198
+ struct Sink {
199
+ name: String,
200
+ text: String,
201
+ }
202
+
203
+ type Sinks = Rc<RefCell<Vec<Sink>>>;
204
+
205
+ fn push(sinks: &Sinks, name: &str, text: String) {
206
+ sinks.borrow_mut().push(Sink { name: name.to_string(), text });
207
+ }
208
+
209
+ fn push_value(sinks: &Sinks, name: &str, val: &Value) {
210
+ push(sinks, &format!("{}:json", name), vs::jsonify(val, None));
211
+ push(sinks, &format!("{}:debug", name), format!("{:?}", val));
212
+ push(sinks, &format!("{}:string", name), vs::stringify(val, None, false));
213
+ }
214
+
215
+ fn push_error(sinks: &Sinks, name: &str, err: &${Name}Error) {
216
+ push(sinks, &format!("{}:message", name), err.to_string());
217
+ push(sinks, &format!("{}:debug", name), format!("{:?}", err));
218
+ push(sinks, &format!("{}:json", name), err.to_json());
219
+ }
220
+
221
+ fn capture(sinks: &Sinks, name: &'static str) -> Value {
222
+ let sinks = sinks.clone();
223
+ vfn(move |rec| {
224
+ push_value(&sinks, name, rec);
225
+ Value::Noval
226
+ })
227
+ }
228
+
229
+ // Captures the serialised context from inside the pipeline: what a hook
230
+ // author would hand to a logger.
231
+ struct CaptureFeature {
232
+ sinks: Sinks,
233
+ }
234
+
235
+ impl CaptureFeature {
236
+ fn grab(&self, name: &str, ctx: &Rc<Context>) {
237
+ push(&self.sinks, &format!("{}:debug", name), format!("{:?}", ctx));
238
+ push(&self.sinks, &format!("{}:display", name), format!("{}", ctx));
239
+ push_value(&self.sinks, name, &ctx.to_value());
240
+ }
241
+ }
242
+
243
+ impl Feature for CaptureFeature {
244
+ fn name(&self) -> String {
245
+ "capture".to_string()
246
+ }
247
+ fn active(&self) -> bool {
248
+ true
249
+ }
250
+ fn pre_request(&mut self, ctx: &Rc<Context>) {
251
+ self.grab("ctx@PreRequest", ctx);
252
+ }
253
+ fn pre_response(&mut self, ctx: &Rc<Context>) {
254
+ self.grab("ctx@PreResponse", ctx);
255
+ }
256
+ fn pre_unexpected(&mut self, ctx: &Rc<Context>) {
257
+ self.grab("ctx@PreUnexpected", ctx);
258
+ }
259
+ }
260
+
261
+ // A feature that fails the operation from inside the pipeline, quoting the
262
+ // request it saw. A rust hook has no error return, so it fails the result:
263
+ // an error make_error receives from a hook, not from the pipeline. For the
264
+ // same reason there is no variant failing in PreUnexpected: make_error has
265
+ // built and cleaned the error it returns before that hook runs.
266
+ struct ThrowFeature;
267
+
268
+ impl Feature for ThrowFeature {
269
+ fn name(&self) -> String {
270
+ "throwhook".to_string()
271
+ }
272
+ fn active(&self) -> bool {
273
+ true
274
+ }
275
+ fn pre_response(&mut self, ctx: &Rc<Context>) {
276
+ let spec = match ctx.spec.borrow().clone() {
277
+ Some(s) => s.borrow().to_value(),
278
+ None => Value::Noval,
279
+ };
280
+ let err = ctx.make_error("hook", &format!("hook saw {}", vs::jsonify(&spec, None)));
281
+ if let Some(res) = ctx.result.borrow().clone() {
282
+ res.borrow_mut().err = Some(err);
283
+ }
284
+ }
285
+ }
286
+
287
+ // A stream that succeeds, so the pipeline's terminal step never runs. A rust
288
+ // stream producer has no error channel, so no stream fails.
289
+ struct StreamOkFeature;
290
+
291
+ impl Feature for StreamOkFeature {
292
+ fn name(&self) -> String {
293
+ "streamok".to_string()
294
+ }
295
+ fn active(&self) -> bool {
296
+ true
297
+ }
298
+ fn pre_done(&mut self, ctx: &Rc<Context>) {
299
+ if let Some(res) = ctx.result.borrow().clone() {
300
+ let items: Vec<Value> = match res.borrow().resdata.clone() {
301
+ Value::List(l) => l.borrow().clone(),
302
+ Value::Noval | Value::Null => Vec::new(),
303
+ other => vec![other],
304
+ };
305
+ let stream: ${rustcrate}::core::result::StreamFn = Rc::new(move || items.clone());
306
+ res.borrow_mut().stream = Some(stream);
307
+ }
308
+ }
309
+ }
310
+
311
+ // A feature that refuses the operation with the SDK's own error, as rbac
312
+ // does, whose code quotes a registered value; it records the error
313
+ // PreUnexpected hands a hook.
314
+ struct DenyFeature {
315
+ sinks: Sinks,
316
+ }
317
+
318
+ impl Feature for DenyFeature {
319
+ fn name(&self) -> String {
320
+ "denyhook".to_string()
321
+ }
322
+ fn active(&self) -> bool {
323
+ true
324
+ }
325
+ fn pre_point(&mut self, ctx: &Rc<Context>) {
326
+ let err = ctx.make_error(&format!("denied:{}", CANARY_VALUE), "denied");
327
+ ctx.out_set("point", OutVal::Err(err));
328
+ }
329
+ fn pre_unexpected(&mut self, ctx: &Rc<Context>) {
330
+ let ctrl = ctx.ctrl.borrow().clone();
331
+ let err = ctrl.borrow().err.clone();
332
+ if let Some(err) = err {
333
+ push_error(&self.sinks, "error", &err);
334
+ }
335
+ }
336
+ }
337
+
338
+ fn response(status: i64, data: Value, headers: &[(&str, &str)]) -> Value {
339
+ let h = jo(vec![("content-type", Value::str("application/json"))]);
340
+ for (k, v) in headers {
341
+ setp(&h, k, Value::str(*v));
342
+ }
343
+ jo(vec![
344
+ ("status", Value::Num(status as f64)),
345
+ ("statusText", Value::str(if status < 400 { "OK" } else { "ERR" })),
346
+ ("headers", h),
347
+ ("body", Value::str(vs::jsonify(&data, None))),
348
+ ("json", json_thunk(data)),
349
+ ])
350
+ }
351
+
352
+ #[derive(Clone, Copy, PartialEq)]
353
+ enum Scenario {
354
+ Ok,
355
+ NotFound,
356
+ Server,
357
+ Transport,
358
+ NotJson,
359
+ }
360
+
361
+ const SCENARIOS: [Scenario; 5] = [
362
+ Scenario::Ok,
363
+ Scenario::NotFound,
364
+ Scenario::Server,
365
+ Scenario::Transport,
366
+ Scenario::NotJson,
367
+ ];
368
+
369
+ impl Scenario {
370
+ fn name(&self) -> &'static str {
371
+ match self {
372
+ Scenario::Ok => "ok",
373
+ Scenario::NotFound => "notfound",
374
+ Scenario::Server => "server",
375
+ Scenario::Transport => "transport",
376
+ Scenario::NotJson => "notjson",
377
+ }
378
+ }
379
+
380
+ fn respond(&self, url: &str) -> Value {
381
+ match self {
382
+ Scenario::Ok => response(
383
+ 200,
384
+ jo(vec![("id", Value::str("i1")), ("name", Value::str("n1"))]),
385
+ &[("x-session-token", "RESP-TOKEN-a1b2c3d4e5")],
386
+ ),
387
+ Scenario::NotFound => response(404, jo(vec![("error", Value::str("no such record"))]), &[]),
388
+ Scenario::Server => response(500, jo(vec![("error", Value::str("boom"))]), &[]),
389
+ Scenario::Transport => jo(vec![(
390
+ "__err__",
391
+ Value::str(format!("socket hang up (URL was: \\"{}\\")", url)),
392
+ )]),
393
+ Scenario::NotJson => jo(vec![
394
+ ("status", Value::Num(200.0)),
395
+ ("statusText", Value::str("OK")),
396
+ ("headers", Value::empty_map()),
397
+ ("body", Value::str("<html>")),
398
+ ("json", json_thunk(Value::Noval)),
399
+ ]),
400
+ }
401
+ }
402
+ }
403
+
404
+ // The transport seam: system.fetch is called with [url, fetchdef].
405
+ fn transport(scenario: Scenario) -> Value {
406
+ Value::func(move |_inj, args, _r, _st| {
407
+ let url = match vs::get_elem(args, &Value::Num(0.0), Value::Noval) {
408
+ Value::Str(s) => s,
409
+ _ => String::new(),
410
+ };
411
+ scenario.respond(&url)
412
+ })
413
+ }
414
+
415
+ fn make_sdk(
416
+ scenario: Scenario,
417
+ sinks: &Sinks,
418
+ cleanopts: Option<Value>,
419
+ extra: Vec<FeatureRef>,
420
+ ) -> Rc<${Name}SDK> {
421
+ let feature = Value::empty_map();
422
+ for name in FEATURES {
423
+ let fopts = jo(vec![("active", Value::Bool(true))]);
424
+ match *name {
425
+ "log" => setp(&fopts, "logger", capture(sinks, "log")),
426
+ "debug" => setp(&fopts, "onEntry", capture(sinks, "debug")),
427
+ "audit" => setp(&fopts, "sink", capture(sinks, "audit")),
428
+ "telemetry" => setp(&fopts, "exporter", capture(sinks, "telemetry")),
429
+ "cost" => setp(&fopts, "sink", capture(sinks, "cost")),
430
+ _ => {}
431
+ }
432
+ setp(&feature, name, fopts);
433
+ }
434
+
435
+ let clean = jo(vec![("values", Value::str(CANARY_VALUE))]);
436
+ if let Some(Value::Map(m)) = cleanopts {
437
+ for (k, v) in m.borrow().iter() {
438
+ setp(&clean, k, v.clone());
439
+ }
440
+ }
441
+
442
+ let sdk = ${Name}SDK::new(jo(vec![
443
+ ("apikey", Value::str(CANARY_APIKEY)),
444
+ ("secret", Value::str(CANARY_SECRET)),
445
+ ("headers", jo(vec![("X-Custom-Token", Value::str(CANARY_HEADER))])),
446
+ ("clean", clean),
447
+ ("feature", feature),
448
+ ("system", jo(vec![("fetch", transport(scenario))])),
449
+ ]));
450
+
451
+ // Rust options are pure data, so the extension feature is added after
452
+ // construction (the \`extend\` option of the ts client).
453
+ let f: FeatureRef = Rc::new(RefCell::new(CaptureFeature { sinks: sinks.clone() }));
454
+ sdk.features.borrow_mut().push(f);
455
+ sdk.features.borrow_mut().extend(extra);
456
+
457
+ sdk
458
+ }
459
+
460
+ type Drive = fn(&Rc<${Name}SDK>, Value, Value) -> Result<Value, ${Name}Error>;
461
+ type Stream = fn(&Rc<${Name}SDK>, Value, Value) -> Result<Vec<Value>, ${Name}Error>;
462
+
463
+ ${drivers}
464
+ // Generated: every CRUD operation of every active entity, list and load
465
+ // first (they need no body), with the path parameters its points declare.
466
+ const CANDIDATES: &[(&str, Drive, Stream, &[&str])] = &[
467
+ ${table}
468
+ ];
469
+
470
+ #[derive(Clone)]
471
+ struct Target {
472
+ drive: Drive,
473
+ stream: Stream,
474
+ mtch: Value,
475
+ }
476
+
477
+ // The first operation that completes against a plain 200: with no
478
+ // arguments, else with every path parameter its points declare filled in.
479
+ fn usable_op() -> Option<Target> {
480
+ let plain = ${Name}SDK::new(jo(vec![
481
+ ("apikey", Value::str(CANARY_APIKEY)),
482
+ ("system", jo(vec![("fetch", transport(Scenario::Ok))])),
483
+ ]));
484
+ for (_name, drive, stream, params) in CANDIDATES {
485
+ let filled = Value::empty_map();
486
+ for p in params.iter() {
487
+ setp(&filled, p, Value::str("p1"));
488
+ }
489
+ for mtch in [Value::empty_map(), filled] {
490
+ if drive(&plain, vs::clone(&mtch), Value::Noval).is_ok() {
491
+ return Some(Target { drive: *drive, stream: *stream, mtch });
492
+ }
493
+ }
494
+ }
495
+ None
496
+ }
497
+
498
+ const NOTHING_TO_SWEEP: &str =
499
+ "SKIP: no operation of this SDK completes against a plain 200; nothing to sweep";
500
+
501
+ fn same_node(a: &Value, b: &Value) -> bool {
502
+ match (a, b) {
503
+ (Value::Map(x), Value::Map(y)) => Rc::ptr_eq(x, y),
504
+ _ => false,
505
+ }
506
+ }
507
+
508
+ fn drive(sdk: &Rc<${Name}SDK>, target: &Target, ctrl: Value, sinks: &Sinks) -> Option<${Name}Error> {
509
+ // A caller may keep the record it passed rather than read ctrl.explain.
510
+ let held = getp(&ctrl, "explain");
511
+ let out = match (target.drive)(sdk, vs::clone(&target.mtch), ctrl.clone()) {
512
+ Ok(out) => {
513
+ push_value(sinks, "result", &out);
514
+ None
515
+ }
516
+ Err(err) => {
517
+ push_error(sinks, "error", &err);
518
+ Some(err)
519
+ }
520
+ };
521
+ let explain = getp(&ctrl, "explain");
522
+ if let Value::Map(_) = explain {
523
+ push_value(sinks, "explain", &explain);
524
+ }
525
+ if let Value::Map(_) = held {
526
+ if !same_node(&held, &explain) {
527
+ push_value(sinks, "explain:held", &held);
528
+ }
529
+ }
530
+ out
531
+ }
532
+
533
+ // Header maps keep the caller's spelling; the assertion should not care.
534
+ fn header(map: &Value, name: &str) -> Option<String> {
535
+ if let Value::Map(m) = map {
536
+ for (k, v) in m.borrow().iter() {
537
+ if k.to_lowercase() == name.to_lowercase() {
538
+ return match v {
539
+ Value::Str(s) => Some(s.clone()),
540
+ other => Some(vs::stringify(other, None, false)),
541
+ };
542
+ }
543
+ }
544
+ }
545
+ None
546
+ }
547
+
548
+ fn leaks(text: &str) -> Vec<String> {
549
+ forms().into_iter().filter(|f| text.contains(f.as_str())).collect()
550
+ }
551
+
552
+ #[test]
553
+ fn clean_no_credential_leaves_the_sdk_in_any_form() {
554
+ let Some(target) = usable_op() else {
555
+ println!("{}", NOTHING_TO_SWEEP);
556
+ return;
557
+ };
558
+
559
+ let sinks: Sinks = Rc::new(RefCell::new(Vec::new()));
560
+ let mut errors: Vec<(String, ${Name}Error)> = Vec::new();
561
+ let mut explains: Vec<(String, Value)> = Vec::new();
562
+
563
+ for scenario in SCENARIOS {
564
+ for variant in ["throw", "explain", "nothrow"] {
565
+ let sdk = make_sdk(scenario, &sinks, None, Vec::new());
566
+ let explain = Value::empty_map();
567
+ let ctrl = match variant {
568
+ "explain" => jo(vec![("explain", explain.clone())]),
569
+ "nothrow" => jo(vec![("throw", Value::Bool(false)), ("explain", explain.clone())]),
570
+ _ => Value::Noval,
571
+ };
572
+ let key = format!("{}/{}", scenario.name(), variant);
573
+ if let Some(err) = drive(&sdk, &target, ctrl, &sinks) {
574
+ errors.push((key.clone(), err));
575
+ }
576
+ if "throw" != variant {
577
+ explains.push((key, explain));
578
+ }
579
+ push(&sinks, "sdk:debug", format!("{:?}", sdk));
580
+ push(&sinks, "sdk:display", format!("{}", sdk));
581
+ }
582
+ }
583
+
584
+ // A credential mistyped as a map. The rust validator does not reject it
585
+ // (make_options keeps its input when validation fails), so what the
586
+ // constructor produced is swept instead: the client's prints, and a
587
+ // string quoting the value, cleaned the way a validation message is.
588
+ let mistyped = ${Name}SDK::new(jo(vec![
589
+ ("apikey", jo(vec![("value", Value::str(CANARY_APIKEY))])),
590
+ ("clean", jo(vec![("values", Value::str(CANARY_VALUE))])),
591
+ ]));
592
+ push(&sinks, "mistyped:debug", format!("{:?}", mistyped));
593
+ push(&sinks, "mistyped:display", format!("{}", mistyped));
594
+ push(
595
+ &sinks,
596
+ "mistyped:quoted",
597
+ clean::clean_str(
598
+ &mistyped.get_root_ctx(),
599
+ &format!("apikey: expected string, got {{\\"value\\":\\"{}\\"}}", CANARY_APIKEY),
600
+ ),
601
+ );
602
+
603
+ // An error a feature hook raises, quoting the request, with explain on.
604
+ let hooked = make_sdk(
605
+ Scenario::Ok,
606
+ &sinks,
607
+ None,
608
+ vec![Rc::new(RefCell::new(ThrowFeature)) as FeatureRef],
609
+ );
610
+ let hookerr = drive(&hooked, &target, jo(vec![("explain", Value::empty_map())]), &sinks);
611
+ assert!(hookerr.is_some(), "the throwing hook should fail the operation");
612
+
613
+ // The explain record a stream call is passed is cleaned however the
614
+ // stream ends: from a feature's producer, or materialised by done.
615
+ for (name, extra) in [
616
+ ("stream-ok", vec![Rc::new(RefCell::new(StreamOkFeature)) as FeatureRef]),
617
+ ("stream-plain", Vec::new()),
618
+ ] {
619
+ let streamed = make_sdk(Scenario::Ok, &sinks, None, extra);
620
+ let explain = Value::empty_map();
621
+ let callopts = jo(vec![("ctrl", jo(vec![("explain", explain.clone())]))]);
622
+ let items = (target.stream)(&streamed, vs::clone(&target.mtch), callopts);
623
+ assert!(items.is_ok(), "{}: only a failing stream raises", name);
624
+ assert!(
625
+ matches!(&explain, Value::Map(m) if 0 < m.borrow().len()),
626
+ "{}: the explain record was not filled",
627
+ name
628
+ );
629
+ push_value(&sinks, &format!("{}:explain", name), &explain);
630
+ }
631
+
632
+ // A feature's own error keeps its code, which is cleaned like the
633
+ // message: returned, handed to a hook, and cleaned where a step's error
634
+ // skips make_error.
635
+ let denier = make_sdk(
636
+ Scenario::Ok,
637
+ &sinks,
638
+ None,
639
+ vec![Rc::new(RefCell::new(DenyFeature { sinks: sinks.clone() })) as FeatureRef],
640
+ );
641
+ let denied = drive(&denier, &target, Value::Noval, &sinks)
642
+ .expect("the refusing hook should fail the operation");
643
+ let stepped = clean::clean_error(
644
+ &denier.get_root_ctx(),
645
+ ${Name}Error::new(&format!("stepped:{}", CANARY_VALUE), "stepped"),
646
+ );
647
+ push_error(&sinks, "stepped", &stepped);
648
+
649
+ // A client given no clean block at all masks by the schema defaults.
650
+ let bare = ${Name}SDK::new(jo(vec![
651
+ ("apikey", Value::str(CANARY_APIKEY)),
652
+ ("secret", Value::str(CANARY_SECRET)),
653
+ ("headers", jo(vec![("X-Custom-Token", Value::str(CANARY_HEADER))])),
654
+ ("system", jo(vec![("fetch", transport(Scenario::NotFound))])),
655
+ ]));
656
+ let barerr = drive(&bare, &target, Value::Noval, &sinks)
657
+ .expect("the 404 scenario must throw without a clean block");
658
+
659
+ // The raw path returns its failure rather than an error.
660
+ let raw = make_sdk(Scenario::Transport, &sinks, None, Vec::new())
661
+ .direct(jo(vec![("path", Value::str("raw"))]))
662
+ .expect("direct() returns its failure as data");
663
+ assert_eq!(getp(&raw, "ok"), Value::Bool(false), "a transport failure should fail direct()");
664
+ push_value(&sinks, "direct", &raw);
665
+
666
+ let leaked: Vec<String> = sinks
667
+ .borrow()
668
+ .iter()
669
+ .filter_map(|s| {
670
+ let found = leaks(&s.text);
671
+ if found.is_empty() {
672
+ None
673
+ } else {
674
+ Some(format!("{} [{}]", s.name, found.join(", ")))
675
+ }
676
+ })
677
+ .collect();
678
+
679
+ println!(
680
+ "clean: swept {} surface(s), {} leak(s)",
681
+ sinks.borrow().len(),
682
+ leaked.len()
683
+ );
684
+
685
+ assert!(leaked.is_empty(), "credential leaked through: {}", leaked.join("; "));
686
+
687
+ // The positive half: the slot the credential travelled in is masked,
688
+ // and an unregistered token in a response header is masked by name.
689
+ let notfound = errors
690
+ .iter()
691
+ .find(|(k, _)| k == "notfound/throw")
692
+ .map(|(_, e)| e.clone())
693
+ .expect("the 404 scenario must throw");
694
+ assert_eq!(notfound.status, 404);
695
+
696
+ let headers = getp(&notfound.spec, "headers");
697
+ if !AUTH_SUPPRESSED {
698
+ if "query" == AUTH_WHERE {
699
+ assert_eq!(header(&getp(&notfound.spec, "query"), AUTH_NAME), Some(MASK.to_string()));
700
+ } else if "cookie" == AUTH_WHERE {
701
+ let cookie = header(&headers, "cookie").unwrap_or_default();
702
+ assert!(cookie.contains(MASK), "cookie: {}", cookie);
703
+ } else {
704
+ let cred = header(&headers, AUTH_NAME).unwrap_or_default();
705
+ assert!(cred.ends_with(MASK), "{}: {}", AUTH_NAME, cred);
706
+ }
707
+ }
708
+ assert_eq!(header(&headers, "x-custom-token"), Some(MASK.to_string()));
709
+ assert_eq!(denied.code, format!("denied:{}", MASK));
710
+ assert_eq!(stepped.code, format!("stepped:{}", MASK));
711
+ assert_eq!(
712
+ header(&getp(&barerr.spec, "headers"), "x-custom-token"),
713
+ Some(MASK.to_string())
714
+ );
715
+
716
+ let explained = explains
717
+ .iter()
718
+ .find(|(k, _)| k == "ok/explain")
719
+ .map(|(_, e)| e.clone())
720
+ .unwrap_or(Value::Noval);
721
+ let result = getp(&explained, "result");
722
+ assert!(matches!(result, Value::Map(_)), "the explain record should carry the result");
723
+ assert_eq!(header(&getp(&result, "headers"), "x-session-token"), Some(MASK.to_string()));
724
+ }
725
+
726
+ #[test]
727
+ fn clean_the_sweep_can_see_a_leak() {
728
+ let Some(target) = usable_op() else {
729
+ println!("{}", NOTHING_TO_SWEEP);
730
+ return;
731
+ };
732
+
733
+ let sinks: Sinks = Rc::new(RefCell::new(Vec::new()));
734
+ let sdk = make_sdk(
735
+ Scenario::NotFound,
736
+ &sinks,
737
+ Some(jo(vec![("active", Value::Bool(false))])),
738
+ Vec::new(),
739
+ );
740
+ let err = drive(&sdk, &target, Value::Noval, &sinks).expect("the 404 scenario must throw");
741
+
742
+ // Explaining a failure must not cost it its error.
743
+ let quiet: Sinks = Rc::new(RefCell::new(Vec::new()));
744
+ let explained = drive(
745
+ &make_sdk(Scenario::NotFound, &quiet, Some(jo(vec![("active", Value::Bool(false))])), Vec::new()),
746
+ &target,
747
+ jo(vec![("explain", Value::empty_map())]),
748
+ &quiet,
749
+ );
750
+ assert_eq!(
751
+ explained.map(|e| e.msg),
752
+ Some(err.msg.clone()),
753
+ "with clean off, explain lost the error"
754
+ );
755
+
756
+ let leaked = sinks.borrow().iter().filter(|s| !leaks(&s.text).is_empty()).count();
757
+ assert!(0 < leaked, "with clean off, nothing showed the canary: the sweep is blind");
758
+
759
+ if !AUTH_SUPPRESSED {
760
+ let text = vs::jsonify(&err.spec, None);
761
+ assert!(
762
+ text.contains(CANARY_APIKEY)
763
+ || text.contains(&b64(&format!("{}:{}", CANARY_APIKEY, CANARY_SECRET))),
764
+ "the raw spec should carry the credential when clean is off"
765
+ );
766
+ }
767
+ let _ = AUTH_BASIC;
768
+ }
769
+
770
+ #[test]
771
+ fn clean_masks_a_registered_value_used_as_a_name() {
772
+ let sdk = ${Name}SDK::new(jo(vec![(
773
+ "clean",
774
+ jo(vec![("values", Value::str("ZZVAL-abc123,ZZVAL-xyz789"))]),
775
+ )]));
776
+ let out = clean::clean_util(
777
+ &sdk.get_root_ctx(),
778
+ &jo(vec![
779
+ ("ZZVAL-abc123", Value::Num(1.0)),
780
+ ("ZZVAL-xyz789", Value::Num(2.0)),
781
+ ("plain", Value::Num(3.0)),
782
+ ]),
783
+ );
784
+ let keys: Vec<String> = match &out {
785
+ Value::Map(m) => m.borrow().iter().map(|(k, _)| k.clone()).collect(),
786
+ _ => Vec::new(),
787
+ };
788
+ assert_eq!(keys, vec![MASK.to_string(), format!("{}#1", MASK), "plain".to_string()]);
789
+ }
790
+
791
+ // A feature's name is not a field name: a feature called secrets does not
792
+ // make its settings secret, though a sensitive field inside it still is. An
793
+ // entity block, of per-entity settings or seeded records keyed by entity name
794
+ // and id, is not read at all.
795
+ #[test]
796
+ fn clean_reads_a_feature_name_as_a_name() {
797
+ let seeded = jo(vec![(
798
+ "zztoken",
799
+ jo(vec![("ZZTOKEN01", jo(vec![("note", Value::str("PLAINRECORD-t5r3e1w9"))]))]),
800
+ )]);
801
+ let sdk = ${Name}SDK::new(jo(vec![
802
+ ("apikey", Value::str(CANARY_APIKEY)),
803
+ (
804
+ "feature",
805
+ jo(vec![
806
+ (
807
+ "secrets",
808
+ jo(vec![
809
+ ("active", Value::Bool(false)),
810
+ ("name", Value::str("ZZNAME-feat123")),
811
+ ("token", Value::str("ZZTOKEN-feat456")),
812
+ ]),
813
+ ),
814
+ ("test", jo(vec![("active", Value::Bool(false)), ("entity", seeded)])),
815
+ ]),
816
+ ),
817
+ (
818
+ "entity",
819
+ jo(vec![(
820
+ "zztoken",
821
+ jo(vec![("alias", jo(vec![("zzkey", Value::str("PLAINALIAS-m2n4b6v8"))]))]),
822
+ )]),
823
+ ),
824
+ ]));
825
+ let ctx = sdk.get_root_ctx();
826
+ assert_eq!(
827
+ clean::clean_str(&ctx, "ZZNAME-feat123 ZZTOKEN-feat456"),
828
+ format!("ZZNAME-feat123 {}", MASK)
829
+ );
830
+ assert_eq!(clean::clean_str(&ctx, "record PLAINRECORD-t5r3e1w9"), "record PLAINRECORD-t5r3e1w9");
831
+ assert_eq!(clean::clean_str(&ctx, "alias PLAINALIAS-m2n4b6v8"), "alias PLAINALIAS-m2n4b6v8");
832
+ }
833
+
834
+ #[test]
835
+ fn clean_honours_the_generated_config_clean_block() {
836
+ let utility = ${Name}SDK::new(Value::empty_map()).get_utility();
837
+ let config = jo(vec![(
838
+ "options",
839
+ jo(vec![(
840
+ "clean",
841
+ jo(vec![("keys", Value::str("zzsens")), ("values", Value::str("CONFIG-SEEDED-1"))]),
842
+ )]),
843
+ )]);
844
+ let ctx = utility.make_context(
845
+ CtxSpec {
846
+ options: Some(jo(vec![(
847
+ "clean",
848
+ jo(vec![("values", Value::str("CALLER-SEEDED-2"))]),
849
+ )])),
850
+ config: Some(config.clone()),
851
+ ..Default::default()
852
+ },
853
+ None,
854
+ );
855
+ let opts = utility.make_options(&ctx);
856
+ *ctx.options.borrow_mut() = opts;
857
+ assert_eq!(
858
+ clean::clean_str(&ctx, "a CONFIG-SEEDED-1 b CALLER-SEEDED-2"),
859
+ format!("a {} b {}", MASK, MASK)
860
+ );
861
+ let out = clean::clean_util(
862
+ &ctx,
863
+ &jo(vec![("my_zzsens", Value::str("x")), ("other", Value::str("y"))]),
864
+ );
865
+ assert_eq!(getp(&out, "my_zzsens"), Value::str(MASK));
866
+ assert_eq!(getp(&out, "other"), Value::str("y"));
867
+ assert_eq!(getpath(&["options", "clean", "keys"], &config), Value::str("zzsens"));
868
+ assert_eq!(getpath(&["options", "clean", "values"], &config), Value::str("CONFIG-SEEDED-1"));
869
+ }
870
+ `
871
+ }
872
+
873
+
874
+ function ruststr(s: string): string {
875
+ return String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
876
+ }
877
+
878
+
879
+ export {
880
+ TestClean
881
+ }