@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
|
@@ -110,7 +110,7 @@ class EntityOperation {
|
|
|
110
110
|
}
|
|
111
111
|
else {
|
|
112
112
|
// Off-happy-path (throw disabled): typed as any so the method's
|
|
113
|
-
// Promise<
|
|
113
|
+
// Promise<EntyClass> return stays clean under strict null checks.
|
|
114
114
|
return undefined as any
|
|
115
115
|
}
|
|
116
116
|
}
|
|
@@ -111,7 +111,7 @@ class EntityOperation {
|
|
|
111
111
|
}
|
|
112
112
|
else {
|
|
113
113
|
// Off-happy-path (throw disabled): typed as any so the method's
|
|
114
|
-
// Promise<
|
|
114
|
+
// Promise<EntyClass> return stays clean under strict null checks.
|
|
115
115
|
return undefined as any
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -111,7 +111,7 @@ class EntityOperation {
|
|
|
111
111
|
}
|
|
112
112
|
else {
|
|
113
113
|
// Off-happy-path (throw disabled): typed as any so the method's
|
|
114
|
-
// Promise<
|
|
114
|
+
// Promise<EntyClass> return stays clean under strict null checks.
|
|
115
115
|
return undefined as any
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
canonScalarKey,
|
|
8
8
|
each,
|
|
9
9
|
opParams,
|
|
10
|
+
jsQuote,
|
|
10
11
|
} from '@voxgig/sdkgen'
|
|
11
12
|
|
|
12
13
|
import {
|
|
@@ -55,7 +56,7 @@ function exampleValue(entity: any, op: any, paramName: string, placeholder: stri
|
|
|
55
56
|
if ('NULL' === key) {
|
|
56
57
|
return 'null'
|
|
57
58
|
}
|
|
58
|
-
return
|
|
59
|
+
return jsQuote(placeholder)
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getModelPath,
|
|
7
7
|
} from '@voxgig/apidef'
|
|
8
8
|
|
|
9
|
-
import { zigVarName } from './utility_zig'
|
|
9
|
+
import { zigVarName, zigListMatch } from './utility_zig'
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
// Canonical type sentinel -> a zig type name for the field/param tables.
|
|
@@ -27,6 +27,7 @@ function zigType(type: any): string {
|
|
|
27
27
|
// A type-correct zig expression constructing a voxgig struct Value.
|
|
28
28
|
function zigLit(type: any, placeholder: string = 'example'): string {
|
|
29
29
|
const k = canonScalarKey(type)
|
|
30
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
30
31
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
31
32
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
32
33
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -154,7 +155,7 @@ switch (client.${method}(h.vnull()).load(${loadArg}, h.vnull())) {
|
|
|
154
155
|
Content(`#### Example: List
|
|
155
156
|
|
|
156
157
|
\`\`\`zig
|
|
157
|
-
switch (client.${method}(h.vnull()).list(
|
|
158
|
+
switch (client.${method}(h.vnull()).list(${zigListMatch(entity)}, h.vnull())) {
|
|
158
159
|
.ok => |${eVar}s| {
|
|
159
160
|
for (${eVar}s) |${eVar}| {
|
|
160
161
|
std.debug.print("{s}\\n", .{h.stringify(${eVar}.asEntity().data(null))});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, isAuthActive, envName, canonKey, canonScalarKey, entityIdField, pickExampleEntity, opRequestShape } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, isAuthActive, envName, canonKey, canonScalarKey, entityIdField, pickExampleEntity, opRequestShape, requiredItems } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -13,6 +13,7 @@ import { zigVarName } from './utility_zig'
|
|
|
13
13
|
// A type-correct zig expression constructing a voxgig struct Value.
|
|
14
14
|
function zigLit(type: any): string {
|
|
15
15
|
const k = canonScalarKey(type)
|
|
16
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
16
17
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
17
18
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
18
19
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -36,13 +37,16 @@ const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
|
|
|
36
37
|
let testArg = 'h.vnull()'
|
|
37
38
|
if (exampleEntity && isMatchOp) {
|
|
38
39
|
testArg = idF ? `h.jo(&.{.{ "${idF}", h.vstr("test01") }})` : 'h.vnull()'
|
|
40
|
+
} else if (exampleEntity && 'list' === primaryOp && 0 < requiredItems(exampleEntity, 'list').length) {
|
|
41
|
+
const chosen = requiredItems(exampleEntity, 'list')
|
|
42
|
+
testArg = `h.jo(&.{${chosen.map((it: any) => `.{ ${JSON.stringify(it.name)}, ${zigLit(it.type)} }`).join(', ')}})`
|
|
39
43
|
} else if (exampleEntity && ('create' === primaryOp || 'update' === primaryOp || 'patch' === primaryOp)) {
|
|
40
44
|
const items = opRequestShape(exampleEntity, primaryOp).items
|
|
41
45
|
.filter((it: any) => it.name !== idF && it.name !== 'id')
|
|
42
46
|
const required = items.filter((it: any) => !it.optional)
|
|
43
47
|
const chosen = required.length ? required : items.slice(0, 3)
|
|
44
48
|
testArg = 0 < chosen.length
|
|
45
|
-
? `h.jo(&.{${chosen.map((it: any) => `.{
|
|
49
|
+
? `h.jo(&.{${chosen.map((it: any) => `.{ ${JSON.stringify(it.name)}, ${zigLit(it.type)} }`).join(', ')}})`
|
|
46
50
|
: 'h.omap()'
|
|
47
51
|
}
|
|
48
52
|
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
nom,
|
|
8
8
|
} from '@voxgig/apidef'
|
|
9
9
|
|
|
10
|
-
import { zigVarName } from './utility_zig'
|
|
10
|
+
import { zigVarName, zigListMatch } from './utility_zig'
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
const ReadmeQuick = cmp(function ReadmeQuick(props: any) {
|
|
@@ -36,6 +36,7 @@ const ReadmeQuick = cmp(function ReadmeQuick(props: any) {
|
|
|
36
36
|
// A type-correct zig expression constructing a voxgig struct Value.
|
|
37
37
|
const zigLit = (type: any, placeholder: string = 'example'): string => {
|
|
38
38
|
const k = canonScalarKey(type)
|
|
39
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
39
40
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
40
41
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
41
42
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -70,7 +71,7 @@ const client = ${ctor};
|
|
|
70
71
|
it. \`asEntity().data(null)\` reads an entity's record.
|
|
71
72
|
|
|
72
73
|
\`\`\`zig
|
|
73
|
-
switch (client.${method}(h.vnull()).list(
|
|
74
|
+
switch (client.${method}(h.vnull()).list(${zigListMatch(exampleEntity)}, h.vnull())) {
|
|
74
75
|
.ok => |${eVar}s| {
|
|
75
76
|
for (${eVar}s) |${eVar}| {
|
|
76
77
|
std.debug.print("{s}\\n", .{h.stringify(${eVar}.asEntity().data(null))});
|
|
@@ -191,7 +192,7 @@ switch (client.${method}(h.vnull()).update(h.jo(&.{${updatePairs.join(', ')}}),
|
|
|
191
192
|
const patchPairs = (idF ? [`.{ "${idF}", ${idValueFor('patch')} }`] : []).concat(examplePairs('patch'))
|
|
192
193
|
Content(`// Patch — sends only the fields given
|
|
193
194
|
switch (client.${method}(h.vnull()).patch(h.jo(&.{${patchPairs.join(', ')}}), h.vnull())) {
|
|
194
|
-
.ok => |patched| std.debug.print("{s}\\n", .{h.stringify(patched)}),
|
|
195
|
+
.ok => |patched| std.debug.print("{s}\\n", .{h.stringify(patched.asEntity().data(null))}),
|
|
195
196
|
.err => |e| std.debug.print("patch failed: {s}\\n", .{e.msg}),
|
|
196
197
|
}
|
|
197
198
|
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getModelPath,
|
|
8
8
|
} from '@voxgig/apidef'
|
|
9
9
|
|
|
10
|
-
import { zigVarName } from './utility_zig'
|
|
10
|
+
import { zigVarName, zigListMatch } from './utility_zig'
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
// Canonical type sentinel -> a zig type name for the field/param tables.
|
|
@@ -26,6 +26,7 @@ function zigType(type: any): string {
|
|
|
26
26
|
// A type-correct zig expression constructing a voxgig struct Value.
|
|
27
27
|
function zigLit(type: any, placeholder: string = 'example'): string {
|
|
28
28
|
const k = canonScalarKey(type)
|
|
29
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
29
30
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
30
31
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
31
32
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -61,8 +62,8 @@ const ReadmeRef = cmp(function ReadmeRef(props: any) {
|
|
|
61
62
|
desc: 'Update an existing entity. The data must include the entity id. `.ok` carries the updated entity.',
|
|
62
63
|
},
|
|
63
64
|
patch: {
|
|
64
|
-
sig: 'patch(reqdata: Value, ctrl: Value)
|
|
65
|
-
desc: 'Change part of an existing entity: only the fields given are sent. The data must include the entity id. `.ok` carries the patched entity
|
|
65
|
+
sig: 'patch(reqdata: Value, ctrl: Value) EntResult',
|
|
66
|
+
desc: 'Change part of an existing entity: only the fields given are sent. The data must include the entity id. `.ok` carries the patched entity.',
|
|
66
67
|
},
|
|
67
68
|
remove: {
|
|
68
69
|
sig: 'remove(reqmatch: Value, ctrl: Value) EntResult',
|
|
@@ -290,7 +291,7 @@ switch (client.${method}(h.vnull()).${opname}(${arg}, h.vnull())) {
|
|
|
290
291
|
}
|
|
291
292
|
else if ('list' === opname) {
|
|
292
293
|
Content(`\`\`\`zig
|
|
293
|
-
switch (client.${method}(h.vnull()).list(
|
|
294
|
+
switch (client.${method}(h.vnull()).list(${zigListMatch(ent)}, h.vnull())) {
|
|
294
295
|
.ok => |results| {
|
|
295
296
|
for (results) |result| {
|
|
296
297
|
std.debug.print("{s}\\n", .{h.stringify(result.asEntity().data(null))});
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
nom,
|
|
8
8
|
} from '@voxgig/apidef'
|
|
9
9
|
|
|
10
|
-
import { zigVarName } from './utility_zig'
|
|
10
|
+
import { zigVarName, zigListMatch } from './utility_zig'
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
// A type-correct zig expression constructing a voxgig struct Value for a
|
|
@@ -15,6 +15,7 @@ import { zigVarName } from './utility_zig'
|
|
|
15
15
|
// render a typed literal.
|
|
16
16
|
function zigLit(type: any, placeholder: string = 'example'): string {
|
|
17
17
|
const k = canonScalarKey(type)
|
|
18
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
18
19
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
19
20
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
20
21
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -55,7 +56,7 @@ const client = ${ctor};
|
|
|
55
56
|
|
|
56
57
|
if (opnames.includes('list')) {
|
|
57
58
|
Content(`// List all ${eName.toLowerCase()}s (one entity per record, .err on failure)
|
|
58
|
-
switch (client.${method}(h.vnull()).list(
|
|
59
|
+
switch (client.${method}(h.vnull()).list(${zigListMatch(exampleEntity)}, h.vnull())) {
|
|
59
60
|
.ok => |${eVar}s| {
|
|
60
61
|
for (${eVar}s) |${eVar}| {
|
|
61
62
|
std.debug.print("{s}\\n", .{h.stringify(${eVar}.asEntity().data(null))});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, canonKey, canonScalarKey, entityIdField, pickExampleEntity, opRequestShape } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, canonKey, canonScalarKey, entityIdField, pickExampleEntity, opRequestShape, requiredItems } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -13,6 +13,7 @@ import { zigVarName } from './utility_zig'
|
|
|
13
13
|
// A type-correct zig expression constructing a voxgig struct Value.
|
|
14
14
|
function zigLit(type: any): string {
|
|
15
15
|
const k = canonScalarKey(type)
|
|
16
|
+
if ('NULL' === k) return 'h.vnull()'
|
|
16
17
|
if ('INTEGER' === k || 'NUMBER' === k) return 'h.vnum(1)'
|
|
17
18
|
if ('BOOLEAN' === k) return 'h.vbool(true)'
|
|
18
19
|
if ('ARRAY' === k) return 'h.olist()'
|
|
@@ -43,16 +44,16 @@ const client = sdk.test_sdk(h.vnull(), h.vnull());
|
|
|
43
44
|
const idF = entityIdField(exampleEntity)
|
|
44
45
|
const isMatchOp = 'load' === primaryOp || 'remove' === primaryOp
|
|
45
46
|
let arg = 'h.vnull()'
|
|
46
|
-
if (isMatchOp) {
|
|
47
|
+
if (isMatchOp || ('list' === primaryOp && 0 < requiredItems(exampleEntity, 'list').length)) {
|
|
47
48
|
// Every REQUIRED match key (id first) — the same shape that generates
|
|
48
49
|
// the op's request match.
|
|
49
|
-
const items = opRequestShape(exampleEntity, primaryOp).items
|
|
50
|
-
.filter((it: any) => !it.optional || it.name === idF)
|
|
50
|
+
const items = (isMatchOp ? opRequestShape(exampleEntity, primaryOp).items
|
|
51
|
+
.filter((it: any) => !it.optional || it.name === idF) : requiredItems(exampleEntity, 'list'))
|
|
51
52
|
.sort((a: any, b: any) =>
|
|
52
53
|
(a.name === idF ? 0 : 1) - (b.name === idF ? 0 : 1))
|
|
53
54
|
arg = 0 < items.length
|
|
54
55
|
? `h.jo(&.{${items.map((it: any) =>
|
|
55
|
-
`.{
|
|
56
|
+
`.{ ${JSON.stringify(it.name)}, ${isMatchOp && it.name === idF ? 'h.vstr("test01")' : zigLit(it.type)} }`).join(', ')}})`
|
|
56
57
|
: 'h.vnull()'
|
|
57
58
|
} else if ('create' === primaryOp || 'update' === primaryOp || 'patch' === primaryOp) {
|
|
58
59
|
const items = opRequestShape(exampleEntity, primaryOp).items
|
|
@@ -60,7 +61,7 @@ const client = sdk.test_sdk(h.vnull(), h.vnull());
|
|
|
60
61
|
const required = items.filter((it: any) => !it.optional)
|
|
61
62
|
const chosen = required.length ? required : items.slice(0, 3)
|
|
62
63
|
arg = 0 < chosen.length
|
|
63
|
-
? `h.jo(&.{${chosen.map((it: any) => `.{
|
|
64
|
+
? `h.jo(&.{${chosen.map((it: any) => `.{ ${JSON.stringify(it.name)}, ${zigLit(it.type)} }`).join(', ')}})`
|
|
64
65
|
: 'h.omap()'
|
|
65
66
|
}
|
|
66
67
|
const eVar = zigVarName(exampleEntity.name)
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
walk,
|
|
5
5
|
} from '@voxgig/struct'
|
|
6
6
|
|
|
7
|
+
import { canonScalarKey, requiredItems } from '@voxgig/sdkgen'
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
// Zig keywords that are illegal as a plain identifier.
|
|
9
11
|
const ZIG_RESERVED = new Set<string>([
|
|
@@ -138,8 +140,19 @@ function clean(o: any, dropDefaults?: boolean): any {
|
|
|
138
140
|
return prune(o, true === dropDefaults)
|
|
139
141
|
}
|
|
140
142
|
|
|
143
|
+
// A list's required route and query parameters, as the match it is called with.
|
|
144
|
+
function zigListMatch(entity: any): string {
|
|
145
|
+
const lit = (type: any): string =>
|
|
146
|
+
(({ NULL: 'h.vnull()', INTEGER: 'h.vnum(1)', NUMBER: 'h.vnum(1)', BOOLEAN: 'h.vbool(true)', ARRAY: 'h.olist()', OBJECT: 'h.omap()' }) as any)[canonScalarKey(type)] ?? 'h.vstr("example")'
|
|
147
|
+
const items = requiredItems(entity, 'list')
|
|
148
|
+
return 0 < items.length
|
|
149
|
+
? `h.jo(&.{${items.map((it: any) => `.{ ${JSON.stringify(it.name)}, ${lit(it.type)} }`).join(', ')}})`
|
|
150
|
+
: 'h.vnull()'
|
|
151
|
+
}
|
|
152
|
+
|
|
141
153
|
|
|
142
154
|
export {
|
|
155
|
+
zigListMatch,
|
|
143
156
|
clean,
|
|
144
157
|
formatZigValue,
|
|
145
158
|
zigModuleName,
|
|
@@ -27,7 +27,7 @@ static bool field_arg(Context* ctx, const char* name) {
|
|
|
27
27
|
|
|
28
28
|
/* A header, cookie or query argument travels where prepare_headers_util or
|
|
29
29
|
prepare_query_util sends it, so the body is built from the request data
|
|
30
|
-
without it, unless the
|
|
30
|
+
without it, unless the point marks it as a field the body keeps. */
|
|
31
31
|
static voxgig_value* routed_args(Context* ctx) {
|
|
32
32
|
voxgig_value* routed = voxgig_new_list();
|
|
33
33
|
for (size_t k = 0; k < 3; k++) {
|
|
@@ -395,8 +395,8 @@
|
|
|
395
395
|
points (let [t (when (vs/ismap opcfg) (vs/getprop opcfg "points"))]
|
|
396
396
|
(if (vs/islist t) t (vs/jt)))
|
|
397
397
|
op (make-operation (vs/jm "entity" entname "name" opname "input" input "points" points))]
|
|
398
|
-
|
|
399
|
-
op))))
|
|
398
|
+
;; Every request racing to build this Operation gets the one stored first.
|
|
399
|
+
(get (swap! opmap #(if (contains? % cache-key) % (assoc % cache-key op))) cache-key)))))
|
|
400
400
|
|
|
401
401
|
;; ---------------------------------------------------------------------------
|
|
402
402
|
;; Feature dispatch.
|
|
@@ -488,19 +488,21 @@
|
|
|
488
488
|
(let [n (try (long (Math/floor (Double/parseDouble (str v)))) (catch Exception _ nil))]
|
|
489
489
|
(if (and n (<= 0 n)) n dflt)))
|
|
490
490
|
|
|
491
|
-
;; The derived clean block: a
|
|
492
|
-
;; and its `values` list
|
|
493
|
-
;; what they resolve later.
|
|
491
|
+
;; The derived clean block: a java.util.Map so it lives in options.__derived__
|
|
492
|
+
;; and its `values` list can be replaced after make-options - features
|
|
493
|
+
;; register what they resolve later. Concurrent, so a clean or a request
|
|
494
|
+
;; copying the options reads it without the lock and sees the last put.
|
|
494
495
|
(defn make-clean-config [cleanopts]
|
|
495
496
|
(let [o (fn [k] (mget cleanopts k))
|
|
496
497
|
keys (vs/jt)]
|
|
497
498
|
(doseq [k (splitkeys (o "keys"))] (.add ^java.util.List keys k))
|
|
498
|
-
(
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
499
|
+
(doto (java.util.concurrent.ConcurrentHashMap.)
|
|
500
|
+
(.put "active" (not= false (o "active")))
|
|
501
|
+
(.put "keys" keys)
|
|
502
|
+
(.put "values" (vs/jt))
|
|
503
|
+
(.put "mask" (let [m (o "mask")] (if (string? m) m "[redacted]")))
|
|
504
|
+
(.put "hint" (count-opt (o "hint") 0))
|
|
505
|
+
(.put "min" (max 1 (count-opt (o "min") 4))))))
|
|
504
506
|
|
|
505
507
|
;; A context without options (make-error accepts a bare one) still masks by
|
|
506
508
|
;; the schema defaults.
|
|
@@ -521,21 +523,25 @@
|
|
|
521
523
|
|
|
522
524
|
(defn u-clean-add [ctx value]
|
|
523
525
|
(let [cfg (clean-config ctx)
|
|
524
|
-
minlen (long (or (mget cfg "min") 4))
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
(let [
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
526
|
+
minlen (long (or (mget cfg "min") 4))]
|
|
527
|
+
(when (and (string? value) (>= (count value) minlen)
|
|
528
|
+
(instance? java.util.List (mget cfg "values")))
|
|
529
|
+
(let [forms (filterv #(>= (count %) minlen) (clean-forms value))]
|
|
530
|
+
;; Every request copies the options, the registry among them, so a
|
|
531
|
+
;; registration publishes a new vector and never changes a published one.
|
|
532
|
+
(locking cfg
|
|
533
|
+
(let [values (vec (mget cfg "values"))
|
|
534
|
+
added (remove #(.contains ^java.util.List values %) forms)]
|
|
535
|
+
;; Longest first, so a value is never masked by a substring of itself.
|
|
536
|
+
(when (seq added)
|
|
537
|
+
(.put ^java.util.Map cfg "values"
|
|
538
|
+
(vec (sort-by (fn [^String s] (- (count s))) (into values added)))))))))
|
|
537
539
|
nil))
|
|
538
540
|
|
|
541
|
+
(defn- registered [cfg]
|
|
542
|
+
(let [values (mget cfg "values")]
|
|
543
|
+
(if (instance? java.util.List values) values [])))
|
|
544
|
+
|
|
539
545
|
(defn- mask-value [cfg ^String value]
|
|
540
546
|
(let [hint (long (or (mget cfg "hint") 0))
|
|
541
547
|
mask (str (mget cfg "mask"))]
|
|
@@ -547,7 +553,7 @@
|
|
|
547
553
|
(reduce (fn [^String out ^String value]
|
|
548
554
|
(if (.contains out value) (str/replace out value (mask-value cfg value)) out))
|
|
549
555
|
text
|
|
550
|
-
(
|
|
556
|
+
(registered cfg)))
|
|
551
557
|
|
|
552
558
|
(defn- sensitive-key? [cfg key]
|
|
553
559
|
(if (or (nil? key) (number? key))
|
|
@@ -1003,7 +1009,7 @@
|
|
|
1003
1009
|
|
|
1004
1010
|
;; A header, cookie or query argument travels where u-prepare-headers or
|
|
1005
1011
|
;; u-prepare-query sends it, so the body is built from the request data
|
|
1006
|
-
;; without it, unless the
|
|
1012
|
+
;; without it, unless the point marks it as a field the body keeps.
|
|
1007
1013
|
(defn- routed-arg-names [ctx]
|
|
1008
1014
|
(->> (concat (call-args ctx "header") (call-args ctx "cookie") (call-args ctx "query"))
|
|
1009
1015
|
(map first)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
;; ProjectName SDK concurrency tests - requests in flight at once on one
|
|
2
|
+
;; client. Each resolves its operation through the cache the client's root
|
|
3
|
+
;; context shares with every request, and registers and cleans secrets
|
|
4
|
+
;; through the one registry the client holds.
|
|
5
|
+
(ns sdk.test.concurrency
|
|
6
|
+
(:require [sdk.core :as core]
|
|
7
|
+
[sdk.client :as client]
|
|
8
|
+
[sdk.testutil :as t]
|
|
9
|
+
[voxgig.struct :as vs])
|
|
10
|
+
(:import [java.util.concurrent ConcurrentLinkedQueue CountDownLatch CyclicBarrier]))
|
|
11
|
+
|
|
12
|
+
(def ^:private rounds 200)
|
|
13
|
+
(def ^:private width 8)
|
|
14
|
+
(def ^:private ops 32)
|
|
15
|
+
(def ^:private masked "a [redacted] b [redacted] c")
|
|
16
|
+
|
|
17
|
+
;; Runs body on width threads released together, and returns what they threw.
|
|
18
|
+
(defn- at-once [body]
|
|
19
|
+
(let [start (CyclicBarrier. width)
|
|
20
|
+
thrown (ConcurrentLinkedQueue.)
|
|
21
|
+
threads (mapv (fn [n]
|
|
22
|
+
(doto (Thread. ^Runnable (fn []
|
|
23
|
+
(try
|
|
24
|
+
(.await start)
|
|
25
|
+
(body n)
|
|
26
|
+
(catch Throwable e (.add thrown e)))))
|
|
27
|
+
(.start)))
|
|
28
|
+
(range width))]
|
|
29
|
+
(doseq [^Thread thread threads] (.join thread))
|
|
30
|
+
(vec thrown)))
|
|
31
|
+
|
|
32
|
+
(defn- resolve-op [root k]
|
|
33
|
+
(core/oget (core/make-context (vs/jm "opname" (str "op" k)) root) :op))
|
|
34
|
+
|
|
35
|
+
(defn- resolutions-share-one-cached-operation []
|
|
36
|
+
(dotimes [round rounds]
|
|
37
|
+
(let [sdk (client/test-sdk nil nil)
|
|
38
|
+
root @(:root-ctx sdk)
|
|
39
|
+
got (vec (repeatedly width #(object-array ops)))
|
|
40
|
+
thrown (at-once (fn [n] (dotimes [k ops] (aset ^objects (got n) k (resolve-op root k)))))]
|
|
41
|
+
(t/is-true (empty? thrown) (str "round " round " threw: " (pr-str thrown)))
|
|
42
|
+
(dotimes [k ops]
|
|
43
|
+
(let [cached (resolve-op root k)]
|
|
44
|
+
(dotimes [n width]
|
|
45
|
+
(t/is-true (identical? cached (aget ^objects (got n) k))
|
|
46
|
+
(str "round " round ": op" k " resolved to more than one Operation"))))))))
|
|
47
|
+
|
|
48
|
+
;; A live client whose transport answers at once.
|
|
49
|
+
(defn- live-sdk []
|
|
50
|
+
(client/make-sdk
|
|
51
|
+
(vs/jm "base" "http://concurrency.test/api"
|
|
52
|
+
"allow" (vs/jm "op" "direct")
|
|
53
|
+
"system" (vs/jm "fetch" (fn [_url _fetchdef]
|
|
54
|
+
[(vs/jm "status" 200 "statusText" "OK" "headers" (vs/jm)
|
|
55
|
+
"json" (fn [] (vs/jm "ok" true)))
|
|
56
|
+
nil])))))
|
|
57
|
+
|
|
58
|
+
(defn- added-secret [round n k] (str "ADDED-SECRET-" round "-" n "-" k))
|
|
59
|
+
|
|
60
|
+
;; Registers thread n's secrets, then counts the thread out of registering.
|
|
61
|
+
(defn- register-secrets [clean-add ^CountDownLatch registering round n]
|
|
62
|
+
(try
|
|
63
|
+
(dotimes [k ops] (clean-add (added-secret round n k)))
|
|
64
|
+
(finally (.countDown registering))))
|
|
65
|
+
|
|
66
|
+
(defn- every-secret-masked [clean round]
|
|
67
|
+
(dotimes [n (quot width 2)]
|
|
68
|
+
(dotimes [k ops]
|
|
69
|
+
(let [added (added-secret round n k)]
|
|
70
|
+
(t/is-eq (clean added) "[redacted]"
|
|
71
|
+
(str "round " round ": " added " was registered but not masked"))))))
|
|
72
|
+
|
|
73
|
+
;; Secrets registered on some threads while others clean: every clean masks
|
|
74
|
+
;; what was registered before it, the longer secret whole, and no
|
|
75
|
+
;; registration is lost.
|
|
76
|
+
(defn- registration-keeps-every-secret-masked []
|
|
77
|
+
(dotimes [round (quot rounds 4)]
|
|
78
|
+
(let [sdk (client/test-sdk nil nil)
|
|
79
|
+
root @(:root-ctx sdk)
|
|
80
|
+
clean (fn [v] ((core/uget root :clean) root v))
|
|
81
|
+
clean-add (fn [v] ((core/uget root :clean-add) root v))
|
|
82
|
+
inner (str "INNER-SECRET-" round)
|
|
83
|
+
text (str "a " inner " b OUTER-" inner "-TAIL c")
|
|
84
|
+
_ (clean-add inner)
|
|
85
|
+
_ (clean-add (str "OUTER-" inner "-TAIL"))
|
|
86
|
+
_ (t/is-eq (clean text) masked (str "round " round))
|
|
87
|
+
registering (CountDownLatch. (quot width 2))
|
|
88
|
+
wrong (ConcurrentLinkedQueue.)
|
|
89
|
+
thrown (at-once
|
|
90
|
+
(fn [n]
|
|
91
|
+
(if (< n (quot width 2))
|
|
92
|
+
(register-secrets clean-add registering round n)
|
|
93
|
+
(loop []
|
|
94
|
+
(when (pos? (.getCount registering))
|
|
95
|
+
(let [got (clean text)]
|
|
96
|
+
(if (= masked got) (recur) (.add wrong got))))))))]
|
|
97
|
+
(t/is-true (empty? thrown) (str "round " round " threw: " (pr-str thrown)))
|
|
98
|
+
(t/is-true (.isEmpty wrong) (str "round " round " cleaned to: " (pr-str (vec wrong))))
|
|
99
|
+
(every-secret-masked clean round))))
|
|
100
|
+
|
|
101
|
+
;; Requests on one client while secrets register on it: each request copies
|
|
102
|
+
;; the client's options, the registry among them.
|
|
103
|
+
(defn- requests-survive-registration []
|
|
104
|
+
(dotimes [round (quot rounds 4)]
|
|
105
|
+
(let [sdk (live-sdk)
|
|
106
|
+
root @(:root-ctx sdk)
|
|
107
|
+
clean (fn [v] ((core/uget root :clean) root v))
|
|
108
|
+
clean-add (fn [v] ((core/uget root :clean-add) root v))
|
|
109
|
+
registering (CountDownLatch. (quot width 2))
|
|
110
|
+
failed (ConcurrentLinkedQueue.)
|
|
111
|
+
thrown (at-once
|
|
112
|
+
(fn [n]
|
|
113
|
+
(if (< n (quot width 2))
|
|
114
|
+
(register-secrets clean-add registering round n)
|
|
115
|
+
(loop []
|
|
116
|
+
(when (pos? (.getCount registering))
|
|
117
|
+
(let [res (client/direct sdk (vs/jm "path" (str "p" n)))]
|
|
118
|
+
(if (true? (vs/getprop res "ok")) (recur) (.add failed res))))))))]
|
|
119
|
+
(t/is-true (empty? thrown) (str "round " round " threw: " (pr-str thrown)))
|
|
120
|
+
(t/is-true (.isEmpty failed) (str "round " round ", a request failed: " (pr-str (vec failed))))
|
|
121
|
+
(every-secret-masked clean round))))
|
|
122
|
+
|
|
123
|
+
(defn run [rec]
|
|
124
|
+
(let [ran (atom 0)
|
|
125
|
+
failed (atom 0)
|
|
126
|
+
counting (fn [name ok? msg]
|
|
127
|
+
(swap! ran inc)
|
|
128
|
+
(when-not ok? (swap! failed inc))
|
|
129
|
+
(rec name ok? msg))]
|
|
130
|
+
(t/run-check counting "concurrency-resolutions-share-one-cached-operation"
|
|
131
|
+
resolutions-share-one-cached-operation)
|
|
132
|
+
(t/run-check counting "concurrency-registration-keeps-every-secret-masked"
|
|
133
|
+
registration-keeps-every-secret-masked)
|
|
134
|
+
(t/run-check counting "concurrency-requests-survive-registration"
|
|
135
|
+
requests-survive-registration)
|
|
136
|
+
(println (str "concurrency: " @ran " check(s), " @failed " failed"))))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
;; ProjectName SDK test runner (tools.deps main entry point).
|
|
2
2
|
;; Runs the vendored omni runner's smoke test, the API-agnostic suites
|
|
3
|
-
;; (primary utility, pipeline, features, netsim), the generated API-specific
|
|
3
|
+
;; (primary utility, pipeline, features, netsim, concurrency), the generated API-specific
|
|
4
4
|
;; suite, and the vendored struct corpus, then reports counts and exits
|
|
5
5
|
;; non-zero on any failure. `--sdk-only` skips the corpus steps (see -main).
|
|
6
6
|
(ns sdk.test-runner
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
[sdk.test.struct-corpus :as corpus]
|
|
12
12
|
[sdk.test.omni-smoke :as omnismoke]
|
|
13
13
|
[sdk.test.clean :as clean]
|
|
14
|
+
[sdk.test.concurrency :as concurrency]
|
|
14
15
|
[sdk.gentest :as gentest]
|
|
15
16
|
[clojure.java.io :as io]))
|
|
16
17
|
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
(feature/run rec)
|
|
120
121
|
(run-feature-suites rec)
|
|
121
122
|
(netsim/run rec)
|
|
123
|
+
(concurrency/run rec)
|
|
122
124
|
(gentest/run rec)
|
|
123
125
|
;; The canary sweep (generated: sdk/test/clean.clj) prints its own
|
|
124
126
|
;; `clean: swept N surface(s), M leak(s)` line, which sdkgen's lane reads.
|
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
#define SDK_CORE_TYPES_HPP
|
|
13
13
|
|
|
14
14
|
#include <algorithm>
|
|
15
|
+
#include <atomic>
|
|
15
16
|
#include <cctype>
|
|
16
17
|
#include <functional>
|
|
17
18
|
#include <map>
|
|
18
19
|
#include <memory>
|
|
20
|
+
#include <mutex>
|
|
19
21
|
#include <ostream>
|
|
22
|
+
#include <shared_mutex>
|
|
20
23
|
#include <stdexcept>
|
|
21
24
|
#include <string>
|
|
22
25
|
#include <vector>
|
|
@@ -51,7 +54,11 @@ using FeaturePtr = std::shared_ptr<Feature>;
|
|
|
51
54
|
using UtilityPtr = std::shared_ptr<Utility>;
|
|
52
55
|
using CtxPtr = std::shared_ptr<Context>;
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
// Shared by every context of one client, so by requests on several threads.
|
|
58
|
+
struct OpMap {
|
|
59
|
+
std::mutex lock;
|
|
60
|
+
std::map<std::string, OperationPtr> ops;
|
|
61
|
+
};
|
|
55
62
|
using OpMapPtr = std::shared_ptr<OpMap>;
|
|
56
63
|
|
|
57
64
|
// Generated (core/config.hpp) — the embedded API config + feature factory.
|
|
@@ -623,6 +630,24 @@ public:
|
|
|
623
630
|
|
|
624
631
|
// ---- SdkClient --------------------------------------------------------
|
|
625
632
|
|
|
633
|
+
// A registration replaces the secret registry (options.__derived__.clean
|
|
634
|
+
// .values) while requests copy the options: it holds this lock exclusively,
|
|
635
|
+
// and every read of that slot holds it shared.
|
|
636
|
+
inline std::shared_mutex& cleanRegistryLock() {
|
|
637
|
+
// winpthreads sets up a static rwlock on its first lock, failing threads
|
|
638
|
+
// that race it with EINVAL; that first lock runs in this static's
|
|
639
|
+
// initialization, which every other caller waits for.
|
|
640
|
+
struct Warmed {
|
|
641
|
+
std::shared_mutex lock;
|
|
642
|
+
Warmed() {
|
|
643
|
+
lock.lock();
|
|
644
|
+
lock.unlock();
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
static Warmed warmed;
|
|
648
|
+
return warmed.lock;
|
|
649
|
+
}
|
|
650
|
+
|
|
626
651
|
class SdkClient {
|
|
627
652
|
public:
|
|
628
653
|
std::string mode = "live";
|
|
@@ -744,7 +769,7 @@ inline SdkErrorPtr Helpers::unsupportedOp(const std::string& opname,
|
|
|
744
769
|
|
|
745
770
|
// ---- Context ----
|
|
746
771
|
inline Context::Context(const CtxSpec& cs, const CtxPtr& basectx) {
|
|
747
|
-
static long long counter
|
|
772
|
+
static std::atomic<long long> counter{10000000};
|
|
748
773
|
id = "C" + std::to_string(++counter);
|
|
749
774
|
|
|
750
775
|
// Client
|
|
@@ -826,8 +851,11 @@ inline OperationPtr Context::resolveOp(const std::string& opname) {
|
|
|
826
851
|
if (entity) entname = entity->getName();
|
|
827
852
|
std::string cacheKey = entname + ":" + opname;
|
|
828
853
|
|
|
829
|
-
|
|
830
|
-
|
|
854
|
+
{
|
|
855
|
+
std::lock_guard<std::mutex> guard(opmap->lock);
|
|
856
|
+
auto it = opmap->ops.find(cacheKey);
|
|
857
|
+
if (it != opmap->ops.end()) return it->second;
|
|
858
|
+
}
|
|
831
859
|
|
|
832
860
|
if (opname.empty()) {
|
|
833
861
|
return std::make_shared<Operation>(vmap());
|
|
@@ -852,8 +880,9 @@ inline OperationPtr Context::resolveOp(const std::string& opname) {
|
|
|
852
880
|
map_put(opdef, "points", points);
|
|
853
881
|
|
|
854
882
|
auto op_ = std::make_shared<Operation>(opdef);
|
|
855
|
-
|
|
856
|
-
|
|
883
|
+
// Every request racing to build this Operation gets the one stored first.
|
|
884
|
+
std::lock_guard<std::mutex> guard(opmap->lock);
|
|
885
|
+
return opmap->ops.emplace(cacheKey, op_).first->second;
|
|
857
886
|
}
|
|
858
887
|
|
|
859
888
|
inline SdkErrorPtr Context::makeError(const std::string& code, const std::string& msg) {
|
|
@@ -951,6 +980,7 @@ inline SdkClient::SdkClient(const Value& options_) {
|
|
|
951
980
|
}
|
|
952
981
|
|
|
953
982
|
inline Value SdkClient::optionsMap() {
|
|
983
|
+
std::shared_lock<std::shared_mutex> guard(cleanRegistryLock());
|
|
954
984
|
Value out = Struct::clone(options);
|
|
955
985
|
return out.is_map() ? out : vmap();
|
|
956
986
|
}
|