@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
|
@@ -9,8 +9,8 @@ import SCALAPACKAGE.utility.struct.Struct
|
|
|
9
9
|
// stamps page/limit (or a cursor) into the request query; on the way back
|
|
10
10
|
// (PreResult) it reads the server's pagination signals — a `Link:
|
|
11
11
|
// rel="next"` header, `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
|
|
12
|
-
// `next`/`cursor`/`nextCursor`/`hasMore` fields in the body
|
|
13
|
-
// them on `ctx.result.paging`. A per-call cursor/page from ctrl takes
|
|
12
|
+
// `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case
|
|
13
|
+
// forms too) — and records them on `ctx.result.paging` and `ctrl.paging`. A per-call cursor/page from ctrl takes
|
|
14
14
|
// priority (used by auto-iteration). Parameter names (`pageParam`,
|
|
15
15
|
// `limitParam`, `cursorParam`), the page size (`limit`) and the start page
|
|
16
16
|
// (`startPage`, default 1) are configurable.
|
|
@@ -65,7 +65,10 @@ class PagingFeature extends BaseFeature("paging", "0.0.1", true) {
|
|
|
65
65
|
if (cursor != null) {
|
|
66
66
|
spec.query.put(cursorParam, cursor)
|
|
67
67
|
} else if (spec.query.get(pageParam) == null) {
|
|
68
|
-
|
|
68
|
+
// A record written back by preResult holds the page just fetched as
|
|
69
|
+
// "page" and the one to fetch as "nextPage", so nextPage wins.
|
|
70
|
+
var page = paging.get("nextPage")
|
|
71
|
+
if (page == null) page = paging.get("page")
|
|
69
72
|
if (page != null) {
|
|
70
73
|
spec.query.put(pageParam, page)
|
|
71
74
|
} else {
|
|
@@ -192,19 +195,37 @@ class PagingFeature extends BaseFeature("paging", "0.0.1", true) {
|
|
|
192
195
|
case _ =>
|
|
193
196
|
}
|
|
194
197
|
|
|
195
|
-
// Body-level
|
|
198
|
+
// Body-level signals; snake_case forms are read first so camelCase wins.
|
|
196
199
|
body match {
|
|
197
200
|
case bm0: JMap[_, _] =>
|
|
198
201
|
val bm = bm0.asInstanceOf[JMap[String, Object]]
|
|
199
202
|
if (bm.get("next") != null && paging.get("next") == null) {
|
|
200
203
|
paging.put("next", bm.get("next"))
|
|
201
204
|
}
|
|
205
|
+
if (bm.get("next_cursor") != null) {
|
|
206
|
+
paging.put("cursor", bm.get("next_cursor"))
|
|
207
|
+
}
|
|
202
208
|
if (bm.get("cursor") != null) {
|
|
203
209
|
paging.put("cursor", bm.get("cursor"))
|
|
204
210
|
}
|
|
205
211
|
if (bm.get("nextCursor") != null) {
|
|
206
212
|
paging.put("cursor", bm.get("nextCursor"))
|
|
207
213
|
}
|
|
214
|
+
if (paging.get("nextPage") == null) {
|
|
215
|
+
var np = bm.get("nextPage")
|
|
216
|
+
if (np == null) np = bm.get("next_page")
|
|
217
|
+
np match {
|
|
218
|
+
case n: java.lang.Number => paging.put("nextPage", java.lang.Integer.valueOf(n.intValue()))
|
|
219
|
+
case s: String => paging.put("nextPage", s)
|
|
220
|
+
case _ =>
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
bm.get("has_more") match {
|
|
224
|
+
case b: java.lang.Boolean =>
|
|
225
|
+
paging.put("hasMore", b)
|
|
226
|
+
explicitMore = true
|
|
227
|
+
case _ =>
|
|
228
|
+
}
|
|
208
229
|
bm.get("hasMore") match {
|
|
209
230
|
case b: java.lang.Boolean =>
|
|
210
231
|
paging.put("hasMore", b)
|
|
@@ -227,6 +248,22 @@ class PagingFeature extends BaseFeature("paging", "0.0.1", true) {
|
|
|
227
248
|
|
|
228
249
|
result.paging = paging
|
|
229
250
|
this.last = paging
|
|
251
|
+
|
|
252
|
+
if (ctx.ctrl != null) {
|
|
253
|
+
// The Context shares the caller's paging map by reference, so refill
|
|
254
|
+
// it in place; an immutable map falls back to replacing the reference.
|
|
255
|
+
val shared = ctx.ctrl.paging
|
|
256
|
+
if (shared == null) {
|
|
257
|
+
ctx.ctrl.paging = paging
|
|
258
|
+
} else {
|
|
259
|
+
try {
|
|
260
|
+
shared.clear()
|
|
261
|
+
shared.putAll(paging)
|
|
262
|
+
} catch {
|
|
263
|
+
case _: UnsupportedOperationException => ctx.ctrl.paging = paging
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
230
267
|
}
|
|
231
268
|
|
|
232
269
|
private def isList(ctx: Context): Boolean = {
|
|
@@ -50,14 +50,18 @@ class TestFeature extends BaseFeature("test", "0.0.1", true) {
|
|
|
50
50
|
val tm = Struct.getprop(ctx.point, "transform")
|
|
51
51
|
Struct.getprop(tm, "res") match {
|
|
52
52
|
case spec: String =>
|
|
53
|
-
//
|
|
54
|
-
//
|
|
53
|
+
// Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
|
|
54
|
+
// GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
|
|
55
55
|
if (!spec.startsWith("`body.") || !spec.endsWith("`") || spec.length < 8) return data
|
|
56
56
|
val inner = spec.substring(6, spec.length - 1)
|
|
57
|
-
if (inner.isEmpty
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
if (inner.isEmpty) return data
|
|
58
|
+
var out: Object = data
|
|
59
|
+
for (seg <- inner.split("\\.", -1).reverse) {
|
|
60
|
+
val wrapped = new java.util.LinkedHashMap[String, Object]()
|
|
61
|
+
wrapped.put(seg, out)
|
|
62
|
+
out = wrapped
|
|
63
|
+
}
|
|
64
|
+
out
|
|
61
65
|
case _ => data
|
|
62
66
|
}
|
|
63
67
|
}
|
|
@@ -134,16 +138,10 @@ class TestFeature extends BaseFeature("test", "0.0.1", true) {
|
|
|
134
138
|
if (updateMatch.isEmpty) updateMatch = resolveMatch(ctx, new LinkedHashMap[String, Object]()).asInstanceOf[LinkedHashMap[String, Object]]
|
|
135
139
|
val args = buildArgs(ctx, op, updateMatch)
|
|
136
140
|
val found = Struct.select(entmap, args)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
val vit = entmap.values().iterator()
|
|
140
|
-
var brk = false
|
|
141
|
-
while (vit.hasNext && !brk) {
|
|
142
|
-
vit.next() match { case e: JMap[_, _] => ent = e; brk = true; case _ => }
|
|
143
|
-
}
|
|
144
|
-
}
|
|
141
|
+
val ent = Struct.getelem(found, java.lang.Integer.valueOf(0))
|
|
142
|
+
// update miss: 404, never another record
|
|
145
143
|
if (ent == null) return respond(ctx, 404, null, extra("statusText", "Not found"))
|
|
146
|
-
ent match { case
|
|
144
|
+
ent match { case _: JMap[_, _] if ctx.reqdata != null => Struct.merge(Struct.jt(ent, ctx.reqdata)); case _ => }
|
|
147
145
|
Struct.delprop(ent, "$KEY")
|
|
148
146
|
val out = Struct.clone(ent)
|
|
149
147
|
respond(ctx, 200, out, null)
|
|
@@ -277,9 +275,14 @@ class TestFeature extends BaseFeature("test", "0.0.1", true) {
|
|
|
277
275
|
case _ =>
|
|
278
276
|
}
|
|
279
277
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
val
|
|
278
|
+
// Path AND query: a path-only read misses a query-addressed record
|
|
279
|
+
// (e.g. GET /result?trace_id=), which has no path param at all.
|
|
280
|
+
val reqdArgs = Struct.jt()
|
|
281
|
+
for (kind <- List("params", "query")) {
|
|
282
|
+
val argsPath = Struct.getpath(point, java.util.List.of("args", kind))
|
|
283
|
+
reqdArgs.addAll(Struct.select(argsPath, Struct.jm("reqd", java.lang.Boolean.TRUE)))
|
|
284
|
+
}
|
|
285
|
+
val reqd = Struct.transform(reqdArgs, Struct.jt("`$EACH`", "", "`$KEY.name`"))
|
|
283
286
|
|
|
284
287
|
val qand = Struct.jt()
|
|
285
288
|
val q = Struct.jm("`$AND`", qand)
|
|
@@ -3,12 +3,44 @@ package SCALAPACKAGE.utility
|
|
|
3
3
|
import java.net.{InetSocketAddress, ProxySelector, URI}
|
|
4
4
|
import java.net.http.{HttpClient, HttpRequest, HttpResponse}
|
|
5
5
|
import java.util.{LinkedHashMap, List => JList, Map => JMap}
|
|
6
|
-
import java.util.
|
|
6
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
7
|
+
import java.util.function.{BiFunction, Function => JFunction, Supplier}
|
|
7
8
|
import SCALAPACKAGE.core._
|
|
8
9
|
import SCALAPACKAGE.utility.struct.Struct
|
|
9
10
|
|
|
10
11
|
object Fetcher {
|
|
11
12
|
|
|
13
|
+
// Clients keyed by redirect policy and proxy. Each HttpClient owns a
|
|
14
|
+
// connection pool and a selector thread, so one per request reused
|
|
15
|
+
// nothing; one per key pools across calls.
|
|
16
|
+
private val clients = new ConcurrentHashMap[String, HttpClient]()
|
|
17
|
+
|
|
18
|
+
private def clientFor(fetchdef: JMap[String, Object]): HttpClient = {
|
|
19
|
+
// "manual" (set by the station feature's middleware under a hosts
|
|
20
|
+
// policy) returns a 3xx like any other response: an automatic follow
|
|
21
|
+
// would carry injected credentials to a host no policy approved.
|
|
22
|
+
val redirectPolicy =
|
|
23
|
+
if ("manual" == fetchdef.get("redirect")) HttpClient.Redirect.NEVER
|
|
24
|
+
else HttpClient.Redirect.NORMAL
|
|
25
|
+
|
|
26
|
+
val proxy = fetchdef.get("proxy") match { case p: String => p; case _ => "" }
|
|
27
|
+
|
|
28
|
+
clients.computeIfAbsent(redirectPolicy.toString + "|" + proxy,
|
|
29
|
+
new JFunction[String, HttpClient] {
|
|
30
|
+
def apply(key: String): HttpClient = {
|
|
31
|
+
val clientb = HttpClient.newBuilder().followRedirects(redirectPolicy)
|
|
32
|
+
if (proxy != "") {
|
|
33
|
+
try {
|
|
34
|
+
val proxyUri = URI.create(proxy)
|
|
35
|
+
val port = if (proxyUri.getPort < 0) 80 else proxyUri.getPort
|
|
36
|
+
clientb.proxy(ProxySelector.of(new InetSocketAddress(proxyUri.getHost, port)))
|
|
37
|
+
} catch { case _: RuntimeException => }
|
|
38
|
+
}
|
|
39
|
+
clientb.build()
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
12
44
|
def defaultHttpFetch(fullurl: String, fetchdef: JMap[String, Object]): JMap[String, Object] = {
|
|
13
45
|
var method = fetchdef.get("method") match { case s: String => s; case _ => "" }
|
|
14
46
|
if ("" == method) method = "GET"
|
|
@@ -40,19 +72,8 @@ object Fetcher {
|
|
|
40
72
|
}
|
|
41
73
|
if (!hasUA) reqb.setHeader("User-Agent", "Mozilla/5.0 (compatible; ProjectNameSDK/1.0)")
|
|
42
74
|
|
|
43
|
-
val clientb = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL)
|
|
44
|
-
fetchdef.get("proxy") match {
|
|
45
|
-
case proxy: String if proxy != "" =>
|
|
46
|
-
try {
|
|
47
|
-
val proxyUri = URI.create(proxy)
|
|
48
|
-
val port = if (proxyUri.getPort < 0) 80 else proxyUri.getPort
|
|
49
|
-
clientb.proxy(ProxySelector.of(new InetSocketAddress(proxyUri.getHost, port)))
|
|
50
|
-
} catch { case _: RuntimeException => }
|
|
51
|
-
case _ =>
|
|
52
|
-
}
|
|
53
|
-
|
|
54
75
|
val resp =
|
|
55
|
-
try
|
|
76
|
+
try clientFor(fetchdef).send(reqb.build(), HttpResponse.BodyHandlers.ofString())
|
|
56
77
|
catch { case e: Exception => throw new RuntimeException("fetch: " + e.getMessage, e) }
|
|
57
78
|
|
|
58
79
|
val headers = new LinkedHashMap[String, Object]()
|
|
@@ -79,7 +79,7 @@ object PrepareQuery {
|
|
|
79
79
|
val item = it.next()
|
|
80
80
|
val key = item.get(0) match { case s: String => s; case _ => "" }
|
|
81
81
|
val v = item.get(1)
|
|
82
|
-
if (v != null && !containsStr(params, key)) out.put(key, v)
|
|
82
|
+
if (v != null && "$action" != key && !containsStr(params, key)) out.put(key, v)
|
|
83
83
|
}
|
|
84
84
|
out
|
|
85
85
|
}
|
|
@@ -9,15 +9,31 @@ object TransformRequest {
|
|
|
9
9
|
if (ctx.spec != null) ctx.spec.step = "reqform"
|
|
10
10
|
|
|
11
11
|
val transform = Helpers.toMapAny(Struct.getprop(ctx.point, "transform"))
|
|
12
|
-
if (transform == null) return ctx.reqdata
|
|
12
|
+
if (transform == null) return stripAction(ctx.reqdata)
|
|
13
13
|
|
|
14
14
|
val reqform = Struct.getprop(transform, "req", null)
|
|
15
|
-
if (reqform == null) return ctx.reqdata
|
|
15
|
+
if (reqform == null) return stripAction(ctx.reqdata)
|
|
16
16
|
|
|
17
17
|
val data = new LinkedHashMap[String, Object]()
|
|
18
18
|
data.put("reqdata", ctx.reqdata)
|
|
19
19
|
|
|
20
|
-
Struct.transform(data, reqform)
|
|
20
|
+
stripAction(Struct.transform(data, reqform))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// `$action` selects the point (see MakePoint); it is never an API field, so
|
|
24
|
+
// the body is a copy without it. The caller's map is left untouched.
|
|
25
|
+
private def stripAction(reqdata: Object): Object = {
|
|
26
|
+
reqdata match {
|
|
27
|
+
case src: JMap[_, _] if src.containsKey("$action") =>
|
|
28
|
+
val body = new LinkedHashMap[String, Object]()
|
|
29
|
+
val it = src.asInstanceOf[JMap[String, Object]].entrySet().iterator()
|
|
30
|
+
while (it.hasNext) {
|
|
31
|
+
val e = it.next()
|
|
32
|
+
if ("$action" != e.getKey) body.put(e.getKey, e.getValue)
|
|
33
|
+
}
|
|
34
|
+
body
|
|
35
|
+
case _ => reqdata
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
}
|
|
23
39
|
|
|
@@ -56,7 +56,7 @@ public final class Context {
|
|
|
56
56
|
if let e = cm.entries["explain"]?.asMap { ctrl.explain = e }
|
|
57
57
|
if let a = cm.entries["actor"]?.asString { ctrl.actor = a }
|
|
58
58
|
if let p = cm.entries["paging"]?.asMap { ctrl.paging = p }
|
|
59
|
-
} else if let b = basectx {
|
|
59
|
+
} else if let b = basectx, ctxProp(ctxmap, "opname") == nil {
|
|
60
60
|
ctrl = b.ctrl
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// stamps page/limit (or a cursor) into the request query; on the way back
|
|
3
3
|
// (PreResult) it reads the server's pagination signals - a `Link:
|
|
4
4
|
// rel="next"` header, `X-Page`/`X-Next-Page`/`X-Total-Count` headers, or
|
|
5
|
-
// `next`/`cursor`/`nextCursor`/`hasMore` fields in the body
|
|
6
|
-
// them on `ctx.result.paging`. A per-call cursor/page from ctrl takes
|
|
5
|
+
// `next`/`cursor`/`nextCursor`/`hasMore` fields in the body (snake_case
|
|
6
|
+
// forms too) - and records them on `ctx.result.paging` and `ctrl.paging`. A per-call cursor/page from ctrl takes
|
|
7
7
|
// priority (used by auto-iteration). Parameter names (`pageParam`,
|
|
8
8
|
// `limitParam`, `cursorParam`), the page size (`limit`) and the start page
|
|
9
9
|
// (`startPage`, default 1) are configurable.
|
|
@@ -68,8 +68,11 @@ public final class PagingFeature: BaseFeature {
|
|
|
68
68
|
} else if isNil(gp(spec.query, pageParam)) {
|
|
69
69
|
var page: Value? = nil
|
|
70
70
|
if let paging = paging {
|
|
71
|
+
// A record written back by preResult holds the page just fetched as
|
|
72
|
+
// "page" and the one to fetch as "nextPage", so nextPage wins.
|
|
73
|
+
let np = gp(paging, "nextPage")
|
|
71
74
|
let p = gp(paging, "page")
|
|
72
|
-
if !isNil(p) { page = p }
|
|
75
|
+
if !isNil(np) { page = np } else if !isNil(p) { page = p }
|
|
73
76
|
}
|
|
74
77
|
spec.query.entries[pageParam] = page ?? .int(Int64(foptInt(options, "startPage", 1)))
|
|
75
78
|
}
|
|
@@ -177,12 +180,16 @@ public final class PagingFeature: BaseFeature {
|
|
|
177
180
|
}
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
// Body-level
|
|
183
|
+
// Body-level signals; snake_case forms are read first so camelCase wins.
|
|
181
184
|
if let bm = body.asMap {
|
|
182
185
|
let next = gp(bm, "next")
|
|
183
186
|
if !isNil(next) && isNil(gp(paging, "next")) {
|
|
184
187
|
paging.entries["next"] = next
|
|
185
188
|
}
|
|
189
|
+
let snakeCursor = gp(bm, "next_cursor")
|
|
190
|
+
if !isNil(snakeCursor) {
|
|
191
|
+
paging.entries["cursor"] = snakeCursor
|
|
192
|
+
}
|
|
186
193
|
let cursor = gp(bm, "cursor")
|
|
187
194
|
if !isNil(cursor) {
|
|
188
195
|
paging.entries["cursor"] = cursor
|
|
@@ -191,6 +198,18 @@ public final class PagingFeature: BaseFeature {
|
|
|
191
198
|
if !isNil(nextCursor) {
|
|
192
199
|
paging.entries["cursor"] = nextCursor
|
|
193
200
|
}
|
|
201
|
+
if isNil(gp(paging, "nextPage")) {
|
|
202
|
+
var np = gp(bm, "nextPage")
|
|
203
|
+
if isNil(np) { np = gp(bm, "next_page") }
|
|
204
|
+
switch np {
|
|
205
|
+
case .int, .double, .string: paging.entries["nextPage"] = np
|
|
206
|
+
default: break
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if let smb = gp(bm, "has_more").asBool {
|
|
210
|
+
paging.entries["hasMore"] = .bool(smb)
|
|
211
|
+
explicitMore = true
|
|
212
|
+
}
|
|
194
213
|
if let hmb = gp(bm, "hasMore").asBool {
|
|
195
214
|
paging.entries["hasMore"] = .bool(hmb)
|
|
196
215
|
explicitMore = true
|
|
@@ -210,6 +229,14 @@ public final class PagingFeature: BaseFeature {
|
|
|
210
229
|
|
|
211
230
|
result.paging = paging
|
|
212
231
|
last = paging
|
|
232
|
+
|
|
233
|
+
// VMap is a class, so the caller's map is refilled in place; a fresh map
|
|
234
|
+
// on ctrl never reaches the caller.
|
|
235
|
+
if let shared = ctx.ctrl.paging {
|
|
236
|
+
shared.entries = paging.entries
|
|
237
|
+
} else {
|
|
238
|
+
ctx.ctrl.paging = paging
|
|
239
|
+
}
|
|
213
240
|
}
|
|
214
241
|
|
|
215
242
|
private func isList(_ ctx: Context) -> Bool {
|
|
@@ -16,14 +16,18 @@ private func testEnvelope(_ ctx: Context, _ data: Value) -> Value {
|
|
|
16
16
|
guard let point = ctx.point else { return data }
|
|
17
17
|
guard case .map(let tm)? = point.entries["transform"] else { return data }
|
|
18
18
|
guard case .string(let spec)? = tm.entries["res"] else { return data }
|
|
19
|
-
//
|
|
20
|
-
//
|
|
19
|
+
// Rebuild whatever nesting the transform unwraps. Multi-segment on purpose:
|
|
20
|
+
// GraphQL ops unwrap `body.data.<field>`, not just one envelope property.
|
|
21
21
|
guard spec.hasPrefix("`body."), spec.hasSuffix("`"), spec.count >= 8 else { return data }
|
|
22
22
|
let inner = String(spec.dropFirst(6).dropLast(1))
|
|
23
|
-
guard !inner.isEmpty
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
guard !inner.isEmpty else { return data }
|
|
24
|
+
var out = data
|
|
25
|
+
for seg in inner.split(separator: ".", omittingEmptySubsequences: false).reversed() {
|
|
26
|
+
let wrapped = VMap()
|
|
27
|
+
wrapped.entries[String(seg)] = out
|
|
28
|
+
out = .map(wrapped)
|
|
29
|
+
}
|
|
30
|
+
return out
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
private func testRespond(_ ctx: Context, _ status: Int, _ data: Value, _ extra: VMap?) -> Value {
|
|
@@ -89,9 +93,14 @@ private func testBuildArgs(_ ctx: Context, _ op: Operation, _ args: VMap?) -> Va
|
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
let
|
|
96
|
+
// Path AND query: a path-only read misses a query-addressed record
|
|
97
|
+
// (e.g. GET /result?trace_id=), which has no path param at all.
|
|
98
|
+
let reqdArgs = VList()
|
|
99
|
+
for kind in ["params", "query"] {
|
|
100
|
+
let argsPath = getpath(point, jtp("args", kind))
|
|
101
|
+
reqdArgs.items.append(contentsOf: select(argsPath, .map(vm(("reqd", .bool(true))))).asList?.items ?? [])
|
|
102
|
+
}
|
|
103
|
+
let reqd = transform(.list(reqdArgs), jtp("`$EACH`", "", "`$KEY.name`"))
|
|
95
104
|
|
|
96
105
|
let qand = VList()
|
|
97
106
|
let q = VMap()
|
|
@@ -202,17 +211,15 @@ public final class TestFeature: BaseFeature {
|
|
|
202
211
|
}
|
|
203
212
|
let args = testBuildArgs(ctx2, op, updateMatch)
|
|
204
213
|
let found = select(.map(entmap), args)
|
|
205
|
-
|
|
206
|
-
if isNil(ent) {
|
|
207
|
-
for (_, e) in entmap.entries where e.isMap { ent = e; break }
|
|
208
|
-
}
|
|
214
|
+
let ent = getelem(found, .int(0))
|
|
209
215
|
if isNil(ent) {
|
|
216
|
+
// update miss: 404, never another record
|
|
210
217
|
let extra = VMap()
|
|
211
218
|
extra.entries["statusText"] = .string("Not found")
|
|
212
219
|
return testRespond(ctx2, 404, .noval, extra)
|
|
213
220
|
}
|
|
214
|
-
if
|
|
215
|
-
|
|
221
|
+
if ent.isMap {
|
|
222
|
+
_ = merge(.list(VList([ent, .map(ctx2.reqdata)])))
|
|
216
223
|
}
|
|
217
224
|
delprop(ent, .string("$KEY"))
|
|
218
225
|
return testRespond(ctx2, 200, clone(ent), nil)
|
|
@@ -6,7 +6,21 @@ import Foundation
|
|
|
6
6
|
import FoundationNetworking
|
|
7
7
|
#endif
|
|
8
8
|
|
|
9
|
-
//
|
|
9
|
+
// Cookies OFF on both sessions: the process-wide session carries the
|
|
10
|
+
// process-wide cookie storage, so one call's Set-Cookie would come back on
|
|
11
|
+
// the next, under a different credential. Pooling is per configuration and
|
|
12
|
+
// is unaffected.
|
|
13
|
+
private func cookielessConfiguration() -> URLSessionConfiguration {
|
|
14
|
+
let cfg = URLSessionConfiguration.default
|
|
15
|
+
cfg.httpCookieStorage = nil
|
|
16
|
+
cfg.httpShouldSetCookies = false
|
|
17
|
+
cfg.httpCookieAcceptPolicy = .never
|
|
18
|
+
return cfg
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private let defaultSession = URLSession(configuration: cookielessConfiguration())
|
|
22
|
+
|
|
23
|
+
// Non-following twin of defaultSession. The station feature's
|
|
10
24
|
// middleware sets `redirect: manual` on the fetch definition under a
|
|
11
25
|
// hosts egress policy: a 3xx must come back as a response like any
|
|
12
26
|
// other, because an automatic follow would carry injected credentials
|
|
@@ -25,7 +39,8 @@ private final class ManualRedirectDelegate: NSObject, URLSessionTaskDelegate {
|
|
|
25
39
|
}
|
|
26
40
|
|
|
27
41
|
private let manualRedirectSession = URLSession(
|
|
28
|
-
configuration:
|
|
42
|
+
configuration: cookielessConfiguration(),
|
|
43
|
+
delegate: ManualRedirectDelegate(), delegateQueue: nil)
|
|
29
44
|
|
|
30
45
|
func defaultHttpFetch(_ fullurl: String, _ fetchdef: VMap) throws -> Value {
|
|
31
46
|
guard let url = URL(string: fullurl) else {
|
|
@@ -59,6 +74,10 @@ func defaultHttpFetch(_ fullurl: String, _ fetchdef: VMap) throws -> Value {
|
|
|
59
74
|
req.setValue("Mozilla/5.0 (compatible; ProjectNameSDK/1.0)", forHTTPHeaderField: "User-Agent")
|
|
60
75
|
}
|
|
61
76
|
|
|
77
|
+
// Also per request, so no store reached another way can rewrite the
|
|
78
|
+
// Cookie header set above — an `apiKey in: cookie` scheme sets one.
|
|
79
|
+
req.httpShouldHandleCookies = false
|
|
80
|
+
|
|
62
81
|
final class FetchBox: @unchecked Sendable {
|
|
63
82
|
var data: Data?
|
|
64
83
|
var resp: URLResponse?
|
|
@@ -67,7 +86,7 @@ func defaultHttpFetch(_ fullurl: String, _ fetchdef: VMap) throws -> Value {
|
|
|
67
86
|
let box = FetchBox()
|
|
68
87
|
let sem = DispatchSemaphore(value: 0)
|
|
69
88
|
let session = gp(fetchdef, "redirect").asString == "manual"
|
|
70
|
-
? manualRedirectSession :
|
|
89
|
+
? manualRedirectSession : defaultSession
|
|
71
90
|
let task = session.dataTask(with: req) { d, r, e in
|
|
72
91
|
box.data = d; box.resp = r; box.err = e; sem.signal()
|
|
73
92
|
}
|
|
@@ -71,7 +71,7 @@ func prepareQueryUtil(_ ctx: Context) -> VMap {
|
|
|
71
71
|
for item in items(.map(reqmatch)) {
|
|
72
72
|
let key = item[0].asString ?? ""
|
|
73
73
|
let val = item[1]
|
|
74
|
-
if !isNil(val) && !containsStr(paramnames, key) {
|
|
74
|
+
if !isNil(val) && "$action" != key && !containsStr(paramnames, key) {
|
|
75
75
|
query.entries[key] = val
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -54,14 +54,25 @@ func resultHeadersUtil(_ ctx: Context) -> Result {
|
|
|
54
54
|
return result!
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// `$action` selects the point (see makePointUtil); it is never an API field,
|
|
58
|
+
// so the body is a copy without it. The caller's map is left untouched.
|
|
59
|
+
private func stripAction(_ reqdata: Value) -> Value {
|
|
60
|
+
guard let src = reqdata.asMap, src.entries["$action"] != nil else { return reqdata }
|
|
61
|
+
let body = VMap()
|
|
62
|
+
for (key, val) in src.entries where "$action" != key {
|
|
63
|
+
body.entries[key] = val
|
|
64
|
+
}
|
|
65
|
+
return .map(body)
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
func transformRequestUtil(_ ctx: Context) -> Value {
|
|
58
69
|
if let sp = ctx.spec { sp.step = "reqform" }
|
|
59
70
|
|
|
60
|
-
guard let tfm = gp(ctx.point, "transform").asMap else { return .map(ctx.reqdata) }
|
|
71
|
+
guard let tfm = gp(ctx.point, "transform").asMap else { return stripAction(.map(ctx.reqdata)) }
|
|
61
72
|
let reqform = gp(tfm, "req")
|
|
62
|
-
if isNil(reqform) { return .map(ctx.reqdata) }
|
|
73
|
+
if isNil(reqform) { return stripAction(.map(ctx.reqdata)) }
|
|
63
74
|
|
|
64
|
-
return transform(.map(vm(("reqdata", .map(ctx.reqdata)))), reqform)
|
|
75
|
+
return stripAction(transform(.map(vm(("reqdata", .map(ctx.reqdata)))), reqform))
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
func transformResponseUtil(_ ctx: Context) -> Value {
|
|
@@ -58,7 +58,13 @@ class Context {
|
|
|
58
58
|
this.client = getprop(ctxmap, 'client', getprop(basectx, 'client'))
|
|
59
59
|
this.utility = getprop(ctxmap, 'utility', getprop(basectx, 'utility'))
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// An operation gets its OWN control unless the caller passed one: a
|
|
62
|
+
// paging cursor left on the client's control would otherwise be picked
|
|
63
|
+
// up by the next, unrelated call. A context with no opname is not an
|
|
64
|
+
// operation, so it still shares (an entity's, with the client's).
|
|
65
|
+
const opname = getprop(ctxmap, 'opname')
|
|
66
|
+
const basectrl = null == opname ? getprop(basectx, 'ctrl', this.ctrl) : this.ctrl
|
|
67
|
+
this.ctrl = getprop(ctxmap, 'ctrl', basectrl)
|
|
62
68
|
this.meta = getprop(ctxmap, 'meta', getprop(basectx, 'meta', this.meta))
|
|
63
69
|
|
|
64
70
|
this.config = getprop(ctxmap, 'config', getprop(basectx, 'config'))
|
|
@@ -79,7 +85,6 @@ class Context {
|
|
|
79
85
|
this.result = getprop(ctxmap, 'result', getprop(basectx, 'result'))
|
|
80
86
|
this.response = getprop(ctxmap, 'response', getprop(basectx, 'response'))
|
|
81
87
|
|
|
82
|
-
const opname = getprop(ctxmap, 'opname')
|
|
83
88
|
this.op = this.resolveOp(opname)
|
|
84
89
|
}
|
|
85
90
|
|
|
@@ -22,7 +22,7 @@ class PagingFeature extends BaseFeature {
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
PreRequest(this: any, ctx: any) {
|
|
25
|
-
if (!this._isList(ctx)) {
|
|
25
|
+
if (!this.active || !this._isList(ctx)) {
|
|
26
26
|
return
|
|
27
27
|
}
|
|
28
28
|
const spec = ctx.spec
|
|
@@ -51,7 +51,10 @@ class PagingFeature extends BaseFeature {
|
|
|
51
51
|
spec.query[cursorParam] = paging.cursor
|
|
52
52
|
}
|
|
53
53
|
else if (null == spec.query[pageParam]) {
|
|
54
|
-
|
|
54
|
+
// A record written back by PreResult holds the page just fetched as
|
|
55
|
+
// `page` and the one to fetch as `nextPage`, so nextPage wins.
|
|
56
|
+
spec.query[pageParam] = null != paging.nextPage ? paging.nextPage :
|
|
57
|
+
null != paging.page ? paging.page : (this._options.startPage || 1)
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
if (null != this._options.limit && null == spec.query[limitParam]) {
|
|
@@ -61,7 +64,7 @@ class PagingFeature extends BaseFeature {
|
|
|
61
64
|
|
|
62
65
|
|
|
63
66
|
PreResult(this: any, ctx: any) {
|
|
64
|
-
if (!this._isList(ctx)) {
|
|
67
|
+
if (!this.active || !this._isList(ctx)) {
|
|
65
68
|
return
|
|
66
69
|
}
|
|
67
70
|
const result = ctx.result
|
|
@@ -118,8 +121,17 @@ class PagingFeature extends BaseFeature {
|
|
|
118
121
|
|
|
119
122
|
if (body && 'object' === typeof body) {
|
|
120
123
|
if (null != body.next) { paging.next = paging.next || body.next }
|
|
124
|
+
if (null != body.next_cursor) { paging.cursor = body.next_cursor }
|
|
121
125
|
if (null != body.cursor) { paging.cursor = body.cursor }
|
|
122
126
|
if (null != body.nextCursor) { paging.cursor = body.nextCursor }
|
|
127
|
+
if (null == paging.nextPage) {
|
|
128
|
+
const np = null != body.nextPage ? body.nextPage : body.next_page
|
|
129
|
+
if ('number' === typeof np || 'string' === typeof np) { paging.nextPage = np }
|
|
130
|
+
}
|
|
131
|
+
if ('boolean' === typeof body.has_more) {
|
|
132
|
+
paging.hasMore = body.has_more
|
|
133
|
+
explicitMore = true
|
|
134
|
+
}
|
|
123
135
|
if ('boolean' === typeof body.hasMore) {
|
|
124
136
|
paging.hasMore = body.hasMore
|
|
125
137
|
explicitMore = true
|
|
@@ -138,6 +150,10 @@ class PagingFeature extends BaseFeature {
|
|
|
138
150
|
|
|
139
151
|
result.paging = paging
|
|
140
152
|
|
|
153
|
+
if (null != ctx.ctrl) {
|
|
154
|
+
ctx.ctrl.paging = paging
|
|
155
|
+
}
|
|
156
|
+
|
|
141
157
|
const client: any = this._client
|
|
142
158
|
client._paging = { last: paging }
|
|
143
159
|
}
|
|
@@ -193,6 +193,7 @@ class TestFeature extends BaseFeature {
|
|
|
193
193
|
const found = select(entmap, args)
|
|
194
194
|
const ent = getelem(found, 0)
|
|
195
195
|
if (null == ent) {
|
|
196
|
+
// update miss: 404, never another record
|
|
196
197
|
return respond(404, undefined, { statusText: S_NOT_FOUND })
|
|
197
198
|
}
|
|
198
199
|
else {
|
|
@@ -237,6 +238,8 @@ class TestFeature extends BaseFeature {
|
|
|
237
238
|
const out = clone(ent)
|
|
238
239
|
return respond(200, out)
|
|
239
240
|
}
|
|
241
|
+
|
|
242
|
+
return respond(404, undefined, { statusText: 'Unknown operation' })
|
|
240
243
|
}
|
|
241
244
|
|
|
242
245
|
// Optional network behaviour simulation over the mock transport. Enable
|
|
@@ -206,6 +206,7 @@ describe('FeatureCorpus', () => {
|
|
|
206
206
|
|
|
207
207
|
const probe: any = makeClient({})
|
|
208
208
|
if (!probe._rootctx.config.hasFeature(name)) {
|
|
209
|
+
t.diagnostic(`feature.${name}: inert (this SDK does not generate the feature)`)
|
|
209
210
|
return t.skip(`this SDK was generated without the ${name} feature`)
|
|
210
211
|
}
|
|
211
212
|
|