@voxgig/sdkgen 4.32.1 → 4.34.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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/action/copies.d.ts +21 -0
- package/dist/action/copies.js +146 -0
- package/dist/action/copies.js.map +1 -0
- package/dist/action/doctor.d.ts +15 -2
- package/dist/action/doctor.js +169 -23
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/edition.js +6 -2
- package/dist/action/edition.js.map +1 -1
- package/dist/action/feature.js +6 -2
- package/dist/action/feature.js.map +1 -1
- package/dist/action/package.js +28 -10
- package/dist/action/package.js.map +1 -1
- package/dist/action/remove.js +2 -0
- package/dist/action/remove.js.map +1 -1
- package/dist/action/resolve.d.ts +1 -0
- package/dist/action/resolve.js +10 -2
- package/dist/action/resolve.js.map +1 -1
- package/dist/action/target.js +6 -2
- package/dist/action/target.js.map +1 -1
- package/dist/helpers/naming.js +1 -1
- package/dist/helpers/naming.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -1
- package/dist/sdkgen.js +36 -3
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/sdkgen.aontu +7 -1
- package/package.json +1 -1
- package/project/.sdk/model/feature/debug.aontu +3 -1
- package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
- package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
- package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
- package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
- package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
- package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
- package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
- package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
- package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
- package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
- package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
- package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
- package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
- package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
- package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
- package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
- package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
- package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
- package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
- package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
- package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
- package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
- package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
- package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
- package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
- package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
- package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
- package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
- package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
- package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
- package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
- package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
- package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
- package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
- package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
- package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
- package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
- package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
- package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
- package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
- package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
- package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
- package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
- package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
- package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
- package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
- package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
- package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
- package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
- package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
- package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
- package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
- package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
- package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
- package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
- package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
- package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
- package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
- package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
- package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
- package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
- package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
- package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
- package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
- package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
- package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
- package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
- package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
- package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
- package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
- package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
- package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
- package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
- package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
- package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
- package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
- package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
- package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
- package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
- package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
- package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
- package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
- package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
- package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
- package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
- package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
- package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
- package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
- package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
- package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
- package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
- package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
- package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
- package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
- package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
- package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
- package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
- package/project/.sdk/tm/c/core/context.c +25 -0
- package/project/.sdk/tm/c/core/error.c +16 -0
- package/project/.sdk/tm/c/core/sdk.h +22 -0
- package/project/.sdk/tm/c/feature/audit.c +2 -0
- package/project/.sdk/tm/c/feature/cost.c +1 -0
- package/project/.sdk/tm/c/feature/debug.c +19 -29
- package/project/.sdk/tm/c/feature/log.c +21 -2
- package/project/.sdk/tm/c/feature/proxy.c +55 -3
- package/project/.sdk/tm/c/feature/secrets.c +7 -0
- package/project/.sdk/tm/c/feature/telemetry.c +2 -0
- package/project/.sdk/tm/c/tests/feature_test.c +2 -2
- package/project/.sdk/tm/c/utility/clean.c +530 -8
- package/project/.sdk/tm/c/utility/done.c +28 -12
- package/project/.sdk/tm/c/utility/make_error.c +4 -3
- package/project/.sdk/tm/c/utility/make_options.c +71 -45
- package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
- package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
- package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
- package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
- package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
- package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
- package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
- package/project/.sdk/tm/cpp/core/types.hpp +93 -3
- package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
- package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
- package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
- package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
- package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
- package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
- package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
- package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
- package/project/.sdk/tm/csharp/core/Context.cs +32 -0
- package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
- package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
- package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
- package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
- package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
- package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
- package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
- package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
- package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
- package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
- package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
- package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
- package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
- package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
- package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
- package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
- package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
- package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
- package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
- package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
- package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
- package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
- package/project/.sdk/tm/go/core/context.go +42 -0
- package/project/.sdk/tm/go/core/error.go +30 -10
- package/project/.sdk/tm/go/core/utility_type.go +2 -0
- package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
- package/project/.sdk/tm/go/feature/base_feature.go +12 -0
- package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
- package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
- package/project/.sdk/tm/go/feature/log_feature.go +13 -8
- package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
- package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
- package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
- package/project/.sdk/tm/go/test/feature_test.go +2 -2
- package/project/.sdk/tm/go/utility/clean.go +585 -2
- package/project/.sdk/tm/go/utility/done.go +29 -9
- package/project/.sdk/tm/go/utility/make_error.go +51 -16
- package/project/.sdk/tm/go/utility/make_options.go +77 -36
- package/project/.sdk/tm/go/utility/register.go +12 -0
- package/project/.sdk/tm/java/core/Context.java +29 -0
- package/project/.sdk/tm/java/core/SdkClient.java +4 -2
- package/project/.sdk/tm/java/core/Utility.java +7 -0
- package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
- package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
- package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
- package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
- package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
- package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
- package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
- package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
- package/project/.sdk/tm/java/utility/Clean.java +519 -1
- package/project/.sdk/tm/java/utility/Done.java +1 -1
- package/project/.sdk/tm/java/utility/MakeError.java +5 -1
- package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
- package/project/.sdk/tm/java/utility/Register.java +4 -0
- package/project/.sdk/tm/js/src/Context.js +5 -1
- package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
- package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
- package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
- package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
- package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
- package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
- package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
- package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
- package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
- package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
- package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
- package/project/.sdk/tm/js/test/feature/harness.js +11 -1
- package/project/.sdk/tm/js/test/feature.test.js +9 -2
- package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
- package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
- package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
- package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
- package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
- package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
- package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
- package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
- package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
- package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
- package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
- package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
- package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
- package/project/.sdk/tm/lua/core/context.lua +43 -0
- package/project/.sdk/tm/lua/core/error.lua +36 -1
- package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
- package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
- package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
- package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
- package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
- package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
- package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
- package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
- package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
- package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
- package/project/.sdk/tm/lua/utility/clean.lua +426 -2
- package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
- package/project/.sdk/tm/lua/utility/done.lua +1 -7
- package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
- package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
- package/project/.sdk/tm/lua/utility/register.lua +4 -1
- package/project/.sdk/tm/ocaml/Makefile +5 -1
- package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
- package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
- package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
- package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
- package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
- package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
- package/project/.sdk/tm/perl/core/context.pm +27 -0
- package/project/.sdk/tm/perl/core/error.pm +52 -5
- package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
- package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
- package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
- package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
- package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
- package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
- package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
- package/project/.sdk/tm/perl/t/feature.t +4 -2
- package/project/.sdk/tm/perl/utility/clean.pm +345 -1
- package/project/.sdk/tm/perl/utility/done.pm +24 -6
- package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
- package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
- package/project/.sdk/tm/php/core/Context.php +24 -1
- package/project/.sdk/tm/php/core/Error.php +34 -3
- package/project/.sdk/tm/php/core/UtilityType.php +4 -0
- package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
- package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
- package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
- package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
- package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
- package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
- package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
- package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
- package/project/.sdk/tm/php/utility/Clean.php +438 -2
- package/project/.sdk/tm/php/utility/Done.php +14 -7
- package/project/.sdk/tm/php/utility/MakeError.php +9 -7
- package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
- package/project/.sdk/tm/php/utility/Register.php +2 -0
- package/project/.sdk/tm/py/pkg/core/context.py +17 -0
- package/project/.sdk/tm/py/pkg/core/error.py +42 -1
- package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
- package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
- package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
- package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
- package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
- package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
- package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
- package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
- package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
- package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
- package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
- package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
- package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
- package/project/.sdk/tm/py/test/feature_harness.py +4 -0
- package/project/.sdk/tm/py/test/test_feature.py +2 -2
- package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
- package/project/.sdk/tm/rb/core/context.rb +28 -0
- package/project/.sdk/tm/rb/core/error.rb +30 -0
- package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
- package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
- package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
- package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
- package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
- package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
- package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
- package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
- package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
- package/project/.sdk/tm/rb/utility/clean.rb +312 -1
- package/project/.sdk/tm/rb/utility/done.rb +15 -5
- package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
- package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
- package/project/.sdk/tm/rb/utility/register.rb +2 -0
- package/project/.sdk/tm/rust/core/context.rs +55 -0
- package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
- package/project/.sdk/tm/rust/feature/audit.rs +2 -0
- package/project/.sdk/tm/rust/feature/cost.rs +3 -2
- package/project/.sdk/tm/rust/feature/debug.rs +16 -16
- package/project/.sdk/tm/rust/feature/log.rs +42 -7
- package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
- package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
- package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
- package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
- package/project/.sdk/tm/rust/utility/clean.rs +446 -5
- package/project/.sdk/tm/rust/utility/done.rs +22 -12
- package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
- package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
- package/project/.sdk/tm/scala/Makefile +3 -1
- package/project/.sdk/tm/scala/core/Context.scala +16 -0
- package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
- package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
- package/project/.sdk/tm/scala/core/Types.scala +3 -0
- package/project/.sdk/tm/scala/core/Utility.scala +2 -0
- package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
- package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
- package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
- package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
- package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
- package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
- package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
- package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
- package/project/.sdk/tm/scala/utility/Make.scala +63 -20
- package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
- package/project/.sdk/tm/scala/utility/Register.scala +1 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
- package/project/.sdk/tm/ts/src/Context.ts +5 -1
- package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
- package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
- package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
- package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
- package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
- package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
- package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
- package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
- package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
- package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
- package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
- package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
- package/project/.sdk/tm/zig/core/context.zig +34 -0
- package/project/.sdk/tm/zig/core/error.zig +22 -1
- package/project/.sdk/tm/zig/core/utility.zig +403 -39
- package/project/.sdk/tm/zig/feature/audit.zig +4 -2
- package/project/.sdk/tm/zig/feature/cost.zig +3 -2
- package/project/.sdk/tm/zig/feature/debug.zig +20 -25
- package/project/.sdk/tm/zig/feature/log.zig +3 -1
- package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
- package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
- package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
- package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
- package/project/sdkgen-package.json +1 -1
- package/src/action/copies.ts +219 -0
- package/src/action/doctor.ts +247 -21
- package/src/action/edition.ts +10 -2
- package/src/action/feature.ts +11 -2
- package/src/action/package.ts +31 -10
- package/src/action/remove.ts +4 -0
- package/src/action/resolve.ts +16 -3
- package/src/action/target.ts +10 -2
- package/src/helpers/naming.ts +1 -1
- package/src/sdkgen.ts +45 -5
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cmp,
|
|
3
|
+
each,
|
|
4
|
+
entityCollection,
|
|
5
|
+
File,
|
|
6
|
+
Content,
|
|
7
|
+
isAuthSuppressed,
|
|
8
|
+
isHttpBasicAuth,
|
|
9
|
+
resolveAuthIn,
|
|
10
|
+
resolveAuthName,
|
|
11
|
+
} from '@voxgig/sdkgen'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import { swiftString } from './utility_swift'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
// The canary sweep, the swift twin of TestClean_ts.ts. The entity accessors
|
|
18
|
+
// and their operations are typed methods, so the candidates the sweep drives
|
|
19
|
+
// are emitted from the model rather than found by walking the client at run
|
|
20
|
+
// time. The helper types nest in the test case: the swift type guard reads
|
|
21
|
+
// top-level declarations, and the Tests module is a namespace of its own.
|
|
22
|
+
const TestClean = cmp(function TestClean(props: any) {
|
|
23
|
+
const { model } = props.ctx$
|
|
24
|
+
const { target } = props
|
|
25
|
+
|
|
26
|
+
const auth = {
|
|
27
|
+
suppressed: isAuthSuppressed(model),
|
|
28
|
+
where: resolveAuthIn(model),
|
|
29
|
+
name: 'header' === resolveAuthIn(model)
|
|
30
|
+
? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
|
|
31
|
+
basic: isHttpBasicAuth(model),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Same order the ts sweep tries: list, then load, then the rest.
|
|
35
|
+
const rank: Record<string, number> = { list: 0, load: 1 }
|
|
36
|
+
const candidates = each(entityCollection(model))
|
|
37
|
+
.filter((e: any) => false !== e.active)
|
|
38
|
+
.map((e: any) => ({
|
|
39
|
+
name: e.name,
|
|
40
|
+
Name: e.Name,
|
|
41
|
+
ops: Object.keys(e.op || {})
|
|
42
|
+
.sort((a, b) => (rank[a] ?? 2) - (rank[b] ?? 2)),
|
|
43
|
+
params: Object.fromEntries(Object.keys(e.op || {})
|
|
44
|
+
.map((op: string) => [op, pointParams(e.op[op])])),
|
|
45
|
+
}))
|
|
46
|
+
.filter((c: any) => 0 < c.ops.length)
|
|
47
|
+
|
|
48
|
+
// Inside Tests/<Name>SdkTests already: Test_swift.ts opens those folders.
|
|
49
|
+
File({ name: 'CleanTest.' + target.ext }, () =>
|
|
50
|
+
Content(render(model.const.Name, auth, candidates)))
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// The path parameters an operation's points declare, as the runtime config
|
|
55
|
+
// carries them under points[].args.params.
|
|
56
|
+
function pointParams(opdef: any): string[] {
|
|
57
|
+
const names: string[] = []
|
|
58
|
+
for (const point of each(opdef?.points || [])) {
|
|
59
|
+
if (false === point?.a) continue
|
|
60
|
+
for (const arg of each(point?.g?.params || [])) {
|
|
61
|
+
if (false !== arg?.a && 'string' === typeof arg?.n && !names.includes(arg.n)) {
|
|
62
|
+
names.push(arg.n)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return names
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
function render(
|
|
71
|
+
Name: string,
|
|
72
|
+
auth: { suppressed: boolean, where: string, name: string, basic: boolean },
|
|
73
|
+
candidates: { name: string, Name: string, ops: string[], params: Record<string, string[]> }[],
|
|
74
|
+
): string {
|
|
75
|
+
const swiftList = (items: string[]) => '[' + items.map((i) => swiftString(i)).join(', ') + ']'
|
|
76
|
+
const candidateLines = candidates.map((c) =>
|
|
77
|
+
` Candidate(name: ${swiftString(c.name)}, accessor: { $0.${c.Name}(nil) }, ` +
|
|
78
|
+
`ops: ${swiftList(c.ops)}, params: [${c.ops.map((o) =>
|
|
79
|
+
swiftString(o) + ': ' + swiftList(c.params[o] || [])).join(', ')}]),`)
|
|
80
|
+
.join('\n')
|
|
81
|
+
|
|
82
|
+
return `// The canary sweep: every credential slot holds a distinctive value, every
|
|
83
|
+
// diagnostic feature this SDK ships is switched on with a capturing sink, a
|
|
84
|
+
// real operation runs through every outcome, and every string that leaves
|
|
85
|
+
// the SDK is searched for the canaries and their encoded forms. It also
|
|
86
|
+
// proves its own sensitivity: with clean switched off the canary MUST show.
|
|
87
|
+
|
|
88
|
+
import Foundation
|
|
89
|
+
import XCTest
|
|
90
|
+
|
|
91
|
+
@testable import ${Name}Sdk
|
|
92
|
+
|
|
93
|
+
// Generated: the credential's wire placement is fixed when the SDK is built.
|
|
94
|
+
private let authSuppressed = ${auth.suppressed ? 'true' : 'false'}
|
|
95
|
+
private let authWhere = ${swiftString(auth.where)}
|
|
96
|
+
private let authName = ${swiftString(auth.name)}
|
|
97
|
+
|
|
98
|
+
private let canaryApikey = "CANARY-APIKEY-k9x2m7q4p1"
|
|
99
|
+
private let canarySecret = "CANARY-SECRET-w3e8r5t2y6"
|
|
100
|
+
private let canaryHeader = "CANARY-HEADER-z1x4c7v0b3"
|
|
101
|
+
private let canaryValue = "CANARY-VALUE-n5m8b2v9c4"
|
|
102
|
+
private let canaryConfig = "CANARY-CONFIG-h6j3k8l2m5"
|
|
103
|
+
|
|
104
|
+
private let mask = "[redacted]"
|
|
105
|
+
|
|
106
|
+
// encodeURIComponent's unreserved set.
|
|
107
|
+
private let unreserved = CharacterSet(
|
|
108
|
+
charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.!~*'()")
|
|
109
|
+
|
|
110
|
+
private func base64(_ s: String) -> String { Data(s.utf8).base64EncodedString() }
|
|
111
|
+
|
|
112
|
+
private func percent(_ s: String) -> String {
|
|
113
|
+
s.addingPercentEncoding(withAllowedCharacters: unreserved) ?? s
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Every form a canary can travel in.
|
|
117
|
+
private let forms: [String] = {
|
|
118
|
+
var out: [String] = []
|
|
119
|
+
for v in [canaryApikey, canarySecret, canaryHeader, canaryValue, canaryConfig] {
|
|
120
|
+
out.append(v)
|
|
121
|
+
out.append(base64(v))
|
|
122
|
+
out.append(percent(v))
|
|
123
|
+
}
|
|
124
|
+
out.append(base64(canaryApikey + ":" + canarySecret))
|
|
125
|
+
return out
|
|
126
|
+
}()
|
|
127
|
+
|
|
128
|
+
private func leaks(_ text: String) -> [String] {
|
|
129
|
+
forms.filter { text.contains($0) }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Header maps keep the caller's spelling; the assertion should not care.
|
|
133
|
+
private func header(_ map: Value, _ name: String) -> Value {
|
|
134
|
+
guard let m = map.asMap else { return .noval }
|
|
135
|
+
for (k, v) in m.entries where k.caseInsensitiveCompare(name) == .orderedSame {
|
|
136
|
+
return v
|
|
137
|
+
}
|
|
138
|
+
return .noval
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private func response(_ status: Int, _ data: Value, _ headers: [(String, String)] = []) -> Value {
|
|
142
|
+
let h = VMap()
|
|
143
|
+
h.entries["content-type"] = .string("application/json")
|
|
144
|
+
for (k, v) in headers { h.entries[k.lowercased()] = .string(v) }
|
|
145
|
+
let m = VMap()
|
|
146
|
+
m.entries["status"] = .int(Int64(status))
|
|
147
|
+
m.entries["statusText"] = .string(status < 400 ? "OK" : "ERR")
|
|
148
|
+
m.entries["json"] = .nat({ () -> Value in data } as NativeCall0)
|
|
149
|
+
m.entries["body"] = .string(jsonify(data, indent: 0))
|
|
150
|
+
m.entries["headers"] = .map(h)
|
|
151
|
+
return .map(m)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The typed pipeline products read through their stored properties, so the
|
|
155
|
+
// raw spec is visible when clean is off - the sensitivity check depends on it.
|
|
156
|
+
private func render(_ any: Any?, _ depth: Int = 0) -> String {
|
|
157
|
+
guard let any = any, depth < 8 else { return "null" }
|
|
158
|
+
if let v = any as? Value {
|
|
159
|
+
if let n = v.asNative { return render(n, depth + 1) }
|
|
160
|
+
return jsonify(v, indent: 0)
|
|
161
|
+
}
|
|
162
|
+
if let m = any as? VMap { return jsonify(.map(m), indent: 0) }
|
|
163
|
+
if let s = any as? String { return s }
|
|
164
|
+
if let sp = any as? Spec {
|
|
165
|
+
let m = VMap()
|
|
166
|
+
m.entries["method"] = .string(sp.method)
|
|
167
|
+
m.entries["url"] = .string(sp.url)
|
|
168
|
+
m.entries["path"] = .string(sp.path)
|
|
169
|
+
m.entries["headers"] = .map(sp.headers)
|
|
170
|
+
m.entries["query"] = .map(sp.query)
|
|
171
|
+
m.entries["params"] = .map(sp.params)
|
|
172
|
+
m.entries["body"] = sp.body
|
|
173
|
+
return jsonify(.map(m), indent: 0)
|
|
174
|
+
}
|
|
175
|
+
if let ent = any as? Entity { return jsonify(ent.data(), indent: 0) }
|
|
176
|
+
if let ctx = any as? Context { return jsonify(.map(ctx.record()), indent: 0) }
|
|
177
|
+
if let e = any as? ${Name}Error { return jsonify(.map(e.record()), indent: 0) }
|
|
178
|
+
var out = ""
|
|
179
|
+
dump(any, to: &out, maxDepth: 8)
|
|
180
|
+
return out
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
final class ${Name}CleanTest: XCTestCase {
|
|
184
|
+
|
|
185
|
+
struct Sink {
|
|
186
|
+
let name: String
|
|
187
|
+
let text: String
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// A reference the capturing closures share.
|
|
191
|
+
final class SinkBox {
|
|
192
|
+
var sinks: [Sink] = []
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
struct Candidate {
|
|
196
|
+
let name: String
|
|
197
|
+
let accessor: (${Name}SDK) -> ${Name}EntityBase
|
|
198
|
+
let ops: [String]
|
|
199
|
+
let params: [String: [String]]
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
struct Target {
|
|
203
|
+
let candidate: Candidate
|
|
204
|
+
let op: String
|
|
205
|
+
let params: [String]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
struct TransportError: Error, CustomStringConvertible {
|
|
209
|
+
let message: String
|
|
210
|
+
var description: String { message }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
struct Scenario {
|
|
214
|
+
let name: String
|
|
215
|
+
let respond: (String, VMap) throws -> Value
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Every default print a value has, plus the SDK's own record of it.
|
|
219
|
+
static func formsOf(_ name: String, _ val: Any?) -> [Sink] {
|
|
220
|
+
var out: [Sink] = []
|
|
221
|
+
func push(_ kind: String, _ fn: () -> String) {
|
|
222
|
+
out.append(Sink(name: name + ":" + kind, text: fn()))
|
|
223
|
+
}
|
|
224
|
+
guard let val = val else { return out }
|
|
225
|
+
push("describing") { String(describing: val) }
|
|
226
|
+
push("reflecting") { String(reflecting: val) }
|
|
227
|
+
push("dump") {
|
|
228
|
+
var s = ""
|
|
229
|
+
dump(val, to: &s, maxDepth: 8)
|
|
230
|
+
return s
|
|
231
|
+
}
|
|
232
|
+
push("render") { render(val) }
|
|
233
|
+
if let v = val as? Value { push("json") { jsonify(v, indent: 0) } }
|
|
234
|
+
if let m = val as? VMap { push("json") { jsonify(.map(m), indent: 0) } }
|
|
235
|
+
if let e = val as? ${Name}Error {
|
|
236
|
+
push("message") { e.message }
|
|
237
|
+
push("record") { jsonify(.map(e.record()), indent: 0) }
|
|
238
|
+
}
|
|
239
|
+
if let e = val as? Error { push("message") { errMessage(e) } }
|
|
240
|
+
if let c = val as? Context { push("record") { jsonify(.map(c.record()), indent: 0) } }
|
|
241
|
+
return out
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Captures the serialised context from inside the pipeline: what a hook
|
|
245
|
+
// author would hand to a logger.
|
|
246
|
+
final class CaptureFeature: BaseFeature {
|
|
247
|
+
let box: SinkBox
|
|
248
|
+
init(_ box: SinkBox) {
|
|
249
|
+
self.box = box
|
|
250
|
+
super.init()
|
|
251
|
+
name = "capture"
|
|
252
|
+
version = "0.0.1"
|
|
253
|
+
active = true
|
|
254
|
+
}
|
|
255
|
+
override func preRequest(_ ctx: Context) { box.sinks += ${Name}CleanTest.formsOf("ctx@PreRequest", ctx) }
|
|
256
|
+
override func preResponse(_ ctx: Context) { box.sinks += ${Name}CleanTest.formsOf("ctx@PreResponse", ctx) }
|
|
257
|
+
|
|
258
|
+
// The SDK's own error as a hook reads it, which an observability feature
|
|
259
|
+
// logs.
|
|
260
|
+
override func preUnexpected(_ ctx: Context) {
|
|
261
|
+
box.sinks += ${Name}CleanTest.formsOf("ctx@PreUnexpected", ctx)
|
|
262
|
+
if let err = ctx.ctrl.err as? ${Name}Error {
|
|
263
|
+
box.sinks += ${Name}CleanTest.formsOf("ctrl.err@PreUnexpected", err)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// A feature that fails the operation from inside the pipeline, quoting the
|
|
269
|
+
// request it saw. A swift hook cannot throw, so it fails the response the
|
|
270
|
+
// way a hook can, and the error never came from makeError.
|
|
271
|
+
final class FailFeature: BaseFeature {
|
|
272
|
+
override init() {
|
|
273
|
+
super.init()
|
|
274
|
+
name = "throwhook"
|
|
275
|
+
version = "0.0.1"
|
|
276
|
+
active = true
|
|
277
|
+
}
|
|
278
|
+
override func preResponse(_ ctx: Context) {
|
|
279
|
+
ctx.response?.err = TransportError(message: "hook saw " + render(ctx.spec))
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// A stream that succeeds, yielding the result's items.
|
|
284
|
+
final class StreamOkFeature: BaseFeature {
|
|
285
|
+
override init() {
|
|
286
|
+
super.init()
|
|
287
|
+
name = "streamok"
|
|
288
|
+
version = "0.0.1"
|
|
289
|
+
active = true
|
|
290
|
+
}
|
|
291
|
+
override func preDone(_ ctx: Context) {
|
|
292
|
+
guard let result = ctx.result else { return }
|
|
293
|
+
let items: [Value] = result.resdata.asList?.items ?? (isNil(result.resdata) ? [] : [result.resdata])
|
|
294
|
+
result.stream = { items }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
static let scenarios: [Scenario] = [
|
|
299
|
+
Scenario(name: "ok", respond: { _, _ in
|
|
300
|
+
response(200, .map(vm(("id", .string("i1")), ("name", .string("n1")))),
|
|
301
|
+
[("x-session-token", "RESP-TOKEN-a1b2c3d4e5")])
|
|
302
|
+
}),
|
|
303
|
+
Scenario(name: "notfound", respond: { _, _ in
|
|
304
|
+
response(404, .map(vm(("error", .string("no such record")))))
|
|
305
|
+
}),
|
|
306
|
+
Scenario(name: "server", respond: { _, _ in
|
|
307
|
+
response(500, .map(vm(("error", .string("boom")))))
|
|
308
|
+
}),
|
|
309
|
+
Scenario(name: "transport", respond: { url, _ in
|
|
310
|
+
throw TransportError(message: "socket hang up (URL was: \\"" + url + "\\")")
|
|
311
|
+
}),
|
|
312
|
+
// The SDK's own error, its code quoting a registered value.
|
|
313
|
+
Scenario(name: "coded", respond: { _, _ in
|
|
314
|
+
throw ${Name}Error("denied_" + canaryApikey, "coded failure", nil)
|
|
315
|
+
}),
|
|
316
|
+
Scenario(name: "notjson", respond: { _, _ in
|
|
317
|
+
let m = VMap()
|
|
318
|
+
m.entries["status"] = .int(200)
|
|
319
|
+
m.entries["statusText"] = .string("OK")
|
|
320
|
+
m.entries["json"] = .nat({ () -> Value in .noval } as NativeCall0)
|
|
321
|
+
m.entries["body"] = .string("<html>")
|
|
322
|
+
m.entries["headers"] = .map(VMap())
|
|
323
|
+
return .map(m)
|
|
324
|
+
}),
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
// True when this SDK was generated with the named feature.
|
|
328
|
+
static func hasFeature(_ name: String) -> Bool {
|
|
329
|
+
gp(SdkConfig.makeConfig(), "feature").asMap?.entries[name] != nil
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
static func makeSdk(
|
|
333
|
+
_ scenario: Scenario, _ box: SinkBox, _ cleanopts: VMap? = nil, _ extra: [BaseFeature] = []
|
|
334
|
+
) -> ${Name}SDK {
|
|
335
|
+
func capture(_ name: String) -> (VMap) -> Void {
|
|
336
|
+
return { rec in box.sinks += formsOf(name, rec) }
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
let feature = VMap()
|
|
340
|
+
if hasFeature("log") {
|
|
341
|
+
let logger: (String, String, VMap) -> Void = { level, _, attrs in
|
|
342
|
+
box.sinks += formsOf("log." + level, attrs)
|
|
343
|
+
}
|
|
344
|
+
feature.entries["log"] = .map(vm(("active", .bool(true)), ("logger", .nat(logger))))
|
|
345
|
+
}
|
|
346
|
+
if hasFeature("debug") {
|
|
347
|
+
feature.entries["debug"] = .map(vm(("active", .bool(true)), ("onEntry", .nat(capture("debug")))))
|
|
348
|
+
}
|
|
349
|
+
if hasFeature("audit") {
|
|
350
|
+
feature.entries["audit"] = .map(vm(("active", .bool(true)), ("sink", .nat(capture("audit")))))
|
|
351
|
+
}
|
|
352
|
+
if hasFeature("telemetry") {
|
|
353
|
+
feature.entries["telemetry"] = .map(vm(("active", .bool(true)), ("exporter", .nat(capture("telemetry")))))
|
|
354
|
+
}
|
|
355
|
+
if hasFeature("cost") {
|
|
356
|
+
let sink: (CostRecord) -> Void = { rec in box.sinks += formsOf("cost", rec) }
|
|
357
|
+
feature.entries["cost"] = .map(vm(("active", .bool(true)), ("sink", .nat(sink))))
|
|
358
|
+
}
|
|
359
|
+
if hasFeature("metrics") {
|
|
360
|
+
feature.entries["metrics"] = .map(vm(("active", .bool(true))))
|
|
361
|
+
}
|
|
362
|
+
if hasFeature("clienttrack") {
|
|
363
|
+
feature.entries["clienttrack"] = .map(vm(("active", .bool(true))))
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let clean = VMap()
|
|
367
|
+
clean.entries["values"] = .string(canaryValue)
|
|
368
|
+
if let extra = cleanopts {
|
|
369
|
+
for (k, v) in extra.entries { clean.entries[k] = v }
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
let fetch: FetcherFunc = { _, url, fetchdef in try scenario.respond(url, fetchdef) }
|
|
373
|
+
|
|
374
|
+
let opts = VMap()
|
|
375
|
+
opts.entries["apikey"] = .string(canaryApikey)
|
|
376
|
+
opts.entries["secret"] = .string(canarySecret)
|
|
377
|
+
opts.entries["headers"] = .map(vm(("X-Custom-Token", .string(canaryHeader))))
|
|
378
|
+
opts.entries["clean"] = .map(clean)
|
|
379
|
+
opts.entries["feature"] = .map(feature)
|
|
380
|
+
var extend: [Value] = [.nat(CaptureFeature(box))]
|
|
381
|
+
for f in extra { extend.append(.nat(f)) }
|
|
382
|
+
opts.entries["extend"] = .list(VList(extend))
|
|
383
|
+
opts.entries["utility"] = .map(vm(("fetcher", .nat(fetch))))
|
|
384
|
+
return ${Name}SDK(opts)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Emitted from the model: every active entity with the operations it
|
|
388
|
+
// declares, list and load first.
|
|
389
|
+
static let candidates: [Candidate] = [
|
|
390
|
+
${candidateLines}
|
|
391
|
+
]
|
|
392
|
+
|
|
393
|
+
static func invoke(
|
|
394
|
+
_ ent: ${Name}EntityBase, _ op: String, _ params: [String], _ ctrl: VMap?
|
|
395
|
+
) throws -> Value {
|
|
396
|
+
let args = VMap()
|
|
397
|
+
for p in params { args.entries[p] = .string("p1") }
|
|
398
|
+
switch op {
|
|
399
|
+
case "list": return try ent.list(args, ctrl)
|
|
400
|
+
case "load": return try ent.load(args, ctrl)
|
|
401
|
+
case "create": return try ent.create(args, ctrl)
|
|
402
|
+
case "update": return try ent.update(args, ctrl)
|
|
403
|
+
case "remove": return try ent.remove(args, ctrl)
|
|
404
|
+
default: throw TransportError(message: "unknown operation: " + op)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// The first operation that completes against a plain 200: with no
|
|
409
|
+
// arguments, else with every path parameter its points declare filled in.
|
|
410
|
+
static func usableOp() -> Target? {
|
|
411
|
+
let fetch: FetcherFunc = { _, _, _ in response(200, .map(vm(("id", .string("i1"))))) }
|
|
412
|
+
let opts = VMap()
|
|
413
|
+
opts.entries["apikey"] = .string(canaryApikey)
|
|
414
|
+
opts.entries["utility"] = .map(vm(("fetcher", .nat(fetch))))
|
|
415
|
+
let plain = ${Name}SDK(opts)
|
|
416
|
+
for candidate in candidates {
|
|
417
|
+
for op in candidate.ops {
|
|
418
|
+
let filled: [String] = candidate.params[op] ?? []
|
|
419
|
+
for params in [[], filled] {
|
|
420
|
+
if (try? invoke(candidate.accessor(plain), op, params, nil)) != nil {
|
|
421
|
+
return Target(candidate: candidate, op: op, params: params)
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return nil
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
static func drive(_ sdk: ${Name}SDK, _ target: Target, _ ctrl: VMap, _ box: SinkBox) -> Error? {
|
|
430
|
+
// A caller may keep the record it passed rather than read ctrl["explain"].
|
|
431
|
+
let held = ctrl.entries["explain"]?.asMap
|
|
432
|
+
var out: Value = .noval
|
|
433
|
+
var err: Error? = nil
|
|
434
|
+
do {
|
|
435
|
+
out = try invoke(target.candidate.accessor(sdk), target.op, target.params, ctrl)
|
|
436
|
+
} catch {
|
|
437
|
+
err = error
|
|
438
|
+
}
|
|
439
|
+
if let e = err { box.sinks += formsOf("error", e) }
|
|
440
|
+
if !isNil(out) { box.sinks += formsOf("result", out) }
|
|
441
|
+
if let explain = ctrl.entries["explain"]?.asMap { box.sinks += formsOf("explain", explain) }
|
|
442
|
+
if let h = held, h !== ctrl.entries["explain"]?.asMap { box.sinks += formsOf("explain:held", h) }
|
|
443
|
+
return err
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
func testNoCredentialLeavesTheSdkInAnyForm() throws {
|
|
447
|
+
guard let target = ${Name}CleanTest.usableOp() else {
|
|
448
|
+
throw XCTSkip("no operation of this SDK completes against a plain 200; nothing to sweep")
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
let box = SinkBox()
|
|
452
|
+
var errors: [String: Error] = [:]
|
|
453
|
+
var explains: [String: VMap] = [:]
|
|
454
|
+
|
|
455
|
+
let variants: [(String, () -> VMap)] = [
|
|
456
|
+
("throw", { VMap() }),
|
|
457
|
+
("explain", { vm(("explain", .map(VMap()))) }),
|
|
458
|
+
("nothrow", { vm(("throw", .bool(false)), ("explain", .map(VMap()))) }),
|
|
459
|
+
]
|
|
460
|
+
|
|
461
|
+
for scenario in ${Name}CleanTest.scenarios {
|
|
462
|
+
for (vname, makeCtrl) in variants {
|
|
463
|
+
let sdk = ${Name}CleanTest.makeSdk(scenario, box)
|
|
464
|
+
let ctrl = makeCtrl()
|
|
465
|
+
let err = ${Name}CleanTest.drive(sdk, target, ctrl, box)
|
|
466
|
+
let key = scenario.name + "/" + vname
|
|
467
|
+
if let e = err { errors[key] = e }
|
|
468
|
+
if let ex = ctrl.entries["explain"]?.asMap { explains[key] = ex }
|
|
469
|
+
box.sinks += ${Name}CleanTest.formsOf("sdk", sdk)
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// A credential mistyped as a map. This struct port's validate collects
|
|
474
|
+
// its errors instead of throwing, so nothing rejects it: the client it
|
|
475
|
+
// produced is swept instead.
|
|
476
|
+
let mistyped = VMap()
|
|
477
|
+
mistyped.entries["apikey"] = .map(vm(("value", .string(canaryApikey))))
|
|
478
|
+
mistyped.entries["clean"] = .map(vm(("values", .string(canaryValue))))
|
|
479
|
+
box.sinks += ${Name}CleanTest.formsOf("mistyped", ${Name}SDK(mistyped))
|
|
480
|
+
|
|
481
|
+
// An error a feature hook raises, quoting the request, skips makeError.
|
|
482
|
+
// A swift hook cannot throw, so no variant fails from PreUnexpected.
|
|
483
|
+
let hooked = ${Name}CleanTest.makeSdk(${Name}CleanTest.scenarios[0], box, nil, [FailFeature()])
|
|
484
|
+
let hookerr = ${Name}CleanTest.drive(hooked, target, vm(("explain", .map(VMap()))), box)
|
|
485
|
+
XCTAssertNotNil(hookerr, "the failing hook should fail the operation")
|
|
486
|
+
|
|
487
|
+
// The explain record a stream call carries is cleaned however the stream
|
|
488
|
+
// is fed. A swift stream cannot raise, so there is no failing variant,
|
|
489
|
+
// and the record is complete once stream() returns.
|
|
490
|
+
let streams: [(String, [BaseFeature])] = [("stream-ok", [StreamOkFeature()]), ("stream-plain", [])]
|
|
491
|
+
for (label, extra) in streams {
|
|
492
|
+
let explain = VMap()
|
|
493
|
+
let streamed = ${Name}CleanTest.makeSdk(${Name}CleanTest.scenarios[0], box, nil, extra)
|
|
494
|
+
XCTAssertNoThrow(try target.candidate.accessor(streamed).stream(
|
|
495
|
+
target.op, nil, vm(("ctrl", .map(vm(("explain", .map(explain))))))), label + ": the stream should not fail")
|
|
496
|
+
XCTAssertFalse(explain.entries.isEmpty, label + ": the explain record was not filled")
|
|
497
|
+
box.sinks += ${Name}CleanTest.formsOf(label + ":explain", explain)
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// The generated config's own clean block is read beside the caller's,
|
|
501
|
+
// and is not changed by it.
|
|
502
|
+
let config = vm(("options", .map(vm(("clean", .map(vm(
|
|
503
|
+
("keys", .string("zzsens")), ("values", .string(canaryConfig)))))))))
|
|
504
|
+
let built = makeOptionsUtil(Context(
|
|
505
|
+
["config": config, "options": vm(("clean", .map(vm(("values", .string(canaryValue))))))], nil))
|
|
506
|
+
let cfgctx = Context(["options": built], nil)
|
|
507
|
+
let seeded = cleanUtil(cfgctx, .string("config " + canaryConfig + " caller " + canaryValue)).asString ?? ""
|
|
508
|
+
box.sinks.append(Sink(name: "config-clean", text: seeded))
|
|
509
|
+
XCTAssertEqual(seeded, "config " + mask + " caller " + mask)
|
|
510
|
+
let bykey = cleanUtil(cfgctx, .map(vm(("my_zzsens", .string("x")), ("other", .string("y"))))).asMap
|
|
511
|
+
XCTAssertEqual(bykey?.entries["my_zzsens"], Value.string(mask))
|
|
512
|
+
XCTAssertEqual(bykey?.entries["other"], Value.string("y"))
|
|
513
|
+
XCTAssertEqual(gpath(config, "options", "clean", "values"), .string(canaryConfig))
|
|
514
|
+
XCTAssertEqual(gpath(config, "options", "clean", "keys"), .string("zzsens"))
|
|
515
|
+
|
|
516
|
+
// A coded SDK error inside a structure is cleaned like any other field.
|
|
517
|
+
let nested = cleanUtil(cfgctx, .map(vm(
|
|
518
|
+
("err", .nat(${Name}Error("denied_" + canaryValue, "coded failure", nil))))))
|
|
519
|
+
box.sinks += ${Name}CleanTest.formsOf("coded-nested", nested)
|
|
520
|
+
|
|
521
|
+
// With no clean option at all, or one that is not a map, the schema
|
|
522
|
+
// defaults still apply.
|
|
523
|
+
for clean in [Value.noval, Value.bool(true)] {
|
|
524
|
+
let fetch404: FetcherFunc = { _, url, fetchdef in
|
|
525
|
+
try ${Name}CleanTest.scenarios[1].respond(url, fetchdef)
|
|
526
|
+
}
|
|
527
|
+
let bareopts = VMap()
|
|
528
|
+
bareopts.entries["apikey"] = .string(canaryApikey)
|
|
529
|
+
bareopts.entries["secret"] = .string(canarySecret)
|
|
530
|
+
bareopts.entries["headers"] = .map(vm(("X-Custom-Token", .string(canaryHeader))))
|
|
531
|
+
bareopts.entries["utility"] = .map(vm(("fetcher", .nat(fetch404))))
|
|
532
|
+
if !isNil(clean) {
|
|
533
|
+
bareopts.entries["clean"] = clean
|
|
534
|
+
}
|
|
535
|
+
let bareerr = ${Name}CleanTest.drive(${Name}SDK(bareopts), target, vm(("explain", .map(VMap()))), box)
|
|
536
|
+
XCTAssertNotNil(bareerr, "the 404 should fail with clean: " + stringify(clean))
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// A feature's name is not a field name: only the sensitive names inside
|
|
540
|
+
// its settings register. An entity block, of entity settings or seeded
|
|
541
|
+
// records keyed by entity name and id, is not read at all.
|
|
542
|
+
let record = vm(("zztoken", .map(vm(("ZZTOKEN01", .map(vm(("note", .string("PLAINRECORD-t5r3e1w9")))))))))
|
|
543
|
+
let alias = vm(("zztoken", .map(vm(("alias", .map(vm(("zzkey", .string("PLAINALIAS-m2n4b6v8")))))))))
|
|
544
|
+
let featopts = VMap()
|
|
545
|
+
featopts.entries["apikey"] = .string(canaryApikey)
|
|
546
|
+
featopts.entries["feature"] = .map(vm(
|
|
547
|
+
("zzsecrets", .map(vm(("active", .bool(false)), ("kind", .string("PLAINSETTING-q8w2e4r6"))))),
|
|
548
|
+
("zzfeat", .map(vm(("active", .bool(false)), ("apitoken", .string("FEATTOKEN-z9y8x7w6"))))),
|
|
549
|
+
("test", .map(vm(("active", .bool(false)), ("entity", .map(record)))))))
|
|
550
|
+
featopts.entries["entity"] = .map(alias)
|
|
551
|
+
let fctx = Context(["options": makeOptionsUtil(Context(["options": featopts], nil))], nil)
|
|
552
|
+
let fplain = cleanUtil(fctx, .string("kind PLAINSETTING-q8w2e4r6")).asString
|
|
553
|
+
let ftoken = cleanUtil(fctx, .string("token FEATTOKEN-z9y8x7w6")).asString
|
|
554
|
+
let frecord = cleanUtil(fctx, .string("record PLAINRECORD-t5r3e1w9")).asString
|
|
555
|
+
let falias = cleanUtil(fctx, .string("alias PLAINALIAS-m2n4b6v8")).asString
|
|
556
|
+
|
|
557
|
+
// direct() returns its error rather than throwing it. Only the SDK's own
|
|
558
|
+
// error can be cleaned in place, so the coded transport is the one used.
|
|
559
|
+
let raw = ${Name}CleanTest.makeSdk(${Name}CleanTest.scenarios[4], box).direct(vm(("path", .string("raw"))))
|
|
560
|
+
XCTAssertEqual(gp(raw, "ok"), .bool(false))
|
|
561
|
+
let rawerr = gp(raw, "err").asNative as? ${Name}Error
|
|
562
|
+
box.sinks += ${Name}CleanTest.formsOf("direct", rawerr)
|
|
563
|
+
|
|
564
|
+
let leaked = box.sinks
|
|
565
|
+
.map { (name: $0.name, found: leaks($0.text)) }
|
|
566
|
+
.filter { !$0.found.isEmpty }
|
|
567
|
+
|
|
568
|
+
print("clean: swept \\(box.sinks.count) surface(s), \\(leaked.count) leak(s)")
|
|
569
|
+
|
|
570
|
+
XCTAssertEqual(leaked.count, 0, "credential leaked through: " +
|
|
571
|
+
leaked.map { $0.name + " [" + $0.found.joined(separator: ", ") + "]" }.joined(separator: "; "))
|
|
572
|
+
|
|
573
|
+
// The positive half: the slot the credential travelled in is masked,
|
|
574
|
+
// and an unregistered token in a response header is masked by name.
|
|
575
|
+
guard let notfound = errors["notfound/throw"] as? ${Name}Error else {
|
|
576
|
+
XCTFail("the 404 scenario must throw")
|
|
577
|
+
return
|
|
578
|
+
}
|
|
579
|
+
XCTAssertEqual(notfound.status, 404)
|
|
580
|
+
let spec = notfound.specVal
|
|
581
|
+
if !authSuppressed {
|
|
582
|
+
if "query" == authWhere {
|
|
583
|
+
XCTAssertEqual(header(gp(spec, "query"), authName), .string(mask))
|
|
584
|
+
} else if "cookie" == authWhere {
|
|
585
|
+
let cookie = header(gp(spec, "headers"), "cookie").asString ?? ""
|
|
586
|
+
XCTAssertTrue(cookie.contains(mask), "cookie: " + cookie)
|
|
587
|
+
} else {
|
|
588
|
+
let cred = header(gp(spec, "headers"), authName).asString ?? ""
|
|
589
|
+
XCTAssertTrue(cred.hasSuffix(mask), authName + ": " + cred)
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
XCTAssertEqual(header(gp(spec, "headers"), "x-custom-token"), .string(mask))
|
|
593
|
+
|
|
594
|
+
XCTAssertEqual((errors["coded/throw"] as? ${Name}Error)?.code, "denied_" + mask)
|
|
595
|
+
|
|
596
|
+
XCTAssertEqual(fplain, "kind PLAINSETTING-q8w2e4r6")
|
|
597
|
+
XCTAssertEqual(ftoken, "token " + mask)
|
|
598
|
+
XCTAssertEqual(frecord, "record PLAINRECORD-t5r3e1w9")
|
|
599
|
+
XCTAssertEqual(falias, "alias PLAINALIAS-m2n4b6v8")
|
|
600
|
+
XCTAssertEqual(rawerr?.code, "denied_" + mask)
|
|
601
|
+
|
|
602
|
+
let explained = explains["ok/explain"] ?? VMap()
|
|
603
|
+
let result = gp(explained, "result")
|
|
604
|
+
XCTAssertFalse(isNil(result), "the explain record should carry the result")
|
|
605
|
+
XCTAssertEqual(header(gp(result, "headers"), "x-session-token"), .string(mask))
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
func testTheSweepCanSeeALeakCleanSwitchedOffShowsTheCredential() throws {
|
|
609
|
+
guard let target = ${Name}CleanTest.usableOp() else {
|
|
610
|
+
throw XCTSkip("no operation of this SDK completes against a plain 200; nothing to sweep")
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
let box = SinkBox()
|
|
614
|
+
let sdk = ${Name}CleanTest.makeSdk(${Name}CleanTest.scenarios[1], box, vm(("active", .bool(false))))
|
|
615
|
+
let err = ${Name}CleanTest.drive(sdk, target, VMap(), box)
|
|
616
|
+
XCTAssertNotNil(err, "the 404 scenario must throw")
|
|
617
|
+
|
|
618
|
+
// Explaining a failure must not cost it its error.
|
|
619
|
+
let explained = ${Name}CleanTest.drive(
|
|
620
|
+
${Name}CleanTest.makeSdk(${Name}CleanTest.scenarios[1], SinkBox(), vm(("active", .bool(false)))),
|
|
621
|
+
target, vm(("explain", .map(VMap()))), SinkBox())
|
|
622
|
+
XCTAssertEqual(explained.map { errMessage($0) }, err.map { errMessage($0) },
|
|
623
|
+
"with clean off, explain lost the error")
|
|
624
|
+
|
|
625
|
+
let leaked = box.sinks.filter { !leaks($0.text).isEmpty }
|
|
626
|
+
XCTAssertTrue(!leaked.isEmpty, "with clean off, nothing showed the canary: the sweep is blind")
|
|
627
|
+
|
|
628
|
+
if !authSuppressed, let e = err as? ${Name}Error {
|
|
629
|
+
let text = render(e.specVal)
|
|
630
|
+
XCTAssertTrue(text.contains(canaryApikey) || text.contains(base64(canaryApikey + ":" + canarySecret)),
|
|
631
|
+
"the raw spec should carry the credential when clean is off")
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
func testARegisteredValueUsedAsAPropertyNameIsMaskedCollisionsKept() {
|
|
636
|
+
let cfg = makeCleanConfig(gp(SdkSchema.optspec, "clean"))
|
|
637
|
+
let ctx = Context(["options": vm(("__derived__", .map(vm(("clean", .nat(cfg))))))], nil)
|
|
638
|
+
cleanAddUtil(ctx, .string("ZZVAL-abc123"))
|
|
639
|
+
cleanAddUtil(ctx, .string("ZZVAL-xyz789"))
|
|
640
|
+
let src = vm(("ZZVAL-abc123", .int(1)), ("ZZVAL-xyz789", .int(2)), ("plain", .int(3)))
|
|
641
|
+
guard let out = cleanUtil(ctx, .map(src)).asMap else {
|
|
642
|
+
XCTFail("clean of a map should be a map")
|
|
643
|
+
return
|
|
644
|
+
}
|
|
645
|
+
XCTAssertEqual(out.entries[mask], Value.int(1))
|
|
646
|
+
XCTAssertEqual(out.entries[mask + "#1"], Value.int(2))
|
|
647
|
+
XCTAssertEqual(out.entries["plain"], Value.int(3))
|
|
648
|
+
XCTAssertNil(out.entries["ZZVAL-abc123"])
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
func testCleanAddSensitiveRegistersEveryScalarUnderASensitiveName() {
|
|
652
|
+
let cfg = makeCleanConfig(gp(SdkSchema.optspec, "clean"))
|
|
653
|
+
let ctx = Context(["options": vm(("__derived__", .map(vm(("clean", .nat(cfg))))))], nil)
|
|
654
|
+
cleanAddSensitiveUtil(ctx, .map(vm(
|
|
655
|
+
("apikey", .map(vm(("value", .string("NESTED-SECRET-1"))))),
|
|
656
|
+
("headers", .map(vm(("X-Api-Token", .list(VList([.string("LISTED-SECRET-2")])))))),
|
|
657
|
+
("secret", .int(123456789)),
|
|
658
|
+
("name", .string("not-a-secret")))))
|
|
659
|
+
XCTAssertTrue(cfg.values.contains("NESTED-SECRET-1"))
|
|
660
|
+
XCTAssertTrue(cfg.values.contains("LISTED-SECRET-2"))
|
|
661
|
+
XCTAssertTrue(cfg.values.contains("123456789"))
|
|
662
|
+
XCTAssertFalse(cfg.values.contains("not-a-secret"))
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
`
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
export {
|
|
670
|
+
TestClean
|
|
671
|
+
}
|
|
@@ -10,6 +10,7 @@ import { cmp, each, Folder, entityCollection } from '@voxgig/sdkgen'
|
|
|
10
10
|
|
|
11
11
|
import { TestEntity } from './TestEntity_swift'
|
|
12
12
|
import { TestDirect } from './TestDirect_swift'
|
|
13
|
+
import { TestClean } from './TestClean_swift'
|
|
13
14
|
import { ReadmeExamplesTest } from './ReadmeExamplesTest_swift'
|
|
14
15
|
|
|
15
16
|
|
|
@@ -23,6 +24,8 @@ const Test = cmp(function Test(props: any) {
|
|
|
23
24
|
// are generated here.
|
|
24
25
|
Folder({ name: 'Tests' }, () => {
|
|
25
26
|
Folder({ name: swiftTestDir(model) }, () => {
|
|
27
|
+
TestClean({ target })
|
|
28
|
+
|
|
26
29
|
const entity = each(entityCollection(model))
|
|
27
30
|
.filter((e: any) => false !== e.active)
|
|
28
31
|
|