@voxgig/sdkgen 4.22.0 → 4.24.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 +18 -2
- package/dist/action/doctor.d.ts +1 -1
- package/dist/action/doctor.js +12 -10
- package/dist/action/doctor.js.map +1 -1
- package/dist/action/edition.js +4 -0
- package/dist/action/edition.js.map +1 -1
- package/dist/action/feature.js +5 -1
- package/dist/action/feature.js.map +1 -1
- package/dist/action/remove.d.ts +16 -0
- package/dist/action/remove.js +345 -0
- package/dist/action/remove.js.map +1 -0
- package/dist/action/target.js +6 -1
- package/dist/action/target.js.map +1 -1
- package/dist/cmp/ReadmeTop.js +1 -1
- package/dist/cmp/ReadmeTop.js.map +1 -1
- package/dist/cmp/ReadmeUnions.js +1 -1
- package/dist/cmp/ReadmeUnions.js.map +1 -1
- package/dist/cmp/Test.js +1 -1
- package/dist/cmp/Test.js.map +1 -1
- package/dist/helpers/buildIdNames.d.ts +3 -1
- package/dist/helpers/buildIdNames.js +15 -7
- package/dist/helpers/buildIdNames.js.map +1 -1
- package/dist/helpers/canonSpec.js +2 -2
- package/dist/helpers/canonSpec.js.map +1 -1
- package/dist/helpers/getMatchEntries.js +2 -2
- package/dist/helpers/getMatchEntries.js.map +1 -1
- package/dist/helpers/modelNames.js +5 -1
- package/dist/helpers/modelNames.js.map +1 -1
- package/dist/helpers/opShape.js +33 -33
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/helpers/pointPath.js +5 -10
- package/dist/helpers/pointPath.js.map +1 -1
- package/dist/helpers/resolved.js +2 -29
- package/dist/helpers/resolved.js.map +1 -1
- package/dist/sdkgen.d.ts +2 -2
- package/dist/sdkgen.js +5 -3
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.js +15 -7
- package/dist/utility.js.map +1 -1
- package/package.json +3 -3
- package/project/.sdk/src/cmp/c/EntityTypes_c.ts +4 -4
- package/project/.sdk/src/cmp/c/ReadmeEntity_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeModel_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeRef_c.ts +5 -5
- package/project/.sdk/src/cmp/c/Schema_c.ts +1 -1
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +12 -12
- package/project/.sdk/src/cmp/clojure/ReadmeEntity_clojure.ts +3 -3
- package/project/.sdk/src/cmp/clojure/ReadmeModel_clojure.ts +3 -3
- package/project/.sdk/src/cmp/clojure/ReadmeRef_clojure.ts +5 -5
- package/project/.sdk/src/cmp/clojure/Schema_clojure.ts +1 -1
- package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/ReadmeEntity_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/ReadmeModel_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/ReadmeRef_cpp.ts +5 -5
- package/project/.sdk/src/cmp/cpp/Schema_cpp.ts +1 -1
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +14 -14
- package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +51 -50
- package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +4 -4
- package/project/.sdk/src/cmp/csharp/ReadmeEntity_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/ReadmeModel_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/ReadmeRef_csharp.ts +5 -5
- package/project/.sdk/src/cmp/csharp/Schema_csharp.ts +1 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +30 -30
- package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +66 -65
- package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +4 -4
- package/project/.sdk/src/cmp/elixir/ReadmeEntity_elixir.ts +3 -3
- package/project/.sdk/src/cmp/elixir/ReadmeModel_elixir.ts +3 -3
- package/project/.sdk/src/cmp/elixir/ReadmeRef_elixir.ts +4 -4
- package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +1 -1
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +4 -4
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +3 -3
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +3 -3
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +5 -5
- package/project/.sdk/src/cmp/go/Schema_go.ts +1 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +38 -38
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +75 -74
- package/project/.sdk/src/cmp/go/utility_go.ts +5 -5
- package/project/.sdk/src/cmp/java/EntityTypes_java.ts +4 -4
- package/project/.sdk/src/cmp/java/ReadmeEntity_java.ts +3 -3
- package/project/.sdk/src/cmp/java/ReadmeModel_java.ts +3 -3
- package/project/.sdk/src/cmp/java/ReadmeRef_java.ts +5 -5
- package/project/.sdk/src/cmp/java/Schema_java.ts +1 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +30 -30
- package/project/.sdk/src/cmp/java/TestEntity_java.ts +69 -68
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +5 -5
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +3 -3
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +3 -3
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +5 -5
- package/project/.sdk/src/cmp/js/Schema_js.ts +1 -1
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +27 -27
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +66 -69
- package/project/.sdk/src/cmp/js/TestLive_js.ts +3 -3
- package/project/.sdk/src/cmp/js/utility_js.ts +5 -5
- package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +4 -4
- package/project/.sdk/src/cmp/kotlin/ReadmeEntity_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/ReadmeModel_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/ReadmeRef_kotlin.ts +5 -5
- package/project/.sdk/src/cmp/kotlin/Schema_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +30 -30
- package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +67 -66
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +5 -5
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +4 -4
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +5 -5
- package/project/.sdk/src/cmp/lua/Schema_lua.ts +1 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +25 -25
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +66 -65
- package/project/.sdk/src/cmp/ocaml/ReadmeEntity_ocaml.ts +3 -3
- package/project/.sdk/src/cmp/ocaml/ReadmeModel_ocaml.ts +3 -3
- package/project/.sdk/src/cmp/ocaml/ReadmeRef_ocaml.ts +5 -5
- package/project/.sdk/src/cmp/ocaml/Schema_ocaml.ts +1 -1
- package/project/.sdk/src/cmp/perl/ReadmeEntity_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/ReadmeModel_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/ReadmeRef_perl.ts +5 -5
- package/project/.sdk/src/cmp/perl/Schema_perl.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +25 -25
- package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +60 -59
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +4 -4
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +3 -3
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +3 -3
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +4 -4
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +5 -5
- package/project/.sdk/src/cmp/php/Schema_php.ts +1 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +25 -25
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +66 -65
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +4 -4
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +3 -3
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +5 -5
- package/project/.sdk/src/cmp/py/Schema_py.ts +1 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +25 -25
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +66 -65
- package/project/.sdk/src/cmp/py-data/Main_py-data.ts +4 -4
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +4 -4
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +4 -4
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +5 -5
- package/project/.sdk/src/cmp/rb/Schema_rb.ts +1 -1
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +25 -25
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +66 -65
- package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +4 -4
- package/project/.sdk/src/cmp/rust/ReadmeEntity_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/ReadmeModel_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/ReadmeRef_rust.ts +5 -5
- package/project/.sdk/src/cmp/rust/Schema_rust.ts +1 -1
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +18 -18
- package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +63 -62
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +4 -4
- package/project/.sdk/src/cmp/scala/ReadmeEntity_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/ReadmeModel_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/ReadmeRef_scala.ts +5 -5
- package/project/.sdk/src/cmp/scala/Schema_scala.ts +1 -1
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +14 -14
- package/project/.sdk/src/cmp/scala/TestEntity_scala.ts +60 -59
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +4 -4
- package/project/.sdk/src/cmp/swift/ReadmeEntity_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/ReadmeModel_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/ReadmeRef_swift.ts +5 -5
- package/project/.sdk/src/cmp/swift/Schema_swift.ts +1 -1
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +5 -5
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +1 -1
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +5 -5
- package/project/.sdk/src/cmp/ts/Schema_ts.ts +1 -1
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +40 -40
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +72 -75
- package/project/.sdk/src/cmp/ts/TestLive_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/utility_ts.ts +5 -5
- package/project/.sdk/src/cmp/zig/ReadmeEntity_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/ReadmeModel_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/ReadmeRef_zig.ts +5 -5
- package/project/.sdk/src/cmp/zig/Schema_zig.ts +1 -1
- package/project/.sdk/tm/c/core/context.c +3 -1
- package/project/.sdk/tm/c/feature/paging.c +37 -3
- package/project/.sdk/tm/c/feature/test.c +71 -31
- package/project/.sdk/tm/c/utility/prepare_query.c +2 -1
- package/project/.sdk/tm/c/utility/transform_request.c +25 -3
- package/project/.sdk/tm/clojure/src/sdk/core.clj +21 -7
- package/project/.sdk/tm/clojure/src/sdk/features.clj +74 -22
- package/project/.sdk/tm/cpp/core/types.hpp +1 -1
- package/project/.sdk/tm/cpp/feature/paging.hpp +36 -3
- package/project/.sdk/tm/cpp/feature/test.hpp +58 -19
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +16 -4
- package/project/.sdk/tm/csharp/core/Context.cs +1 -1
- package/project/.sdk/tm/csharp/feature/PagingFeature.cs +58 -4
- package/project/.sdk/tm/csharp/feature/TestFeature.cs +23 -25
- package/project/.sdk/tm/csharp/utility/Fetcher.cs +19 -12
- package/project/.sdk/tm/csharp/utility/PrepareQuery.cs +1 -1
- package/project/.sdk/tm/csharp/utility/TransformRequest.cs +23 -3
- package/project/.sdk/tm/elixir/lib/projectname/context.ex +1 -1
- package/project/.sdk/tm/elixir/lib/projectname/feature/paging.ex +52 -10
- package/project/.sdk/tm/elixir/lib/projectname/feature/test.ex +58 -22
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +30 -9
- package/project/.sdk/tm/go/core/context.go +13 -13
- package/project/.sdk/tm/go/feature/paging_feature.go +40 -2
- package/project/.sdk/tm/go/feature/test_feature.go +3 -15
- package/project/.sdk/tm/go/test/feature_corpus_test.go +1 -0
- package/project/.sdk/tm/go/test/feature_test.go +54 -0
- package/project/.sdk/tm/go/utility/fetcher.go +41 -20
- package/project/.sdk/tm/go/utility/prepare_query.go +1 -1
- package/project/.sdk/tm/go/utility/transform_request.go +22 -3
- package/project/.sdk/tm/java/core/Context.java +2 -1
- package/project/.sdk/tm/java/feature/PagingFeature.java +46 -4
- package/project/.sdk/tm/java/feature/TestFeature.java +21 -19
- package/project/.sdk/tm/java/test/FeatureCorpusTest.java +3 -0
- package/project/.sdk/tm/java/test/FeatureTest.java +42 -0
- package/project/.sdk/tm/java/utility/Fetcher.java +36 -28
- package/project/.sdk/tm/java/utility/PrepareQuery.java +1 -1
- package/project/.sdk/tm/java/utility/TransformRequest.java +18 -3
- package/project/.sdk/tm/js/src/Context.js +7 -2
- package/project/.sdk/tm/js/src/feature/paging/PagingFeature.js +24 -6
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +7 -5
- package/project/.sdk/tm/js/src/utility/PrepareQueryUtility.js +1 -1
- package/project/.sdk/tm/js/test/feature/Corpus.test.js +4 -0
- package/project/.sdk/tm/js/test/live-entity.js +29 -29
- package/project/.sdk/tm/js/test/live-scenarios.js +4 -4
- package/project/.sdk/tm/kotlin/core/Context.kt +1 -1
- package/project/.sdk/tm/kotlin/feature/PagingFeature.kt +36 -4
- package/project/.sdk/tm/kotlin/feature/TestFeature.kt +19 -18
- package/project/.sdk/tm/kotlin/utility/Fetcher.kt +33 -24
- package/project/.sdk/tm/kotlin/utility/Prepare.kt +1 -1
- package/project/.sdk/tm/kotlin/utility/ResultTransform.kt +18 -3
- package/project/.sdk/tm/lua/core/context.lua +8 -1
- package/project/.sdk/tm/lua/core/control.lua +3 -0
- package/project/.sdk/tm/lua/feature/paging_feature.lua +44 -5
- package/project/.sdk/tm/lua/feature/test_feature.lua +32 -14
- package/project/.sdk/tm/lua/utility/prepare_query.lua +2 -1
- package/project/.sdk/tm/lua/utility/transform_request.lua +19 -3
- package/project/.sdk/tm/ocaml/sdk_features.ml +78 -25
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +23 -8
- package/project/.sdk/tm/perl/core/context.pm +2 -1
- package/project/.sdk/tm/perl/feature/paging_feature.pm +31 -5
- package/project/.sdk/tm/perl/feature/test_feature.pm +52 -20
- package/project/.sdk/tm/perl/feature/timeout_feature.pm +17 -13
- package/project/.sdk/tm/perl/t/feature_corpus.t +14 -1
- package/project/.sdk/tm/perl/utility/fetcher.pm +15 -1
- package/project/.sdk/tm/perl/utility/prepare_query.pm +1 -0
- package/project/.sdk/tm/perl/utility/transform_request.pm +13 -3
- package/project/.sdk/tm/php/core/Context.php +5 -1
- package/project/.sdk/tm/php/core/Control.php +5 -0
- package/project/.sdk/tm/php/feature/PagingFeature.php +26 -5
- package/project/.sdk/tm/php/feature/TestFeature.php +27 -42
- package/project/.sdk/tm/php/test/FeatureCorpusTest.php +17 -1
- package/project/.sdk/tm/php/test/FeatureTest.php +44 -0
- package/project/.sdk/tm/php/utility/Fetcher.php +17 -3
- package/project/.sdk/tm/php/utility/PrepareQuery.php +1 -1
- package/project/.sdk/tm/php/utility/TransformRequest.php +15 -3
- package/project/.sdk/tm/py/pkg/core/context.py +2 -1
- package/project/.sdk/tm/py/pkg/feature/paging_feature.py +29 -4
- package/project/.sdk/tm/py/pkg/feature/test_feature.py +29 -12
- package/project/.sdk/tm/py/pkg/utility/fetcher.py +63 -65
- package/project/.sdk/tm/py/pkg/utility/prepare_query.py +2 -1
- package/project/.sdk/tm/py/pkg/utility/transform_request.py +11 -3
- package/project/.sdk/tm/py/test/test_feature.py +27 -0
- package/project/.sdk/tm/py/test/test_feature_corpus.py +11 -1
- package/project/.sdk/tm/rb/core/context.rb +1 -1
- package/project/.sdk/tm/rb/feature/paging_feature.rb +27 -5
- package/project/.sdk/tm/rb/feature/test_feature.rb +39 -11
- package/project/.sdk/tm/rb/test/feature_corpus_test.rb +12 -1
- package/project/.sdk/tm/rb/test/feature_test.rb +38 -0
- package/project/.sdk/tm/rb/utility/fetcher.rb +49 -3
- package/project/.sdk/tm/rb/utility/prepare_query.rb +1 -1
- package/project/.sdk/tm/rb/utility/transform_request.rb +10 -3
- package/project/.sdk/tm/rust/core/context.rs +2 -6
- package/project/.sdk/tm/rust/feature/paging.rs +44 -3
- package/project/.sdk/tm/rust/feature/secrets.rs +1 -1
- package/project/.sdk/tm/rust/feature/test.rs +74 -37
- package/project/.sdk/tm/rust/utility/fetcher.rs +41 -14
- package/project/.sdk/tm/rust/utility/prepare_query.rs +1 -1
- package/project/.sdk/tm/rust/utility/transform_request.rs +31 -5
- package/project/.sdk/tm/scala/core/Context.scala +2 -1
- package/project/.sdk/tm/scala/feature/PagingFeature.scala +41 -4
- package/project/.sdk/tm/scala/feature/TestFeature.scala +21 -18
- package/project/.sdk/tm/scala/utility/Fetcher.scala +34 -13
- package/project/.sdk/tm/scala/utility/Prepare.scala +1 -1
- package/project/.sdk/tm/scala/utility/Transform.scala +19 -3
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +1 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/PagingFeature.swift +31 -4
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TestFeature.swift +22 -15
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Fetcher.swift +22 -3
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +1 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +14 -3
- package/project/.sdk/tm/ts/src/Context.ts +7 -2
- package/project/.sdk/tm/ts/src/feature/paging/PagingFeature.ts +19 -3
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +3 -0
- package/project/.sdk/tm/ts/src/utility/PrepareQueryUtility.ts +1 -1
- package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +1 -0
- package/project/.sdk/tm/ts/test/live-entity.ts +26 -26
- package/project/.sdk/tm/ts/test/live-scenarios.ts +3 -3
- package/project/.sdk/tm/zig/core/context.zig +1 -1
- package/project/.sdk/tm/zig/core/utility.zig +19 -5
- package/project/.sdk/tm/zig/feature/paging.zig +34 -4
- package/project/.sdk/tm/zig/feature/test.zig +65 -30
- package/project/sdkgen-package.json +1 -1
- package/src/action/doctor.ts +12 -9
- package/src/action/edition.ts +8 -0
- package/src/action/feature.ts +7 -1
- package/src/action/remove.ts +492 -0
- package/src/action/target.ts +8 -1
- package/src/cmp/ReadmeTop.ts +1 -1
- package/src/cmp/ReadmeUnions.ts +1 -1
- package/src/cmp/Test.ts +1 -1
- package/src/helpers/buildIdNames.ts +17 -7
- package/src/helpers/canonSpec.ts +2 -2
- package/src/helpers/getMatchEntries.ts +2 -2
- package/src/helpers/modelNames.ts +6 -1
- package/src/helpers/opShape.ts +33 -33
- package/src/helpers/pointPath.ts +5 -10
- package/src/helpers/resolved.ts +3 -14
- package/src/sdkgen.ts +3 -1
- package/src/utility.ts +16 -7
|
@@ -200,6 +200,13 @@ class FeatureCorpusTest < Minitest::Test
|
|
|
200
200
|
assert_equal expect, actual, path
|
|
201
201
|
end
|
|
202
202
|
|
|
203
|
+
# Whether the SDK built the feature at all. The activity record is the
|
|
204
|
+
# wrong probe: most features create theirs on first use, so an idle
|
|
205
|
+
# client has none and every section but the eager ones read as inert.
|
|
206
|
+
def present?(client, name)
|
|
207
|
+
(client.features || []).any? { |f| f.respond_to?(:name) && f.name == name }
|
|
208
|
+
end
|
|
209
|
+
|
|
203
210
|
def record(client, name)
|
|
204
211
|
# A corpus key is any manifest item name, so it may carry characters
|
|
205
212
|
# (foo-bar, foo.2) that cannot form a Ruby instance-variable name. The
|
|
@@ -246,7 +253,11 @@ class FeatureCorpusTest < Minitest::Test
|
|
|
246
253
|
# Probed by ACTIVATING it: the feature defaults to inactive, so an idle
|
|
247
254
|
# client never builds it and its absence says nothing.
|
|
248
255
|
probe = build_client({ "feature" => [{ "name" => name, "active" => true }] })
|
|
249
|
-
|
|
256
|
+
unless present?(probe, name)
|
|
257
|
+
# The one line every runner prints for an inert section.
|
|
258
|
+
puts "feature.#{name}: inert (this SDK does not generate the feature)"
|
|
259
|
+
next
|
|
260
|
+
end
|
|
250
261
|
|
|
251
262
|
ops = usable_ops(2)
|
|
252
263
|
by_key = ops.each_with_object({}) { |o, h| h[o["key"]] = o }
|
|
@@ -911,6 +911,44 @@ class FeatureTest < Minitest::Test
|
|
|
911
911
|
assert_equal true, res["result"].paging["hasMore"]
|
|
912
912
|
end
|
|
913
913
|
|
|
914
|
+
def test_paging_snake_case_signals_and_ctrl_write_back
|
|
915
|
+
skip_unless_feature("paging")
|
|
916
|
+
server, calls = H.recording_server { |n, _fd|
|
|
917
|
+
body = 1 == n ? { "has_more" => true, "next_cursor" => "c2" } : { "has_more" => false }
|
|
918
|
+
[H.make_response(200, body), nil]
|
|
919
|
+
}
|
|
920
|
+
h = harness([fspec("paging")], server: server)
|
|
921
|
+
pg = {}
|
|
922
|
+
ctrl = { "paging" => pg }
|
|
923
|
+
res = h.op(opname: "list", path: "/w", ctrl: ctrl)
|
|
924
|
+
assert_equal true, res["result"].paging["hasMore"]
|
|
925
|
+
assert_equal "c2", res["result"].paging["cursor"]
|
|
926
|
+
assert_equal "c2", pg["cursor"], "record written back into ctrl"
|
|
927
|
+
assert_equal true, pg["hasMore"]
|
|
928
|
+
h.op(opname: "list", path: "/w", ctrl: ctrl)
|
|
929
|
+
assert_match(/[?&]cursor=c2(&|\z)/, calls[1]["url"])
|
|
930
|
+
assert_equal false, pg["hasMore"]
|
|
931
|
+
assert_nil pg["cursor"]
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
def test_paging_continues_from_written_back_next_page
|
|
935
|
+
skip_unless_feature("paging")
|
|
936
|
+
server, calls = H.recording_server { |n, _fd|
|
|
937
|
+
body = 1 == n ? { "next_page" => 2 } : {}
|
|
938
|
+
[H.make_response(200, body, "x-page" => n.to_s), nil]
|
|
939
|
+
}
|
|
940
|
+
h = harness([fspec("paging")], server: server)
|
|
941
|
+
pg = {}
|
|
942
|
+
ctrl = { "paging" => pg }
|
|
943
|
+
h.op(opname: "list", path: "/w", ctrl: ctrl)
|
|
944
|
+
assert_equal 1, pg["page"]
|
|
945
|
+
assert_equal 2, pg["nextPage"]
|
|
946
|
+
assert_equal true, pg["hasMore"]
|
|
947
|
+
h.op(opname: "list", path: "/w", ctrl: ctrl)
|
|
948
|
+
assert_match(/[?&]page=2(&|\z)/, calls[1]["url"])
|
|
949
|
+
assert_equal false, pg["hasMore"]
|
|
950
|
+
end
|
|
951
|
+
|
|
914
952
|
def test_paging_non_list_op_is_not_paged
|
|
915
953
|
skip_unless_feature("paging")
|
|
916
954
|
server, calls = H.recording_server
|
|
@@ -5,6 +5,42 @@ require 'uri'
|
|
|
5
5
|
require 'json'
|
|
6
6
|
|
|
7
7
|
module ProjectNameUtilities
|
|
8
|
+
# Started Net::HTTP connections keyed by scheme, host, port and proxy,
|
|
9
|
+
# checked out for one request and returned. A Net::HTTP serves one
|
|
10
|
+
# request at a time, so the pool holds idle ones rather than sharing one.
|
|
11
|
+
HTTP_POOL = Hash.new { |h, k| h[k] = [] }
|
|
12
|
+
HTTP_POOL_LOCK = Mutex.new
|
|
13
|
+
HTTP_POOL_IDLE_MAX = 4
|
|
14
|
+
|
|
15
|
+
def self.http_checkout(key, uri, proxy)
|
|
16
|
+
http = HTTP_POOL_LOCK.synchronize { HTTP_POOL[key].pop }
|
|
17
|
+
return http if http && http.started?
|
|
18
|
+
|
|
19
|
+
if proxy
|
|
20
|
+
purl = URI.parse(proxy)
|
|
21
|
+
http = Net::HTTP.new(uri.host, uri.port, purl.host, purl.port, purl.user, purl.password)
|
|
22
|
+
else
|
|
23
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
24
|
+
end
|
|
25
|
+
http.use_ssl = (uri.scheme == "https")
|
|
26
|
+
http.start
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.http_checkin(key, http)
|
|
30
|
+
kept = HTTP_POOL_LOCK.synchronize do
|
|
31
|
+
HTTP_POOL[key].size < HTTP_POOL_IDLE_MAX && HTTP_POOL[key].push(http)
|
|
32
|
+
end
|
|
33
|
+
http.finish unless kept
|
|
34
|
+
rescue IOError
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.http_discard(http)
|
|
39
|
+
http.finish if http.started?
|
|
40
|
+
rescue IOError
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
8
44
|
DefaultHttpFetch = ->(fullurl, fetchdef) {
|
|
9
45
|
method_str = fetchdef["method"] || "GET"
|
|
10
46
|
body_str = fetchdef["body"]
|
|
@@ -12,8 +48,9 @@ module ProjectNameUtilities
|
|
|
12
48
|
|
|
13
49
|
begin
|
|
14
50
|
uri = URI.parse(fullurl)
|
|
15
|
-
|
|
16
|
-
|
|
51
|
+
proxy = fetchdef["proxy"]
|
|
52
|
+
proxy = nil unless proxy.is_a?(String) && !proxy.empty?
|
|
53
|
+
key = [uri.scheme, uri.host, uri.port, proxy]
|
|
17
54
|
|
|
18
55
|
klass = case method_str.upcase
|
|
19
56
|
when "POST" then Net::HTTP::Post
|
|
@@ -35,7 +72,16 @@ module ProjectNameUtilities
|
|
|
35
72
|
request['User-Agent'] = 'Mozilla/5.0 (compatible; ProjectNameSDK/1.0)' unless has_ua
|
|
36
73
|
request.body = body_str if body_str.is_a?(String)
|
|
37
74
|
|
|
38
|
-
|
|
75
|
+
http = ProjectNameUtilities.http_checkout(key, uri, proxy)
|
|
76
|
+
begin
|
|
77
|
+
# Net::HTTP retries idempotent requests; an EOF can follow a committed POST.
|
|
78
|
+
resp = http.request(request)
|
|
79
|
+
rescue StandardError
|
|
80
|
+
ProjectNameUtilities.http_discard(http)
|
|
81
|
+
raise
|
|
82
|
+
end
|
|
83
|
+
ProjectNameUtilities.http_checkin(key, http)
|
|
84
|
+
|
|
39
85
|
resp_headers = {}
|
|
40
86
|
resp.each_header { |k, v| resp_headers[k.downcase] = v }
|
|
41
87
|
|
|
@@ -14,7 +14,7 @@ module ProjectNameUtilities
|
|
|
14
14
|
if items
|
|
15
15
|
items.each do |item|
|
|
16
16
|
key, val = item[0], item[1]
|
|
17
|
-
out[key] = val if val && key.is_a?(String) && !params.include?(key)
|
|
17
|
+
out[key] = val if val && key.is_a?(String) && key != "$action" && !params.include?(key)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
out
|
|
@@ -2,14 +2,21 @@
|
|
|
2
2
|
require_relative 'struct/voxgig_struct'
|
|
3
3
|
require_relative '../core/helpers'
|
|
4
4
|
module ProjectNameUtilities
|
|
5
|
+
# `$action` selects the point (see MakePoint); it is never an API field, so
|
|
6
|
+
# the body is a copy without it. The caller's hash is left untouched.
|
|
7
|
+
def self.strip_action(reqdata)
|
|
8
|
+
return reqdata unless reqdata.is_a?(Hash) && reqdata.key?("$action")
|
|
9
|
+
reqdata.reject { |k, _| k == "$action" }
|
|
10
|
+
end
|
|
11
|
+
|
|
5
12
|
TransformRequest = ->(ctx) {
|
|
6
13
|
spec = ctx.spec
|
|
7
14
|
point = ctx.point
|
|
8
15
|
spec.step = "reqform" if spec
|
|
9
16
|
transform = ProjectNameHelpers.to_map(VoxgigStruct.getprop(point, "transform"))
|
|
10
|
-
return ctx.reqdata unless transform
|
|
17
|
+
return ProjectNameUtilities.strip_action(ctx.reqdata) unless transform
|
|
11
18
|
reqform = VoxgigStruct.getprop(transform, "req")
|
|
12
|
-
return ctx.reqdata unless reqform
|
|
13
|
-
VoxgigStruct.transform({ "reqdata" => ctx.reqdata }, reqform)
|
|
19
|
+
return ProjectNameUtilities.strip_action(ctx.reqdata) unless reqform
|
|
20
|
+
ProjectNameUtilities.strip_action(VoxgigStruct.transform({ "reqdata" => ctx.reqdata }, reqform))
|
|
14
21
|
}
|
|
15
22
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
use std::cell::RefCell;
|
|
3
2
|
use std::collections::HashMap;
|
|
4
3
|
use std::rc::Rc;
|
|
@@ -101,7 +100,7 @@ impl Context {
|
|
|
101
100
|
Rc::new(RefCell::new(c))
|
|
102
101
|
} else if let Some(co) = ctxspec.ctrl_obj {
|
|
103
102
|
co
|
|
104
|
-
} else if let Some(b) = basectx {
|
|
103
|
+
} else if let Some(b) = basectx.filter(|_| ctxspec.opname.is_none()) {
|
|
105
104
|
b.ctrl.borrow().clone()
|
|
106
105
|
} else {
|
|
107
106
|
Rc::new(RefCell::new(Control::new()))
|
|
@@ -249,10 +248,7 @@ impl Context {
|
|
|
249
248
|
return Rc::new(Operation::new(&Value::empty_map()));
|
|
250
249
|
}
|
|
251
250
|
|
|
252
|
-
let opcfg = getpath(
|
|
253
|
-
&["entity", &entname, "op", opname],
|
|
254
|
-
&self.config.borrow(),
|
|
255
|
-
);
|
|
251
|
+
let opcfg = getpath(&["entity", &entname, "op", opname], &self.config.borrow());
|
|
256
252
|
|
|
257
253
|
let input = if opname == "update" || opname == "create" {
|
|
258
254
|
"data"
|
|
@@ -7,6 +7,7 @@ use crate::core::spec::Spec;
|
|
|
7
7
|
use crate::core::helpers::{get_bool, getp, getpath, setp};
|
|
8
8
|
use crate::core::types::Feature;
|
|
9
9
|
use crate::feature::support::*;
|
|
10
|
+
use crate::utility::voxgigstruct::ordered_map::OrderedMap;
|
|
10
11
|
use crate::utility::voxgigstruct::Value;
|
|
11
12
|
|
|
12
13
|
pub struct PagingFeature {
|
|
@@ -193,7 +194,12 @@ impl Feature for PagingFeature {
|
|
|
193
194
|
if !cursor.is_noval() && !cursor.is_null() {
|
|
194
195
|
setp(&query, &cursor_param, cursor);
|
|
195
196
|
} else if getp(&query, &page_param).is_noval() {
|
|
196
|
-
|
|
197
|
+
// A record written back by pre_result holds the page just fetched
|
|
198
|
+
// as "page" and the one to fetch as "nextPage", so nextPage wins.
|
|
199
|
+
let mut page = getp(&paging, "nextPage");
|
|
200
|
+
if page.is_noval() || page.is_null() {
|
|
201
|
+
page = getp(&paging, "page");
|
|
202
|
+
}
|
|
197
203
|
if !page.is_noval() && !page.is_null() {
|
|
198
204
|
setp(&query, &page_param, page);
|
|
199
205
|
} else {
|
|
@@ -281,12 +287,16 @@ impl Feature for PagingFeature {
|
|
|
281
287
|
}
|
|
282
288
|
}
|
|
283
289
|
|
|
284
|
-
// Body-level
|
|
290
|
+
// Body-level signals; snake_case forms are read first so camelCase wins.
|
|
285
291
|
if let Value::Map(_) = body {
|
|
286
292
|
let next = getp(&body, "next");
|
|
287
293
|
if !next.is_noval() && !next.is_null() && getp(&paging, "next").is_noval() {
|
|
288
294
|
setp(&paging, "next", next);
|
|
289
295
|
}
|
|
296
|
+
let snake_cursor = getp(&body, "next_cursor");
|
|
297
|
+
if !snake_cursor.is_noval() && !snake_cursor.is_null() {
|
|
298
|
+
setp(&paging, "cursor", snake_cursor);
|
|
299
|
+
}
|
|
290
300
|
let cursor = getp(&body, "cursor");
|
|
291
301
|
if !cursor.is_noval() && !cursor.is_null() {
|
|
292
302
|
setp(&paging, "cursor", cursor);
|
|
@@ -295,6 +305,19 @@ impl Feature for PagingFeature {
|
|
|
295
305
|
if !next_cursor.is_noval() && !next_cursor.is_null() {
|
|
296
306
|
setp(&paging, "cursor", next_cursor);
|
|
297
307
|
}
|
|
308
|
+
if getp(&paging, "nextPage").is_noval() {
|
|
309
|
+
let mut np = getp(&body, "nextPage");
|
|
310
|
+
if np.is_noval() || np.is_null() {
|
|
311
|
+
np = getp(&body, "next_page");
|
|
312
|
+
}
|
|
313
|
+
if matches!(np, Value::Num(_) | Value::Str(_)) {
|
|
314
|
+
setp(&paging, "nextPage", np);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if let Some(has_more) = get_bool(&body, "has_more") {
|
|
318
|
+
setp(&paging, "hasMore", Value::Bool(has_more));
|
|
319
|
+
explicit_more = true;
|
|
320
|
+
}
|
|
298
321
|
if let Some(has_more) = get_bool(&body, "hasMore") {
|
|
299
322
|
setp(&paging, "hasMore", Value::Bool(has_more));
|
|
300
323
|
explicit_more = true;
|
|
@@ -316,6 +339,24 @@ impl Feature for PagingFeature {
|
|
|
316
339
|
}
|
|
317
340
|
|
|
318
341
|
result.borrow_mut().paging = paging.clone();
|
|
319
|
-
self.last = paging;
|
|
342
|
+
self.last = paging.clone();
|
|
343
|
+
|
|
344
|
+
// Value::Map is Rc-shared, so the caller's map is refilled in place;
|
|
345
|
+
// a fresh map on ctrl never reaches the caller.
|
|
346
|
+
let ctrl = ctx.ctrl.borrow().clone();
|
|
347
|
+
let shared = ctrl.borrow().paging.clone();
|
|
348
|
+
if let Value::Map(m) = &shared {
|
|
349
|
+
let entries: Vec<(String, Value)> = match &paging {
|
|
350
|
+
Value::Map(pm) => pm.borrow().iter().map(|(k, v)| (k.clone(), v.clone())).collect(),
|
|
351
|
+
_ => Vec::new(),
|
|
352
|
+
};
|
|
353
|
+
let mut mm = m.borrow_mut();
|
|
354
|
+
*mm = OrderedMap::new();
|
|
355
|
+
for (k, v) in entries {
|
|
356
|
+
mm.insert(k, v);
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
ctrl.borrow_mut().paging = paging;
|
|
360
|
+
}
|
|
320
361
|
}
|
|
321
362
|
}
|
|
@@ -754,7 +754,7 @@ fn raw_exchange_fetch(fullurl: &str, fetchdef: &Value) -> Result<Value, ProjectN
|
|
|
754
754
|
.filter(|m| !m.is_empty())
|
|
755
755
|
.unwrap_or_else(|| "POST".to_string());
|
|
756
756
|
|
|
757
|
-
let agent =
|
|
757
|
+
let agent = crate::utility::fetcher::default_agent();
|
|
758
758
|
let mut req = agent.request(&method, fullurl);
|
|
759
759
|
|
|
760
760
|
if let Value::Map(m) = getp(fetchdef, "headers") {
|
|
@@ -34,11 +34,15 @@ fn envelope(ctx: &Rc<Context>, data: Value) -> Value {
|
|
|
34
34
|
}
|
|
35
35
|
let restf = crate::core::helpers::getpath(&["transform", "res"], &ctx.point.borrow());
|
|
36
36
|
if let Value::Str(spec) = restf {
|
|
37
|
-
//
|
|
38
|
-
//
|
|
37
|
+
// Rebuild whatever nesting the transform unwraps: a GraphQL op unwraps
|
|
38
|
+
// `body.data.<field>`, not just one envelope property.
|
|
39
39
|
if let Some(inner) = spec.strip_prefix("`body.").and_then(|r| r.strip_suffix('`')) {
|
|
40
|
-
if !inner.is_empty()
|
|
41
|
-
|
|
40
|
+
if !inner.is_empty() {
|
|
41
|
+
let mut out = data;
|
|
42
|
+
for seg in inner.split('.').rev() {
|
|
43
|
+
out = jo(vec![(seg, out)]);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -76,6 +80,61 @@ fn resolve_match(ctx: &Rc<Context>, explicit: &Value) -> Value {
|
|
|
76
80
|
Value::empty_map()
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
fn point_terminal(p: &Value) -> bool {
|
|
84
|
+
match getp(p, "parts") {
|
|
85
|
+
Value::List(l) => match l.borrow().last() {
|
|
86
|
+
Some(Value::Str(s)) => s.starts_with('{'),
|
|
87
|
+
_ => false,
|
|
88
|
+
},
|
|
89
|
+
_ => false,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fn point_depth(p: &Value) -> usize {
|
|
94
|
+
match getp(p, "parts") {
|
|
95
|
+
Value::List(l) => l.borrow().len(),
|
|
96
|
+
_ => 0,
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The entity's own endpoint: a terminal `{param}` marks a record route, and
|
|
101
|
+
// among equals the shallower path wins (the same rule as make_point).
|
|
102
|
+
fn pick_point(points: &Value) -> Value {
|
|
103
|
+
let list: Vec<Value> = match points {
|
|
104
|
+
Value::List(l) => l.borrow().clone(),
|
|
105
|
+
_ => return Value::Noval,
|
|
106
|
+
};
|
|
107
|
+
let mut point = match list.first() {
|
|
108
|
+
Some(p) => p.clone(),
|
|
109
|
+
None => return Value::Noval,
|
|
110
|
+
};
|
|
111
|
+
for cand in list.iter().skip(1) {
|
|
112
|
+
if point_terminal(cand) != point_terminal(&point) {
|
|
113
|
+
if point_terminal(cand) {
|
|
114
|
+
point = cand.clone();
|
|
115
|
+
}
|
|
116
|
+
} else if point_depth(cand) < point_depth(&point) {
|
|
117
|
+
point = cand.clone();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
point
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fn reqd_names(point: &Value, kind: &str) -> Value {
|
|
124
|
+
let args_path = crate::core::helpers::getpath(&["args", kind], point);
|
|
125
|
+
let reqd_args = vs::select(&args_path, &jo(vec![("reqd", Value::Bool(true))]));
|
|
126
|
+
vs::transform(
|
|
127
|
+
&reqd_args,
|
|
128
|
+
&ja(vec![
|
|
129
|
+
Value::str("`$EACH`"),
|
|
130
|
+
Value::str(""),
|
|
131
|
+
Value::str("`$KEY.name`"),
|
|
132
|
+
]),
|
|
133
|
+
None,
|
|
134
|
+
)
|
|
135
|
+
.unwrap_or_else(|_| Value::empty_list())
|
|
136
|
+
}
|
|
137
|
+
|
|
79
138
|
fn build_args(ctx: &Rc<Context>, args: &Value) -> Value {
|
|
80
139
|
let op = ctx.op.borrow().clone();
|
|
81
140
|
let opname = op.name.clone();
|
|
@@ -84,26 +143,16 @@ fn build_args(ctx: &Rc<Context>, args: &Value) -> Value {
|
|
|
84
143
|
None => op.entity.clone(),
|
|
85
144
|
};
|
|
86
145
|
|
|
87
|
-
// Get last point from config.
|
|
88
146
|
let points = crate::core::helpers::getpath(
|
|
89
147
|
&["entity", &entname, "op", &opname, "points"],
|
|
90
148
|
&ctx.config.borrow(),
|
|
91
149
|
);
|
|
92
|
-
let point =
|
|
150
|
+
let point = pick_point(&points);
|
|
93
151
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
let reqd_params =
|
|
97
|
-
let
|
|
98
|
-
&reqd_params,
|
|
99
|
-
&ja(vec![
|
|
100
|
-
Value::str("`$EACH`"),
|
|
101
|
-
Value::str(""),
|
|
102
|
-
Value::str("`$KEY.name`"),
|
|
103
|
-
]),
|
|
104
|
-
None,
|
|
105
|
-
)
|
|
106
|
-
.unwrap_or_else(|_| Value::empty_list());
|
|
152
|
+
// Path AND query: a path-only read misses a query-addressed record
|
|
153
|
+
// (e.g. GET /result?trace_id=), which has no path param at all.
|
|
154
|
+
let reqd_params = reqd_names(&point, "params");
|
|
155
|
+
let reqd_query = reqd_names(&point, "query");
|
|
107
156
|
|
|
108
157
|
let qand = Value::empty_list();
|
|
109
158
|
let q = jo(vec![("`$AND`", qand.clone())]);
|
|
@@ -112,8 +161,8 @@ fn build_args(ctx: &Rc<Context>, args: &Value) -> Value {
|
|
|
112
161
|
let keys = vs::keysof_vec(args);
|
|
113
162
|
for key in keys {
|
|
114
163
|
let is_id = key == "id";
|
|
115
|
-
let
|
|
116
|
-
|
|
164
|
+
let is_reqd = !vs::is_empty(&vs::select(&reqd_params, &Value::str(key.clone())))
|
|
165
|
+
|| !vs::is_empty(&vs::select(&reqd_query, &Value::str(key.clone())));
|
|
117
166
|
|
|
118
167
|
if is_id || is_reqd {
|
|
119
168
|
let v = ctx.util().param(ctx, &Value::str(key.clone()));
|
|
@@ -211,28 +260,16 @@ fn test_fetch(
|
|
|
211
260
|
};
|
|
212
261
|
let args = build_args(ctx, &update_match);
|
|
213
262
|
let found = vs::select(&entmap, &args);
|
|
214
|
-
let
|
|
215
|
-
if (ent.is_noval() || ent.is_null()) && vs::size(&entmap) > 0 {
|
|
216
|
-
// Fall back to any entity in the fixture.
|
|
217
|
-
for (_k, e) in vs::items_vec(&entmap) {
|
|
218
|
-
if let Value::Map(_) = e {
|
|
219
|
-
ent = e;
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
263
|
+
let ent = vs::get_elem(&found, &Value::Num(0.0), Value::Noval);
|
|
224
264
|
if ent.is_noval() || ent.is_null() {
|
|
265
|
+
// update miss: 404, never another record
|
|
225
266
|
return Ok(respond(ctx, 404,
|
|
226
267
|
Value::Noval,
|
|
227
268
|
vec![("statusText", Value::str("Not found"))],
|
|
228
269
|
));
|
|
229
270
|
}
|
|
230
|
-
if let Value::Map(_) = &ent {
|
|
231
|
-
|
|
232
|
-
for (k, v) in rm.borrow().iter() {
|
|
233
|
-
setp(&ent, k, v.clone());
|
|
234
|
-
}
|
|
235
|
-
}
|
|
271
|
+
if let (Value::Map(_), Value::Map(_)) = (&ent, &reqdata) {
|
|
272
|
+
vs::merge(&Value::list(vec![ent.clone(), reqdata.clone()]), None);
|
|
236
273
|
}
|
|
237
274
|
vs::del_prop(ent.clone(), &Value::str("$KEY"));
|
|
238
275
|
Ok(respond(ctx, 200, vs::clone(&ent), vec![]))
|
|
@@ -1,29 +1,56 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
1
2
|
use std::rc::Rc;
|
|
3
|
+
use std::sync::{Mutex, OnceLock};
|
|
2
4
|
|
|
3
5
|
use crate::core::context::Context;
|
|
4
6
|
use crate::core::error::ProjectNameError;
|
|
5
7
|
use crate::core::helpers::{call_vfn, get_str, getp, getpath, ja, jo, json_thunk, setp};
|
|
6
8
|
use crate::utility::voxgigstruct::Value;
|
|
7
9
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
10
|
+
// One agent per process: ureq pools keep-alive connections per agent, so
|
|
11
|
+
// an agent per request reused nothing. Cloning shares the pool.
|
|
12
|
+
pub(crate) fn default_agent() -> ureq::Agent {
|
|
13
|
+
static AGENT: OnceLock<ureq::Agent> = OnceLock::new();
|
|
14
|
+
AGENT.get_or_init(|| ureq::AgentBuilder::new().build()).clone()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Agents keyed by the `proxy` annotation (set by the proxy feature) and
|
|
18
|
+
// manual redirects, for requests the default agent cannot serve.
|
|
19
|
+
fn agent_for(fetchdef: &Value) -> ureq::Agent {
|
|
20
|
+
let proxy = get_str(fetchdef, "proxy").filter(|p| !p.is_empty());
|
|
21
|
+
let manual = get_str(fetchdef, "redirect").as_deref() == Some("manual");
|
|
22
|
+
if proxy.is_none() && !manual {
|
|
23
|
+
return default_agent();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static AGENTS: OnceLock<Mutex<HashMap<(Option<String>, bool), ureq::Agent>>> =
|
|
27
|
+
OnceLock::new();
|
|
28
|
+
let mut agents = AGENTS
|
|
29
|
+
.get_or_init(|| Mutex::new(HashMap::new()))
|
|
30
|
+
.lock()
|
|
31
|
+
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
|
32
|
+
agents
|
|
33
|
+
.entry((proxy.clone(), manual))
|
|
34
|
+
.or_insert_with(|| {
|
|
35
|
+
let mut builder = ureq::AgentBuilder::new();
|
|
36
|
+
if let Some(p) = proxy.as_deref().and_then(|p| ureq::Proxy::new(p).ok()) {
|
|
37
|
+
builder = builder.proxy(p);
|
|
38
|
+
}
|
|
39
|
+
if manual {
|
|
40
|
+
builder = builder.redirects(0);
|
|
41
|
+
}
|
|
42
|
+
builder.build()
|
|
43
|
+
})
|
|
44
|
+
.clone()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Default live transport: ureq (blocking, minimal).
|
|
11
48
|
fn default_http_fetch(fullurl: &str, fetchdef: &Value) -> Result<Value, ProjectNameError> {
|
|
12
49
|
let method = get_str(fetchdef, "method")
|
|
13
50
|
.filter(|m| !m.is_empty())
|
|
14
51
|
.unwrap_or_else(|| "GET".to_string());
|
|
15
52
|
|
|
16
|
-
let
|
|
17
|
-
if let Some(proxy) = get_str(fetchdef, "proxy").filter(|p| !p.is_empty()) {
|
|
18
|
-
if let Ok(p) = ureq::Proxy::new(&proxy) {
|
|
19
|
-
builder = builder.proxy(p);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
if get_str(fetchdef, "redirect").as_deref() == Some("manual") {
|
|
23
|
-
builder = builder.redirects(0);
|
|
24
|
-
}
|
|
25
|
-
let agent = builder.build();
|
|
26
|
-
|
|
53
|
+
let agent = agent_for(fetchdef);
|
|
27
54
|
let mut req = agent.request(&method, fullurl);
|
|
28
55
|
|
|
29
56
|
let mut has_ua = false;
|
|
@@ -37,7 +37,7 @@ pub fn prepare_query_util(ctx: &Rc<Context>) -> Value {
|
|
|
37
37
|
.map(|(k, v)| (k.clone(), v.clone()))
|
|
38
38
|
.collect();
|
|
39
39
|
for (key, val) in entries {
|
|
40
|
-
if !val.is_noval() && !val.is_null() && !contains(&key) {
|
|
40
|
+
if !val.is_noval() && !val.is_null() && "$action" != key && !contains(&key) {
|
|
41
41
|
setp(&out, &key, val);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
use std::rc::Rc;
|
|
2
2
|
|
|
3
3
|
use crate::core::context::Context;
|
|
4
|
-
use crate::core::helpers::{getp, jo, to_map};
|
|
4
|
+
use crate::core::helpers::{getp, jo, setp, to_map};
|
|
5
5
|
use crate::utility::voxgigstruct as vs;
|
|
6
6
|
use crate::utility::voxgigstruct::Value;
|
|
7
7
|
|
|
8
|
+
// `$action` selects the point (see make_point_util); it is never an API
|
|
9
|
+
// field, so the body is a copy without it. The caller's map is left untouched.
|
|
10
|
+
fn strip_action(reqdata: Value) -> Value {
|
|
11
|
+
let has = match &reqdata {
|
|
12
|
+
Value::Map(src) => src.borrow().contains_key("$action"),
|
|
13
|
+
_ => false,
|
|
14
|
+
};
|
|
15
|
+
if !has {
|
|
16
|
+
return reqdata;
|
|
17
|
+
}
|
|
18
|
+
let body = Value::empty_map();
|
|
19
|
+
if let Value::Map(src) = &reqdata {
|
|
20
|
+
let entries: Vec<(String, Value)> = src
|
|
21
|
+
.borrow()
|
|
22
|
+
.iter()
|
|
23
|
+
.map(|(k, v)| (k.clone(), v.clone()))
|
|
24
|
+
.collect();
|
|
25
|
+
for (k, v) in entries {
|
|
26
|
+
if "$action" != k {
|
|
27
|
+
setp(&body, &k, v);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
body
|
|
32
|
+
}
|
|
33
|
+
|
|
8
34
|
pub fn transform_request_util(ctx: &Rc<Context>) -> Value {
|
|
9
35
|
let spec = ctx.spec.borrow().clone();
|
|
10
36
|
let point = ctx.point.borrow().clone();
|
|
@@ -15,17 +41,17 @@ pub fn transform_request_util(ctx: &Rc<Context>) -> Value {
|
|
|
15
41
|
|
|
16
42
|
let transform = to_map(&getp(&point, "transform"));
|
|
17
43
|
if transform.is_noval() {
|
|
18
|
-
return ctx.reqdata.borrow().clone();
|
|
44
|
+
return strip_action(ctx.reqdata.borrow().clone());
|
|
19
45
|
}
|
|
20
46
|
|
|
21
47
|
let reqform = getp(&transform, "req");
|
|
22
48
|
if reqform.is_noval() || reqform.is_null() {
|
|
23
|
-
return ctx.reqdata.borrow().clone();
|
|
49
|
+
return strip_action(ctx.reqdata.borrow().clone());
|
|
24
50
|
}
|
|
25
51
|
|
|
26
52
|
let store = jo(vec![("reqdata", ctx.reqdata.borrow().clone())]);
|
|
27
|
-
match vs::transform(&store, &reqform, None) {
|
|
53
|
+
strip_action(match vs::transform(&store, &reqform, None) {
|
|
28
54
|
Ok(reqdata) => reqdata,
|
|
29
55
|
Err(_) => ctx.reqdata.borrow().clone(),
|
|
30
|
-
}
|
|
56
|
+
})
|
|
31
57
|
}
|
|
@@ -51,7 +51,8 @@ class Context(ctxmap: JMap[String, Object], basectx: Context) {
|
|
|
51
51
|
case c: Control => ctrl = c
|
|
52
52
|
case _ =>
|
|
53
53
|
}
|
|
54
|
-
} else if (basectx != null && basectx.ctrl != null
|
|
54
|
+
} else if (basectx != null && basectx.ctrl != null
|
|
55
|
+
&& Helpers.getCtxProp(ctxmap, "opname") == null) {
|
|
55
56
|
ctrl = basectx.ctrl
|
|
56
57
|
}
|
|
57
58
|
|