@voxgig/sdkgen 4.34.1 → 4.34.2
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/cmp/ReadmeErrors.js +3 -3
- package/dist/cmp/ReadmeErrors.js.map +1 -1
- package/dist/cmp/ReadmeExplanation.js +3 -3
- package/dist/cmp/ReadmeExplanation.js.map +1 -1
- package/dist/cmp/ReadmeQuick.js +3 -1
- package/dist/cmp/ReadmeQuick.js.map +1 -1
- package/dist/cmp/ReadmeTop.js +9 -8
- package/dist/cmp/ReadmeTop.js.map +1 -1
- package/dist/helpers/definitionPlan.js +8 -4
- package/dist/helpers/definitionPlan.js.map +1 -1
- package/dist/helpers/naming.d.ts +2 -1
- package/dist/helpers/naming.js +11 -4
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/opExample.d.ts +16 -2
- package/dist/helpers/opExample.js +80 -21
- package/dist/helpers/opExample.js.map +1 -1
- package/dist/helpers/opShape.d.ts +3 -1
- package/dist/helpers/opShape.js +21 -8
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/sdkgen.d.ts +4 -4
- package/dist/sdkgen.js +12 -4
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +29 -3
- package/dist/utility.js.map +1 -1
- package/package.json +2 -2
- package/project/.sdk/src/cmp/c/ReadmeEntity_c.ts +3 -2
- package/project/.sdk/src/cmp/c/ReadmeHowto_c.ts +7 -3
- package/project/.sdk/src/cmp/c/ReadmeQuick_c.ts +3 -2
- package/project/.sdk/src/cmp/c/ReadmeRef_c.ts +5 -4
- package/project/.sdk/src/cmp/c/ReadmeTopQuick_c.ts +3 -2
- package/project/.sdk/src/cmp/c/ReadmeTopTest_c.ts +8 -7
- package/project/.sdk/src/cmp/c/utility_c.ts +21 -2
- package/project/.sdk/src/cmp/clojure/ReadmeEntity_clojure.ts +4 -1
- package/project/.sdk/src/cmp/clojure/ReadmeHowto_clojure.ts +17 -6
- package/project/.sdk/src/cmp/clojure/ReadmeModel_clojure.ts +6 -6
- package/project/.sdk/src/cmp/clojure/ReadmeQuick_clojure.ts +13 -8
- package/project/.sdk/src/cmp/clojure/ReadmeRef_clojure.ts +21 -18
- package/project/.sdk/src/cmp/clojure/ReadmeTopQuick_clojure.ts +6 -3
- package/project/.sdk/src/cmp/clojure/ReadmeTopTest_clojure.ts +16 -9
- package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +4 -4
- package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +2 -1
- package/project/.sdk/src/cmp/clojure/utility_clojure.ts +14 -0
- package/project/.sdk/src/cmp/cpp/ReadmeEntity_cpp.ts +3 -2
- package/project/.sdk/src/cmp/cpp/ReadmeHowto_cpp.ts +7 -3
- package/project/.sdk/src/cmp/cpp/ReadmeQuick_cpp.ts +3 -2
- package/project/.sdk/src/cmp/cpp/ReadmeRef_cpp.ts +6 -5
- package/project/.sdk/src/cmp/cpp/ReadmeTopQuick_cpp.ts +3 -2
- package/project/.sdk/src/cmp/cpp/ReadmeTopTest_cpp.ts +8 -7
- package/project/.sdk/src/cmp/cpp/utility_cpp.ts +13 -0
- package/project/.sdk/src/cmp/csharp/ReadmeEntity_csharp.ts +3 -2
- package/project/.sdk/src/cmp/csharp/ReadmeHowto_csharp.ts +20 -8
- package/project/.sdk/src/cmp/csharp/ReadmeQuick_csharp.ts +13 -8
- package/project/.sdk/src/cmp/csharp/ReadmeRef_csharp.ts +10 -5
- package/project/.sdk/src/cmp/csharp/ReadmeTopQuick_csharp.ts +14 -7
- package/project/.sdk/src/cmp/csharp/ReadmeTopTest_csharp.ts +18 -10
- package/project/.sdk/src/cmp/csharp/utility_csharp.ts +13 -0
- package/project/.sdk/src/cmp/elixir/ReadmeEntity_elixir.ts +4 -4
- package/project/.sdk/src/cmp/elixir/ReadmeExplanation_elixir.ts +2 -1
- package/project/.sdk/src/cmp/elixir/ReadmeHowto_elixir.ts +13 -6
- package/project/.sdk/src/cmp/elixir/ReadmeModel_elixir.ts +5 -5
- package/project/.sdk/src/cmp/elixir/ReadmeQuick_elixir.ts +13 -10
- package/project/.sdk/src/cmp/elixir/ReadmeRef_elixir.ts +11 -11
- package/project/.sdk/src/cmp/elixir/ReadmeTopQuick_elixir.ts +8 -6
- package/project/.sdk/src/cmp/elixir/ReadmeTopTest_elixir.ts +14 -10
- package/project/.sdk/src/cmp/elixir/fragment/EntityCreateOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/fragment/EntityListOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/fragment/EntityLoadOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/fragment/EntityPatchOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/fragment/EntityRemoveOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/fragment/EntityUpdateOp.fragment.ex +4 -3
- package/project/.sdk/src/cmp/elixir/utility_elixir.ts +12 -0
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +8 -5
- package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +3 -1
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +20 -8
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +16 -13
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +14 -13
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +14 -13
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +10 -8
- package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +6 -2
- package/project/.sdk/src/cmp/go/utility_go.ts +1 -1
- package/project/.sdk/src/cmp/java/ReadmeEntity_java.ts +8 -19
- package/project/.sdk/src/cmp/java/ReadmeHowto_java.ts +19 -22
- package/project/.sdk/src/cmp/java/ReadmeModel_java.ts +10 -9
- package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +24 -28
- package/project/.sdk/src/cmp/java/ReadmeRef_java.ts +27 -35
- package/project/.sdk/src/cmp/java/ReadmeTopQuick_java.ts +22 -25
- package/project/.sdk/src/cmp/java/ReadmeTopTest_java.ts +18 -24
- package/project/.sdk/src/cmp/java/utility_java.ts +25 -0
- package/project/.sdk/src/cmp/js/EntityOperation_js.ts +3 -1
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +2 -8
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +11 -9
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +9 -9
- package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +7 -13
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +14 -15
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +16 -11
- package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +11 -7
- package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/fragment/EntityPatchOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +1 -1
- package/project/.sdk/src/cmp/js/utility_js.ts +2 -1
- package/project/.sdk/src/cmp/kotlin/ReadmeEntity_kotlin.ts +3 -2
- package/project/.sdk/src/cmp/kotlin/ReadmeHowto_kotlin.ts +19 -9
- package/project/.sdk/src/cmp/kotlin/ReadmeModel_kotlin.ts +10 -9
- package/project/.sdk/src/cmp/kotlin/ReadmeQuick_kotlin.ts +14 -9
- package/project/.sdk/src/cmp/kotlin/ReadmeRef_kotlin.ts +18 -15
- package/project/.sdk/src/cmp/kotlin/ReadmeTopQuick_kotlin.ts +14 -8
- package/project/.sdk/src/cmp/kotlin/ReadmeTopTest_kotlin.ts +17 -10
- package/project/.sdk/src/cmp/kotlin/utility_kotlin.ts +21 -1
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +3 -2
- package/project/.sdk/src/cmp/lua/ReadmeExamplesTest_lua.ts +7 -4
- package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +9 -7
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +13 -13
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +20 -9
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +9 -8
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +15 -7
- package/project/.sdk/src/cmp/lua/ReadmeTopTest_lua.ts +6 -5
- package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +1 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityCreateOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/lua/fragment/EntityListOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/lua/fragment/EntityLoadOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/lua/fragment/EntityPatchOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/lua/fragment/EntityRemoveOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/lua/fragment/EntityUpdateOp.fragment.lua +1 -1
- package/project/.sdk/src/cmp/ocaml/ReadmeEntity_ocaml.ts +3 -2
- package/project/.sdk/src/cmp/ocaml/ReadmeHowto_ocaml.ts +3 -2
- package/project/.sdk/src/cmp/ocaml/ReadmeModel_ocaml.ts +1 -0
- package/project/.sdk/src/cmp/ocaml/ReadmeQuick_ocaml.ts +5 -3
- package/project/.sdk/src/cmp/ocaml/ReadmeRef_ocaml.ts +10 -8
- package/project/.sdk/src/cmp/ocaml/ReadmeTopQuick_ocaml.ts +4 -2
- package/project/.sdk/src/cmp/ocaml/ReadmeTopTest_ocaml.ts +3 -2
- package/project/.sdk/src/cmp/ocaml/utility_ocaml.ts +13 -1
- package/project/.sdk/src/cmp/perl/ReadmeEntity_perl.ts +4 -1
- package/project/.sdk/src/cmp/perl/ReadmeHowto_perl.ts +10 -5
- package/project/.sdk/src/cmp/perl/ReadmeModel_perl.ts +6 -6
- package/project/.sdk/src/cmp/perl/ReadmeQuick_perl.ts +8 -5
- package/project/.sdk/src/cmp/perl/ReadmeRef_perl.ts +21 -18
- package/project/.sdk/src/cmp/perl/ReadmeTopQuick_perl.ts +6 -3
- package/project/.sdk/src/cmp/perl/ReadmeTopTest_perl.ts +11 -8
- package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +1 -1
- package/project/.sdk/src/cmp/perl/fragment/EntityCreateOp.fragment.pm +2 -2
- package/project/.sdk/src/cmp/perl/fragment/EntityLoadOp.fragment.pm +2 -2
- package/project/.sdk/src/cmp/perl/fragment/EntityPatchOp.fragment.pm +2 -2
- package/project/.sdk/src/cmp/perl/fragment/EntityRemoveOp.fragment.pm +1 -1
- package/project/.sdk/src/cmp/perl/fragment/EntityUpdateOp.fragment.pm +2 -2
- package/project/.sdk/src/cmp/perl/utility_perl.ts +11 -1
- package/project/.sdk/src/cmp/php/EntityOperation_php.ts +3 -1
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +4 -3
- package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +12 -6
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +9 -9
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +3 -2
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +15 -14
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +5 -4
- package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +13 -7
- package/project/.sdk/src/cmp/php/fragment/EntityCreateOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/php/fragment/EntityListOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/php/fragment/EntityLoadOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/php/fragment/EntityPatchOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/php/fragment/EntityRemoveOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/php/fragment/EntityUpdateOp.fragment.php +2 -2
- package/project/.sdk/src/cmp/py/EntityOperation_py.ts +3 -1
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +3 -8
- package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +9 -9
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +9 -9
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +9 -14
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +23 -30
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +7 -12
- package/project/.sdk/src/cmp/py/ReadmeTopTest_py.ts +8 -7
- package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityListOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityPatchOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/rb/EntityOperation_rb.ts +3 -1
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +2 -1
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +4 -1
- package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +3 -2
- package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +20 -10
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +10 -9
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +14 -11
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +6 -3
- package/project/.sdk/src/cmp/rb/ReadmeTopTest_rb.ts +14 -10
- package/project/.sdk/src/cmp/rb/fragment/EntityCreateOp.fragment.rb +2 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityListOp.fragment.rb +1 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityLoadOp.fragment.rb +2 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityPatchOp.fragment.rb +2 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityRemoveOp.fragment.rb +2 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityUpdateOp.fragment.rb +2 -1
- package/project/.sdk/src/cmp/rb/utility_rb.ts +10 -0
- package/project/.sdk/src/cmp/rust/ReadmeEntity_rust.ts +3 -2
- package/project/.sdk/src/cmp/rust/ReadmeHowto_rust.ts +6 -2
- package/project/.sdk/src/cmp/rust/ReadmeQuick_rust.ts +3 -2
- package/project/.sdk/src/cmp/rust/ReadmeRef_rust.ts +5 -4
- package/project/.sdk/src/cmp/rust/ReadmeTopQuick_rust.ts +3 -2
- package/project/.sdk/src/cmp/rust/ReadmeTopTest_rust.ts +7 -6
- package/project/.sdk/src/cmp/rust/utility_rust.ts +13 -1
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +5 -2
- package/project/.sdk/src/cmp/scala/ReadmeEntity_scala.ts +8 -19
- package/project/.sdk/src/cmp/scala/ReadmeHowto_scala.ts +17 -22
- package/project/.sdk/src/cmp/scala/ReadmeModel_scala.ts +10 -9
- package/project/.sdk/src/cmp/scala/ReadmeQuick_scala.ts +18 -28
- package/project/.sdk/src/cmp/scala/ReadmeRef_scala.ts +25 -35
- package/project/.sdk/src/cmp/scala/ReadmeTopQuick_scala.ts +14 -25
- package/project/.sdk/src/cmp/scala/ReadmeTopTest_scala.ts +16 -24
- package/project/.sdk/src/cmp/scala/utility_scala.ts +25 -0
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeEntity_swift.ts +3 -2
- package/project/.sdk/src/cmp/swift/ReadmeHowto_swift.ts +22 -8
- package/project/.sdk/src/cmp/swift/ReadmeModel_swift.ts +10 -9
- package/project/.sdk/src/cmp/swift/ReadmeQuick_swift.ts +16 -8
- package/project/.sdk/src/cmp/swift/ReadmeRef_swift.ts +20 -15
- package/project/.sdk/src/cmp/swift/ReadmeTopQuick_swift.ts +12 -7
- package/project/.sdk/src/cmp/swift/ReadmeTopTest_swift.ts +21 -10
- package/project/.sdk/src/cmp/swift/utility_swift.ts +14 -1
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +2 -8
- package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +11 -9
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +9 -9
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +7 -13
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +14 -23
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +8 -14
- package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +29 -14
- package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +1 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +1 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +1 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityPatchOp.fragment.ts +1 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +1 -1
- package/project/.sdk/src/cmp/ts/utility_ts.ts +2 -1
- package/project/.sdk/src/cmp/zig/ReadmeEntity_zig.ts +3 -2
- package/project/.sdk/src/cmp/zig/ReadmeHowto_zig.ts +6 -2
- package/project/.sdk/src/cmp/zig/ReadmeQuick_zig.ts +4 -3
- package/project/.sdk/src/cmp/zig/ReadmeRef_zig.ts +5 -4
- package/project/.sdk/src/cmp/zig/ReadmeTopQuick_zig.ts +3 -2
- package/project/.sdk/src/cmp/zig/ReadmeTopTest_zig.ts +7 -6
- package/project/.sdk/src/cmp/zig/utility_zig.ts +13 -0
- package/project/.sdk/tm/c/utility/transform_request.c +1 -1
- package/project/.sdk/tm/clojure/src/sdk/core.clj +32 -26
- package/project/.sdk/tm/clojure/test/sdk/test/concurrency.clj +136 -0
- package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +3 -1
- package/project/.sdk/tm/cpp/core/types.hpp +36 -6
- package/project/.sdk/tm/cpp/test/concurrency_test.cpp +348 -0
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +42 -25
- package/project/.sdk/tm/csharp/core/Context.cs +8 -5
- package/project/.sdk/tm/csharp/test/ConcurrencyTest.cs +238 -0
- package/project/.sdk/tm/csharp/utility/Clean.cs +12 -10
- package/project/.sdk/tm/csharp/utility/TransformRequest.cs +1 -1
- package/project/.sdk/tm/elixir/lib/projectname/context.ex +3 -0
- package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +2 -1
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +31 -10
- package/project/.sdk/tm/elixir/test/concurrency_test.exs +176 -0
- package/project/.sdk/tm/go/core/context.go +5 -1
- package/project/.sdk/tm/go/test/concurrency_test.go +214 -0
- package/project/.sdk/tm/go/utility/transform_request.go +1 -1
- package/project/.sdk/tm/java/core/Context.java +6 -3
- package/project/.sdk/tm/java/test/ConcurrencyTest.java +221 -0
- package/project/.sdk/tm/java/utility/Clean.java +22 -17
- package/project/.sdk/tm/java/utility/TransformRequest.java +1 -1
- package/project/.sdk/tm/js/src/utility/TransformRequestUtility.js +1 -1
- package/project/.sdk/tm/kotlin/core/Context.kt +5 -3
- package/project/.sdk/tm/kotlin/test/ConcurrencyTest.kt +193 -0
- package/project/.sdk/tm/kotlin/utility/ResultTransform.kt +1 -1
- package/project/.sdk/tm/lua/utility/transform_request.lua +1 -1
- package/project/.sdk/tm/ocaml/Makefile +21 -8
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +27 -12
- package/project/.sdk/tm/ocaml/sdk_types.ml +6 -2
- package/project/.sdk/tm/ocaml/test/concurrency_test.ml +148 -0
- package/project/.sdk/tm/perl/utility/transform_request.pm +1 -1
- package/project/.sdk/tm/php/feature/TestFeature.php +9 -9
- package/project/.sdk/tm/php/utility/TransformRequest.php +1 -1
- package/project/.sdk/tm/py/pkg/core/context.py +2 -2
- package/project/.sdk/tm/py/pkg/utility/clean.py +12 -8
- package/project/.sdk/tm/py/pkg/utility/transform_request.py +1 -1
- package/project/.sdk/tm/py/test/test_concurrency.py +177 -0
- package/project/.sdk/tm/rb/core/context.rb +8 -3
- package/project/.sdk/tm/rb/test/concurrency_test.rb +160 -0
- package/project/.sdk/tm/rb/utility/clean.rb +8 -7
- package/project/.sdk/tm/rb/utility/transform_request.rb +1 -1
- package/project/.sdk/tm/rust/utility/transform_request.rs +1 -1
- package/project/.sdk/tm/scala/Makefile +2 -0
- package/project/.sdk/tm/scala/core/Context.scala +6 -4
- package/project/.sdk/tm/scala/sdktest/ConcurrencyTest.scala +186 -0
- package/project/.sdk/tm/scala/utility/Transform.scala +1 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +2 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +35 -12
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/ConcurrencyTest.swift +214 -0
- package/project/.sdk/tm/ts/src/utility/TransformRequestUtility.ts +1 -1
- package/project/.sdk/tm/zig/core/utility.zig +1 -1
- package/project/.sdk/tm/zig/feature/test.zig +10 -8
- package/project/sdkgen-package.json +1 -1
- package/src/cmp/ReadmeErrors.ts +5 -5
- package/src/cmp/ReadmeExplanation.ts +4 -5
- package/src/cmp/ReadmeQuick.ts +3 -1
- package/src/cmp/ReadmeTop.ts +10 -12
- package/src/helpers/definitionPlan.ts +8 -4
- package/src/helpers/naming.ts +12 -4
- package/src/helpers/opExample.ts +97 -25
- package/src/helpers/opShape.ts +25 -9
- package/src/sdkgen.ts +14 -3
- package/src/utility.ts +31 -4
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
// ProjectName SDK - requests in flight at once on one client. Each resolves
|
|
2
|
+
// its operation through the cache the client's root context shares with
|
|
3
|
+
// every request, and registers and cleans secrets through the one registry
|
|
4
|
+
// the client holds.
|
|
5
|
+
|
|
6
|
+
#include "testlib.hpp"
|
|
7
|
+
|
|
8
|
+
#include <algorithm>
|
|
9
|
+
#include <atomic>
|
|
10
|
+
#include <cstdlib>
|
|
11
|
+
#include <functional>
|
|
12
|
+
#include <mutex>
|
|
13
|
+
#include <thread>
|
|
14
|
+
#include <vector>
|
|
15
|
+
|
|
16
|
+
using namespace sdk;
|
|
17
|
+
|
|
18
|
+
// PROJECTENV_TEST_CONCURRENCY_ROUNDS sets the rounds: fewer where each costs
|
|
19
|
+
// more, as under ThreadSanitizer.
|
|
20
|
+
static int envRounds() {
|
|
21
|
+
const char* set = std::getenv("PROJECTENV_TEST_CONCURRENCY_ROUNDS");
|
|
22
|
+
int rounds = nullptr == set ? 0 : std::atoi(set);
|
|
23
|
+
return 0 < rounds ? rounds : 200;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static const int ROUNDS = envRounds();
|
|
27
|
+
static const int QUARTER = std::max(1, ROUNDS / 4);
|
|
28
|
+
static const int WIDTH = 8;
|
|
29
|
+
static const int OPS = 32;
|
|
30
|
+
|
|
31
|
+
static const std::string BASIC_USER = "CONCURRENCY-BASIC-USER";
|
|
32
|
+
static const std::string BASIC_PASS = "CONCURRENCY-BASIC-PASS";
|
|
33
|
+
|
|
34
|
+
static Value liveOptions() {
|
|
35
|
+
return vmap({{"base", Value(std::string("http://concurrency.test/api"))},
|
|
36
|
+
{"allow", vmap({{"op", Value(std::string("direct"))}})}});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// A live client whose transport answers at once, showing `seen` the headers
|
|
40
|
+
// of each request.
|
|
41
|
+
static std::shared_ptr<ProjectNameSDK> liveClient(
|
|
42
|
+
const Value& options = liveOptions(), std::function<void(const Value&)> seen = nullptr) {
|
|
43
|
+
auto client = std::make_shared<ProjectNameSDK>(options);
|
|
44
|
+
// Through the base: an entity accessor may share the member's name.
|
|
45
|
+
SdkClient& base = *client;
|
|
46
|
+
base.utility->fetcher = [seen](CtxPtr, const std::string&, const Value& fetchdef) -> Value {
|
|
47
|
+
if (seen) seen(getp(fetchdef, "headers"));
|
|
48
|
+
vs::Injector json = [](vs::Injection&, const Value&, const std::string&, const Value&) -> Value {
|
|
49
|
+
return vmap({{"ok", Value(true)}});
|
|
50
|
+
};
|
|
51
|
+
return vmap({{"status", Value(200)}, {"statusText", Value(std::string("OK"))},
|
|
52
|
+
{"headers", vmap()}, {"json", Value(json)}});
|
|
53
|
+
};
|
|
54
|
+
return client;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Runs body on WIDTH threads released together, and returns what they threw.
|
|
58
|
+
template <typename F>
|
|
59
|
+
static std::vector<std::string> atOnce(F body) {
|
|
60
|
+
std::atomic<int> ready{0};
|
|
61
|
+
std::mutex mu;
|
|
62
|
+
std::vector<std::string> thrown;
|
|
63
|
+
std::vector<std::thread> threads;
|
|
64
|
+
for (int n = 0; n < WIDTH; n++) {
|
|
65
|
+
threads.emplace_back([&, n]() {
|
|
66
|
+
ready.fetch_add(1);
|
|
67
|
+
while (ready.load() < WIDTH) std::this_thread::yield();
|
|
68
|
+
try {
|
|
69
|
+
body(n);
|
|
70
|
+
} catch (const SdkErrorPtr& e) {
|
|
71
|
+
std::lock_guard<std::mutex> lk(mu);
|
|
72
|
+
thrown.push_back(e->msg);
|
|
73
|
+
} catch (const std::exception& e) {
|
|
74
|
+
std::lock_guard<std::mutex> lk(mu);
|
|
75
|
+
thrown.push_back(e.what());
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
for (auto& t : threads) t.join();
|
|
80
|
+
return thrown;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static void concurrent_first_requests_succeed() {
|
|
84
|
+
for (int round = 0; round < ROUNDS; round++) {
|
|
85
|
+
// A fresh client each round, so every request in it is a first request.
|
|
86
|
+
auto client = liveClient();
|
|
87
|
+
std::vector<Value> results(WIDTH);
|
|
88
|
+
auto thrown = atOnce([&](int n) {
|
|
89
|
+
results[n] = client->direct(vmap({{"path", Value("p" + std::to_string(n))}}));
|
|
90
|
+
});
|
|
91
|
+
if (!thrown.empty()) {
|
|
92
|
+
ASSERT_TRUE(false, "round " + std::to_string(round) + " threw: " + thrown[0]);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
for (int n = 0; n < WIDTH; n++) {
|
|
96
|
+
if (!is_true(getp(results[n], "ok"))) {
|
|
97
|
+
ASSERT_TRUE(false, "round " + std::to_string(round) + ", request " + std::to_string(n) +
|
|
98
|
+
" failed: " + sdktest::vstr(results[n]));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
ASSERT_TRUE(true, "every request succeeded");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static void concurrent_resolutions_share_one_cached_operation() {
|
|
107
|
+
for (int round = 0; round < ROUNDS; round++) {
|
|
108
|
+
auto client = liveClient();
|
|
109
|
+
auto utility = client->getUtility();
|
|
110
|
+
auto root = client->getRootCtx();
|
|
111
|
+
std::vector<std::vector<OperationPtr>> ops(WIDTH, std::vector<OperationPtr>(OPS));
|
|
112
|
+
auto resolve = [&](int k) {
|
|
113
|
+
CtxSpec cs;
|
|
114
|
+
cs.setOpname("op" + std::to_string(k));
|
|
115
|
+
return utility->makeContext(cs, root)->op;
|
|
116
|
+
};
|
|
117
|
+
auto thrown = atOnce([&](int n) {
|
|
118
|
+
for (int k = 0; k < OPS; k++) ops[n][k] = resolve(k);
|
|
119
|
+
});
|
|
120
|
+
if (!thrown.empty()) {
|
|
121
|
+
ASSERT_TRUE(false, "round " + std::to_string(round) + " threw: " + thrown[0]);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
for (int k = 0; k < OPS; k++) {
|
|
125
|
+
OperationPtr cached = resolve(k);
|
|
126
|
+
for (int n = 0; n < WIDTH; n++) {
|
|
127
|
+
if (ops[n][k] != cached) {
|
|
128
|
+
ASSERT_TRUE(false, "round " + std::to_string(round) + ": op" + std::to_string(k) +
|
|
129
|
+
" resolved to more than one Operation");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
ASSERT_TRUE(true, "every operation resolved to one cached Operation");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// The k-th secret registering thread n adds in round r.
|
|
139
|
+
static std::string addedSecret(const std::string& r, int n, int k) {
|
|
140
|
+
return "ADDED-SECRET-" + r + "-" + std::to_string(n) + "-" + std::to_string(k);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Registers thread n's secrets, then counts the thread out of `left`.
|
|
144
|
+
static void registerSecrets(UtilityPtr utility, CtxPtr root, const std::string& r, int n,
|
|
145
|
+
std::atomic<int>& left) {
|
|
146
|
+
struct Done {
|
|
147
|
+
std::atomic<int>& left;
|
|
148
|
+
~Done() { left.fetch_sub(1); }
|
|
149
|
+
} done{left};
|
|
150
|
+
for (int k = 0; k < OPS; k++) utility->cleanAdd(root, Value(addedSecret(r, n, k)));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// The first of `known` and the secrets `registrars` threads registered in
|
|
154
|
+
// round r that a clean leaves raw, or "".
|
|
155
|
+
static std::string unmaskedSecret(UtilityPtr utility, CtxPtr root, const std::string& r,
|
|
156
|
+
int registrars, std::vector<std::string> known = {}) {
|
|
157
|
+
for (int n = 0; n < registrars; n++) {
|
|
158
|
+
for (int k = 0; k < OPS; k++) known.push_back(addedSecret(r, n, k));
|
|
159
|
+
}
|
|
160
|
+
for (const auto& secret : known) {
|
|
161
|
+
Value got = utility->clean(root, Value(secret));
|
|
162
|
+
if (!got.is_string() || "[redacted]" != got.as_string()) return secret;
|
|
163
|
+
}
|
|
164
|
+
return "";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Secrets registered on some threads while others clean: every clean masks
|
|
168
|
+
// what was registered before it, the longer secret whole, and no
|
|
169
|
+
// registration is lost.
|
|
170
|
+
static void concurrent_registration_keeps_every_secret_masked() {
|
|
171
|
+
const std::string masked = "a [redacted] b [redacted] c";
|
|
172
|
+
for (int round = 0; round < QUARTER; round++) {
|
|
173
|
+
auto client = liveClient();
|
|
174
|
+
auto utility = client->getUtility();
|
|
175
|
+
auto root = client->getRootCtx();
|
|
176
|
+
std::string r = std::to_string(round);
|
|
177
|
+
std::string inner = "INNER-SECRET-" + r;
|
|
178
|
+
utility->cleanAdd(root, Value(inner));
|
|
179
|
+
utility->cleanAdd(root, Value("OUTER-" + inner + "-TAIL"));
|
|
180
|
+
Value text("a " + inner + " b OUTER-" + inner + "-TAIL c");
|
|
181
|
+
Value before = utility->clean(root, text);
|
|
182
|
+
if (!before.is_string() || masked != before.as_string()) {
|
|
183
|
+
ASSERT_TRUE(false, "round " + r + " cleaned to: " + sdktest::vstr(before));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
std::atomic<int> registering{WIDTH / 2};
|
|
188
|
+
std::mutex mu;
|
|
189
|
+
std::vector<std::string> wrong;
|
|
190
|
+
auto thrown = atOnce([&](int n) {
|
|
191
|
+
if (n < WIDTH / 2) {
|
|
192
|
+
registerSecrets(utility, root, r, n, registering);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
while (0 < registering.load()) {
|
|
196
|
+
Value got = utility->clean(root, text);
|
|
197
|
+
if (!got.is_string() || masked != got.as_string()) {
|
|
198
|
+
std::lock_guard<std::mutex> lk(mu);
|
|
199
|
+
wrong.push_back(sdktest::vstr(got));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!thrown.empty()) {
|
|
205
|
+
ASSERT_TRUE(false, "round " + r + " threw: " + thrown[0]);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (!wrong.empty()) {
|
|
209
|
+
ASSERT_TRUE(false, "round " + r + " cleaned to: " + wrong[0]);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
std::string raw = unmaskedSecret(utility, root, r, WIDTH / 2);
|
|
213
|
+
if (!raw.empty()) {
|
|
214
|
+
ASSERT_TRUE(false, "round " + r + ": " + raw + " was registered but not masked");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
ASSERT_TRUE(true, "every secret stayed masked");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Requests on one client while secrets register on it: each request copies
|
|
222
|
+
// the client's options, the registry among them.
|
|
223
|
+
static void concurrent_requests_survive_registration() {
|
|
224
|
+
for (int round = 0; round < QUARTER; round++) {
|
|
225
|
+
auto client = liveClient();
|
|
226
|
+
auto utility = client->getUtility();
|
|
227
|
+
auto root = client->getRootCtx();
|
|
228
|
+
std::string r = std::to_string(round);
|
|
229
|
+
std::atomic<int> registering{WIDTH / 2};
|
|
230
|
+
std::mutex mu;
|
|
231
|
+
std::vector<std::string> failed;
|
|
232
|
+
auto thrown = atOnce([&](int n) {
|
|
233
|
+
if (n < WIDTH / 2) {
|
|
234
|
+
registerSecrets(utility, root, r, n, registering);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
while (0 < registering.load()) {
|
|
238
|
+
Value got = client->direct(vmap({{"path", Value("p" + std::to_string(n))}}));
|
|
239
|
+
if (!is_true(getp(got, "ok"))) {
|
|
240
|
+
std::lock_guard<std::mutex> lk(mu);
|
|
241
|
+
failed.push_back(sdktest::vstr(got));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
if (!thrown.empty()) {
|
|
247
|
+
ASSERT_TRUE(false, "round " + r + " threw: " + thrown[0]);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (!failed.empty()) {
|
|
251
|
+
ASSERT_TRUE(false, "round " + r + ", a request failed: " + failed[0]);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
std::string raw = unmaskedSecret(utility, root, r, WIDTH / 2);
|
|
255
|
+
if (!raw.empty()) {
|
|
256
|
+
ASSERT_TRUE(false, "round " + r + ": " + raw + " was registered but not masked");
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
ASSERT_TRUE(true, "every request succeeded while secrets registered");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Whether a header value holds `text`.
|
|
264
|
+
static bool carries(const Value& headers, const std::string& text) {
|
|
265
|
+
if (!headers.is_map()) return false;
|
|
266
|
+
for (const auto& kv : *headers.as_map()) {
|
|
267
|
+
if (kv.second.is_string() && std::string::npos != kv.second.as_string().find(text)) return true;
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// First requests on a client carrying Basic credentials while secrets
|
|
273
|
+
// register on it: where the API takes HTTP Basic, prepareAuth registers the
|
|
274
|
+
// encoded pair as the other requests copy the options.
|
|
275
|
+
static void concurrent_basic_requests_survive_registration() {
|
|
276
|
+
const std::string pair = util::cleanBase64(BASIC_USER + ":" + BASIC_PASS);
|
|
277
|
+
int sent = 0;
|
|
278
|
+
int paired = 0;
|
|
279
|
+
for (int round = 0; round < QUARTER; round++) {
|
|
280
|
+
std::atomic<int> roundSent{0};
|
|
281
|
+
std::atomic<int> roundPaired{0};
|
|
282
|
+
Value options = liveOptions();
|
|
283
|
+
map_put(options, "apikey", Value(BASIC_USER));
|
|
284
|
+
map_put(options, "secret", Value(BASIC_PASS));
|
|
285
|
+
auto client = liveClient(options, [&](const Value& headers) {
|
|
286
|
+
roundSent.fetch_add(1);
|
|
287
|
+
if (carries(headers, pair)) roundPaired.fetch_add(1);
|
|
288
|
+
});
|
|
289
|
+
auto utility = client->getUtility();
|
|
290
|
+
auto root = client->getRootCtx();
|
|
291
|
+
std::string r = "basic-" + std::to_string(round);
|
|
292
|
+
std::atomic<int> registering{1};
|
|
293
|
+
std::mutex mu;
|
|
294
|
+
std::vector<std::string> failed;
|
|
295
|
+
auto thrown = atOnce([&](int n) {
|
|
296
|
+
if (0 == n) {
|
|
297
|
+
registerSecrets(utility, root, r, n, registering);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// Bounded, as requests that never pause can hold off a registration.
|
|
301
|
+
int made = 0;
|
|
302
|
+
do {
|
|
303
|
+
Value got = client->direct(vmap({{"path", Value("p" + std::to_string(n))}}));
|
|
304
|
+
if (!is_true(getp(got, "ok"))) {
|
|
305
|
+
std::lock_guard<std::mutex> lk(mu);
|
|
306
|
+
failed.push_back(sdktest::vstr(got));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
} while (0 < registering.load() && ++made < OPS);
|
|
310
|
+
});
|
|
311
|
+
if (!thrown.empty()) {
|
|
312
|
+
ASSERT_TRUE(false, "round " + r + " threw: " + thrown[0]);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (!failed.empty()) {
|
|
316
|
+
ASSERT_TRUE(false, "round " + r + ", a request failed: " + failed[0]);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
int rsent = roundSent.load();
|
|
320
|
+
int rpaired = roundPaired.load();
|
|
321
|
+
if (0 < rpaired && rpaired != rsent) {
|
|
322
|
+
ASSERT_TRUE(false, "round " + r + ": " + std::to_string(rpaired) + " of " +
|
|
323
|
+
std::to_string(rsent) + " requests carried the Basic pair");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
std::vector<std::string> known{BASIC_USER, BASIC_PASS};
|
|
327
|
+
if (0 < rpaired) known.push_back(pair);
|
|
328
|
+
std::string raw = unmaskedSecret(utility, root, r, 1, known);
|
|
329
|
+
if (!raw.empty()) {
|
|
330
|
+
ASSERT_TRUE(false, "round " + r + ": " + raw + " was registered but not masked");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
sent += rsent;
|
|
334
|
+
paired += rpaired;
|
|
335
|
+
}
|
|
336
|
+
std::cout << "concurrency_test: " << paired << " of " << sent
|
|
337
|
+
<< " requests carried the Basic pair\n";
|
|
338
|
+
ASSERT_TRUE(true, "every request succeeded while the Basic pair and secrets registered");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
int main() {
|
|
342
|
+
T_RUN(concurrent_first_requests_succeed);
|
|
343
|
+
T_RUN(concurrent_resolutions_share_one_cached_operation);
|
|
344
|
+
T_RUN(concurrent_registration_keeps_every_secret_masked);
|
|
345
|
+
T_RUN(concurrent_requests_survive_registration);
|
|
346
|
+
T_RUN(concurrent_basic_requests_survive_registration);
|
|
347
|
+
return sdktest::summary("concurrency_test");
|
|
348
|
+
}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
#include <algorithm>
|
|
11
11
|
#include <memory>
|
|
12
|
+
#include <mutex>
|
|
13
|
+
#include <shared_mutex>
|
|
12
14
|
#include <cctype>
|
|
13
15
|
#include <string>
|
|
14
16
|
#include <vector>
|
|
@@ -66,7 +68,7 @@ inline CtxPtr makeContext(const CtxSpec& cs, CtxPtr basectx) {
|
|
|
66
68
|
//
|
|
67
69
|
// The configuration is the derived clean block makeOptions builds
|
|
68
70
|
// (`options.__derived__.clean`): a plain map, so the registry list inside
|
|
69
|
-
// it
|
|
71
|
+
// it can be replaced after construction - features register later.
|
|
70
72
|
|
|
71
73
|
constexpr int CLEAN_MAXDEPTH = 32;
|
|
72
74
|
|
|
@@ -176,36 +178,51 @@ inline std::vector<std::string> cleanForms(const std::string& value) {
|
|
|
176
178
|
return out;
|
|
177
179
|
}
|
|
178
180
|
|
|
181
|
+
inline Value cleanValues(const Value& cfg) {
|
|
182
|
+
std::shared_lock<std::shared_mutex> guard(cleanRegistryLock());
|
|
183
|
+
return getp(cfg, "values");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
inline bool cleanKnown(const Value& values, const std::string& form) {
|
|
187
|
+
if (!values.is_list()) return false;
|
|
188
|
+
for (const auto& v : *values.as_list()) {
|
|
189
|
+
if (v.is_string() && v.as_string() == form) return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
179
194
|
// Register a secret value. Idempotent; shorter than `min` is not a secret
|
|
180
|
-
// the SDK can mask without blanking ordinary text.
|
|
195
|
+
// the SDK can mask without blanking ordinary text. A registration publishes
|
|
196
|
+
// a new list and never changes a published one.
|
|
181
197
|
inline void cleanAddCfg(const Value& cfg, const Value& value) {
|
|
182
198
|
if (!cfg.is_map() || !value.is_string()) return;
|
|
183
199
|
size_t min = static_cast<size_t>(cleanCount(getp(cfg, "min"), 4));
|
|
184
200
|
const std::string& raw = value.as_string();
|
|
185
201
|
if (raw.size() < min) return;
|
|
186
|
-
|
|
187
|
-
if (!values.is_list()) {
|
|
188
|
-
values = vlist();
|
|
189
|
-
map_put(cfg, "values", values);
|
|
190
|
-
}
|
|
191
|
-
auto& list = *values.as_list();
|
|
192
|
-
bool changed = false;
|
|
202
|
+
std::vector<std::string> forms;
|
|
193
203
|
for (const auto& form : cleanForms(raw)) {
|
|
194
|
-
if (form.size()
|
|
195
|
-
bool known = false;
|
|
196
|
-
for (const auto& v : list) {
|
|
197
|
-
if (v.is_string() && v.as_string() == form) { known = true; break; }
|
|
198
|
-
}
|
|
199
|
-
if (!known) {
|
|
200
|
-
list.push_back(Value(form));
|
|
201
|
-
changed = true;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (changed) {
|
|
205
|
-
std::stable_sort(list.begin(), list.end(), [](const Value& a, const Value& b) {
|
|
206
|
-
return a.as_string().size() > b.as_string().size();
|
|
207
|
-
});
|
|
204
|
+
if (min <= form.size()) forms.push_back(form);
|
|
208
205
|
}
|
|
206
|
+
auto unknown = [&forms](const Value& values) {
|
|
207
|
+
std::vector<std::string> out;
|
|
208
|
+
for (const auto& form : forms) {
|
|
209
|
+
if (!cleanKnown(values, form)) out.push_back(form);
|
|
210
|
+
}
|
|
211
|
+
return out;
|
|
212
|
+
};
|
|
213
|
+
if (unknown(cleanValues(cfg)).empty()) return;
|
|
214
|
+
std::unique_lock<std::shared_mutex> guard(cleanRegistryLock());
|
|
215
|
+
Value values = getp(cfg, "values");
|
|
216
|
+
std::vector<std::string> added = unknown(values);
|
|
217
|
+
if (added.empty()) return;
|
|
218
|
+
Value next = vlist();
|
|
219
|
+
if (values.is_list()) *next.as_list() = *values.as_list();
|
|
220
|
+
auto& list = *next.as_list();
|
|
221
|
+
for (const auto& form : added) list.push_back(Value(form));
|
|
222
|
+
std::stable_sort(list.begin(), list.end(), [](const Value& a, const Value& b) {
|
|
223
|
+
return a.as_string().size() > b.as_string().size();
|
|
224
|
+
});
|
|
225
|
+
map_put(cfg, "values", next);
|
|
209
226
|
}
|
|
210
227
|
|
|
211
228
|
inline void cleanAdd(CtxPtr ctx, const Value& value) {
|
|
@@ -221,7 +238,7 @@ inline std::string cleanMaskValue(const Value& cfg, const std::string& value) {
|
|
|
221
238
|
|
|
222
239
|
inline std::string cleanString(const Value& cfg, const std::string& text) {
|
|
223
240
|
std::string out = text;
|
|
224
|
-
Value values =
|
|
241
|
+
Value values = cleanValues(cfg);
|
|
225
242
|
if (!values.is_list()) return out;
|
|
226
243
|
for (const auto& v : *values.as_list()) {
|
|
227
244
|
if (!v.is_string() || v.as_string().empty()) continue;
|
|
@@ -1776,7 +1793,7 @@ inline bool fieldArg(CtxPtr ctx, const std::string& name) {
|
|
|
1776
1793
|
|
|
1777
1794
|
// A header, cookie or query argument travels where prepareHeaders or
|
|
1778
1795
|
// prepareQuery sends it, so the body is built from the request data without
|
|
1779
|
-
// it, unless the
|
|
1796
|
+
// it, unless the point marks it as a field the body keeps.
|
|
1780
1797
|
inline std::vector<std::string> routedArgNames(CtxPtr ctx) {
|
|
1781
1798
|
std::vector<std::string> names;
|
|
1782
1799
|
for (const char* kind : {"header", "cookie", "query"}) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// ProjectName SDK - operation context.
|
|
2
2
|
|
|
3
|
+
using System.Collections.Concurrent;
|
|
4
|
+
|
|
3
5
|
using Voxgig.Struct;
|
|
4
6
|
|
|
5
7
|
namespace ProjectNameSdk;
|
|
@@ -17,7 +19,7 @@ public class Context
|
|
|
17
19
|
public Dictionary<string, object?>? Config;
|
|
18
20
|
public Dictionary<string, object?>? Entopts;
|
|
19
21
|
public Dictionary<string, object?>? Options;
|
|
20
|
-
public
|
|
22
|
+
public ConcurrentDictionary<string, Operation> Opmap = new();
|
|
21
23
|
public Response? Response;
|
|
22
24
|
public Result? Result;
|
|
23
25
|
public Spec? Spec;
|
|
@@ -145,7 +147,7 @@ public class Context
|
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
// Opmap
|
|
148
|
-
if (Helpers.GetCtxProp(ctxmap, "opmap") is
|
|
150
|
+
if (Helpers.GetCtxProp(ctxmap, "opmap") is ConcurrentDictionary<string, Operation> opm)
|
|
149
151
|
{
|
|
150
152
|
Opmap = opm;
|
|
151
153
|
}
|
|
@@ -153,7 +155,7 @@ public class Context
|
|
|
153
155
|
{
|
|
154
156
|
Opmap = basectx.Opmap;
|
|
155
157
|
}
|
|
156
|
-
Opmap ??= new
|
|
158
|
+
Opmap ??= new ConcurrentDictionary<string, Operation>();
|
|
157
159
|
|
|
158
160
|
// Data maps
|
|
159
161
|
Data = Helpers.ToMapAny(Helpers.GetCtxProp(ctxmap, "data")) ?? new Dictionary<string, object?>();
|
|
@@ -246,8 +248,9 @@ public class Context
|
|
|
246
248
|
["points"] = points,
|
|
247
249
|
});
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
// Requests on other threads share this cache; every one of them gets
|
|
252
|
+
// the Operation stored first.
|
|
253
|
+
return Opmap.GetOrAdd(cacheKey, op);
|
|
251
254
|
}
|
|
252
255
|
|
|
253
256
|
public ProjectNameError MakeError(string code, string msg)
|