@voxgig/sdkgen 1.3.17 → 1.3.19
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/Deploy.js +16 -16
- package/dist/cmp/Deploy.js.map +1 -1
- package/dist/cmp/Entity.js +5 -1
- package/dist/cmp/Entity.js.map +1 -1
- package/dist/cmp/Feature.js +2 -1
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/cmp/ReadmeTop.js +13 -11
- package/dist/cmp/ReadmeTop.js.map +1 -1
- package/dist/helpers/canonType.js +8 -3
- package/dist/helpers/canonType.js.map +1 -1
- package/dist/helpers/collectDeps.d.ts +1 -1
- package/dist/helpers/collectDeps.js +36 -13
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/naming.d.ts +5 -1
- package/dist/helpers/naming.js +118 -0
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/opShape.d.ts +3 -1
- package/dist/helpers/opShape.js +87 -8
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/helpers/serverVars.d.ts +10 -0
- package/dist/helpers/serverVars.js +87 -0
- package/dist/helpers/serverVars.js.map +1 -0
- package/dist/sdkgen.d.ts +4 -3
- package/dist/sdkgen.js +11 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -10
- package/project/.sdk/model/target/cpp.aontu +4 -4
- package/project/.sdk/model/target/go-cli.aontu +17 -17
- package/project/.sdk/model/target/go-mcp.aontu +11 -11
- package/project/.sdk/model/target/go.aontu +1 -1
- package/project/.sdk/model/target/java.aontu +4 -4
- package/project/.sdk/model/target/kotlin.aontu +4 -4
- package/project/.sdk/model/target/lean.aontu +51 -0
- package/project/.sdk/model/target/scala.aontu +4 -4
- package/project/.sdk/src/cmp/c/EntityTypes_c.ts +3 -4
- package/project/.sdk/src/cmp/c/Entity_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeExamplesTest_c.ts +24 -7
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +3 -3
- package/project/.sdk/src/cmp/c/TestEntity_c.ts +1 -1
- package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +1 -1
- package/project/.sdk/src/cmp/clojure/ReadmeExamplesTest_clojure.ts +19 -8
- package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/ReadmeExamplesTest_cpp.ts +136 -0
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -0
- package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +2 -3
- package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +2 -2
- package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
- package/project/.sdk/src/cmp/csharp/ReadmeExamplesTest_csharp.ts +13 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +22 -15
- package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +2 -3
- package/project/.sdk/src/cmp/dart/Entity_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +2 -2
- package/project/.sdk/src/cmp/dart/Main_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/Package_dart.ts +1 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +4 -4
- package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +2 -3
- package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +1 -1
- package/project/.sdk/src/cmp/elixir/ReadmeExamplesTest_elixir.ts +21 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +14 -2
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +110 -18
- package/project/.sdk/src/cmp/go/Entity_go.ts +3 -3
- package/project/.sdk/src/cmp/go/Main_go.ts +7 -6
- package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +3 -3
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
- package/project/.sdk/src/cmp/go/utility_go.ts +25 -0
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +62 -35
- package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +7 -7
- package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +21 -18
- package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +9 -1
- package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +28 -18
- package/project/.sdk/src/cmp/java/EntityTypes_java.ts +2 -3
- package/project/.sdk/src/cmp/java/Entity_java.ts +3 -3
- package/project/.sdk/src/cmp/java/MainEntity_java.ts +2 -2
- package/project/.sdk/src/cmp/java/Package_java.ts +1 -1
- package/project/.sdk/src/cmp/java/ReadmeExamplesTest_java.ts +23 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
- package/project/.sdk/src/cmp/js/Config_js.ts +11 -0
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +2 -3
- package/project/.sdk/src/cmp/js/Entity_js.ts +3 -3
- package/project/.sdk/src/cmp/js/MainEntity_js.ts +2 -2
- package/project/.sdk/src/cmp/js/Main_js.ts +2 -2
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +4 -4
- package/project/.sdk/src/cmp/js/fragment/Config.fragment.js +2 -2
- package/project/.sdk/src/cmp/js/fragment/Direct.test.fragment.js +4 -0
- package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +2 -3
- package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +2 -2
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/kotlin/ReadmeExamplesTest_kotlin.ts +27 -2
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/lean/Config_lean.ts +88 -0
- package/project/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
- package/project/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Main_lean.ts +120 -0
- package/project/.sdk/src/cmp/lean/Package_lean.ts +68 -0
- package/project/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
- package/project/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
- package/project/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +38 -0
- package/project/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
- package/project/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
- package/project/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
- package/project/.sdk/src/cmp/lean/ReadmeRef_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Test_lean.ts +207 -0
- package/project/.sdk/src/cmp/lean/utility_lean.ts +78 -0
- package/project/.sdk/src/cmp/lua/Config_lua.ts +10 -1
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +2 -3
- package/project/.sdk/src/cmp/lua/Entity_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +1 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +1 -1
- package/project/.sdk/src/cmp/ocaml/ReadmeExamplesTest_ocaml.ts +29 -14
- package/project/.sdk/src/cmp/perl/Entity_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +2 -2
- package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
- package/project/.sdk/src/cmp/php/Config_php.ts +13 -2
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +2 -3
- package/project/.sdk/src/cmp/php/Entity_php.ts +3 -3
- package/project/.sdk/src/cmp/php/MainEntity_php.ts +2 -2
- package/project/.sdk/src/cmp/php/Package_php.ts +1 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +1 -1
- package/project/.sdk/src/cmp/py/Config_py.ts +10 -1
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +2 -3
- package/project/.sdk/src/cmp/py/Entity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Main_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +1 -1
- package/project/.sdk/src/cmp/rb/Config_rb.ts +12 -1
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +15 -5
- package/project/.sdk/src/cmp/rb/Entity_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/Package_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +1 -1
- package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +3 -4
- package/project/.sdk/src/cmp/rust/Entity_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/Package_rust.ts +1 -1
- package/project/.sdk/src/cmp/rust/ReadmeExamplesTest_rust.ts +22 -10
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +25 -18
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +2 -3
- package/project/.sdk/src/cmp/scala/Entity_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +2 -2
- package/project/.sdk/src/cmp/scala/ReadmeExamplesTest_scala.ts +22 -3
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/Test_scala.ts +1 -1
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +12 -6
- package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +2 -2
- package/project/.sdk/src/cmp/swift/Package_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +18 -1
- package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +1 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +11 -0
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +2 -3
- package/project/.sdk/src/cmp/ts/Entity_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/Main_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +4 -4
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +2 -2
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +4 -0
- package/project/.sdk/src/cmp/zig/Entity_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +2 -2
- package/project/.sdk/src/cmp/zig/Package_zig.ts +10 -2
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +8 -16
- package/project/.sdk/tm/csharp/Makefile +6 -6
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
- package/project/.sdk/tm/dart/Makefile +3 -3
- package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
- package/project/.sdk/tm/go/Makefile +6 -6
- package/project/.sdk/tm/go/feature/test_feature.go +33 -1
- package/project/.sdk/tm/go/test/primary_utility_test.go +46 -42
- package/project/.sdk/tm/go/test/runner_test.go +30 -1
- package/project/.sdk/tm/go/utility/make_options.go +48 -0
- package/project/.sdk/tm/java/Makefile +6 -6
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
- package/project/.sdk/tm/js/Makefile +6 -6
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -1
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +13 -0
- package/project/.sdk/tm/kotlin/Makefile +6 -6
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +7 -20
- package/project/.sdk/tm/lean/LICENSE +21 -0
- package/project/.sdk/tm/lean/VERSION +1 -0
- package/project/.sdk/tm/lean/src/SdkFeature.lean +171 -0
- package/project/.sdk/tm/lean/src/SdkFeatures.lean +602 -0
- package/project/.sdk/tm/lean/src/SdkJson.lean +134 -0
- package/project/.sdk/tm/lean/src/SdkRuntime.lean +356 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +617 -0
- package/project/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
- package/project/.sdk/tm/lean/src/Vregex.lean +412 -0
- package/project/.sdk/tm/lean/src/feature/README.md +5 -0
- package/project/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +697 -0
- package/project/.sdk/tm/lean/test/TFeature.lean +268 -0
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +349 -0
- package/project/.sdk/tm/lua/Makefile +7 -7
- package/project/.sdk/tm/lua/feature/test_feature.lua +29 -1
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +14 -8
- package/project/.sdk/tm/lua/utility/make_options.lua +39 -0
- package/project/.sdk/tm/perl/Makefile +6 -6
- package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
- package/project/.sdk/tm/php/Makefile +6 -6
- package/project/.sdk/tm/php/feature/TestFeature.php +30 -2
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +14 -7
- package/project/.sdk/tm/php/utility/MakeOptions.php +44 -0
- package/project/.sdk/tm/py/Makefile +6 -6
- package/project/.sdk/tm/py/feature/test_feature.py +28 -1
- package/project/.sdk/tm/py/test/test_primary_utility.py +18 -18
- package/project/.sdk/tm/py/utility/make_options.py +42 -0
- package/project/.sdk/tm/rb/Makefile +6 -6
- package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +11 -8
- package/project/.sdk/tm/rb/utility/make_options.rb +37 -0
- package/project/.sdk/tm/rust/Makefile +6 -6
- package/project/.sdk/tm/rust/tests/common/mod.rs +37 -1
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +12 -26
- package/project/.sdk/tm/swift/Makefile +6 -6
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
- package/project/.sdk/tm/ts/Makefile +6 -6
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +39 -1
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +69 -21
- package/src/cmp/Deploy.ts +16 -16
- package/src/cmp/Entity.ts +5 -1
- package/src/cmp/Feature.ts +2 -1
- package/src/cmp/ReadmeTop.ts +13 -11
- package/src/helpers/canonType.ts +8 -3
- package/src/helpers/collectDeps.ts +39 -12
- package/src/helpers/naming.ts +130 -0
- package/src/helpers/opShape.ts +99 -12
- package/src/helpers/serverVars.ts +105 -0
- package/src/sdkgen.ts +12 -3
|
@@ -41,11 +41,39 @@ function TestFeature:init(ctx, options)
|
|
|
41
41
|
local test_self = self
|
|
42
42
|
|
|
43
43
|
local function test_fetcher(fctx, _fullurl, _fetchdef)
|
|
44
|
+
-- Shape the mock payload the way the real API would, so the op's
|
|
45
|
+
-- response transform recovers the entity from it. A point carrying
|
|
46
|
+
-- transform.res of `body.item` describes an API that answers
|
|
47
|
+
-- { item = {...} }; handing back the bare entity means the transform
|
|
48
|
+
-- unwraps a property that is not there and the caller gets nil.
|
|
49
|
+
-- The mock has to agree with the model, or it only ever simulates
|
|
50
|
+
-- APIs whose responses happen to be unwrapped. Mirrors the ts/py mocks.
|
|
51
|
+
local function envelope(data)
|
|
52
|
+
local point = fctx.point
|
|
53
|
+
if data == nil or type(point) ~= "table" then
|
|
54
|
+
return data
|
|
55
|
+
end
|
|
56
|
+
local transform = point.transform
|
|
57
|
+
if type(transform) ~= "table" then
|
|
58
|
+
return data
|
|
59
|
+
end
|
|
60
|
+
local restf = transform.res
|
|
61
|
+
if type(restf) ~= "string" then
|
|
62
|
+
return data
|
|
63
|
+
end
|
|
64
|
+
local key = string.match(restf, "^`body%.([^`%.]+)`$")
|
|
65
|
+
if key == nil then
|
|
66
|
+
return data
|
|
67
|
+
end
|
|
68
|
+
return { [key] = data }
|
|
69
|
+
end
|
|
70
|
+
|
|
44
71
|
local function respond(status, data, extra)
|
|
72
|
+
local payload = envelope(data)
|
|
45
73
|
local out = {
|
|
46
74
|
status = status,
|
|
47
75
|
statusText = "OK",
|
|
48
|
-
json = function() return
|
|
76
|
+
json = function() return payload end,
|
|
49
77
|
body = "not-used",
|
|
50
78
|
}
|
|
51
79
|
if type(extra) == "table" then
|
|
@@ -576,6 +576,9 @@ describe("PrimaryUtility", function()
|
|
|
576
576
|
it("fetcher-live", function()
|
|
577
577
|
local calls = {}
|
|
578
578
|
local live_client = sdk.new({
|
|
579
|
+
-- Concrete base: a live construction must satisfy any server variables
|
|
580
|
+
-- a templated base URL declares; a literal base sidesteps the requirement.
|
|
581
|
+
base = "http://localhost:8080",
|
|
579
582
|
system = {
|
|
580
583
|
fetch = function(url, fetchdef)
|
|
581
584
|
table.insert(calls, { url = url, init = fetchdef })
|
|
@@ -600,6 +603,7 @@ describe("PrimaryUtility", function()
|
|
|
600
603
|
|
|
601
604
|
it("fetcher-blocked-test-mode", function()
|
|
602
605
|
local blocked_client = sdk.new({
|
|
606
|
+
base = "http://localhost:8080",
|
|
603
607
|
system = {
|
|
604
608
|
fetch = function(url, fetchdef)
|
|
605
609
|
return {}, nil
|
|
@@ -1052,14 +1056,16 @@ describe("PrimaryUtility", function()
|
|
|
1052
1056
|
|
|
1053
1057
|
|
|
1054
1058
|
it("preparePath-basic", function()
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1059
|
+
-- Was hand-written cases that had drifted out of the shared corpus
|
|
1060
|
+
-- (the preparePath fixture shipped as an empty `set: []`).
|
|
1061
|
+
runset(get_spec(primary, "preparePath", "basic"), function(entry)
|
|
1062
|
+
local ctxmap = entry["ctx"]
|
|
1063
|
+
if type(ctxmap) ~= "table" then
|
|
1064
|
+
ctxmap = {}
|
|
1065
|
+
end
|
|
1066
|
+
local ctx = make_ctx_from_map(ctxmap, client, utility)
|
|
1067
|
+
return utility.prepare_path(ctx), nil
|
|
1068
|
+
end)
|
|
1063
1069
|
end)
|
|
1064
1070
|
|
|
1065
1071
|
|
|
@@ -92,6 +92,13 @@ local function make_options_util(ctx)
|
|
|
92
92
|
clean = {
|
|
93
93
|
keys = "key,token,id",
|
|
94
94
|
},
|
|
95
|
+
-- Server-variable values for a templated base URL (OpenAPI server
|
|
96
|
+
-- variables): {name} placeholders in `base` are substituted from this
|
|
97
|
+
-- map at construction. Spec defaults arrive via the generated config;
|
|
98
|
+
-- user values override them.
|
|
99
|
+
server = {
|
|
100
|
+
["`$CHILD`"] = "",
|
|
101
|
+
},
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
-- Preserve system.fetch before merge/validate.
|
|
@@ -104,6 +111,38 @@ local function make_options_util(ctx)
|
|
|
104
111
|
end
|
|
105
112
|
opts = validated
|
|
106
113
|
|
|
114
|
+
-- Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
115
|
+
-- Every placeholder must resolve to a non-empty value: from
|
|
116
|
+
-- options.server (user), else the config default. A placeholder that
|
|
117
|
+
-- resolves to "" is a construction ERROR in live mode — the URL cannot
|
|
118
|
+
-- work — but in test mode substitutes the deterministic value
|
|
119
|
+
-- "test-<name>" so offline tests need no configuration.
|
|
120
|
+
local base = opts.base
|
|
121
|
+
if type(base) == "string" and string.find(base, "{", 1, true) then
|
|
122
|
+
local testmode = vs.getpath(opts, "test.active") == true
|
|
123
|
+
or vs.getpath(opts, "feature.test.active") == true
|
|
124
|
+
local server = type(opts.server) == "table" and opts.server or {}
|
|
125
|
+
local sdkname = vs.getpath(config, "main.name")
|
|
126
|
+
if type(sdkname) ~= "string" or sdkname == "" then
|
|
127
|
+
sdkname = "SDK"
|
|
128
|
+
end
|
|
129
|
+
opts.base = string.gsub(base, "{([%w_]+)}", function(name)
|
|
130
|
+
local val = server[name]
|
|
131
|
+
if type(val) ~= "string" then
|
|
132
|
+
val = ""
|
|
133
|
+
end
|
|
134
|
+
if val == "" then
|
|
135
|
+
if testmode then
|
|
136
|
+
return "test-" .. name
|
|
137
|
+
end
|
|
138
|
+
error(sdkname .. ": the server variable '" .. name .. "' is required: " ..
|
|
139
|
+
"the API base URL is '" .. base .. "' — pass " ..
|
|
140
|
+
"{ server = { " .. name .. " = \"...\" } } in the SDK options", 0)
|
|
141
|
+
end
|
|
142
|
+
return val
|
|
143
|
+
end)
|
|
144
|
+
end
|
|
145
|
+
|
|
107
146
|
-- Restore system.fetch.
|
|
108
147
|
if sys_fetch ~= nil then
|
|
109
148
|
if type(opts["system"]) == "table" then
|
|
@@ -20,10 +20,10 @@ clean:
|
|
|
20
20
|
# Build a CPAN dist in a throwaway .release/ dir to validate the package,
|
|
21
21
|
# then tag perl/vX.Y.Z (version from $VERSION in lib/*SDK.pm). The CPAN
|
|
22
22
|
# registry entry for this port is declared but pending, so publish is
|
|
23
|
-
# tag-only: no upload happens. Run headless under the
|
|
23
|
+
# tag-only: no upload happens. Run headless under the boru key vault, which
|
|
24
24
|
# injects the GitHub token (never on disk or argv):
|
|
25
|
-
#
|
|
26
|
-
#
|
|
25
|
+
# boru vault exec --for=github=<alias> -- make publish
|
|
26
|
+
# boru `--dry-run` injects a filler token we detect to rehearse (build only,
|
|
27
27
|
# no tag). set -e + tag-last: a failed build never leaves a tag behind.
|
|
28
28
|
#
|
|
29
29
|
# NOTE: `perl Makefile.PL` (ExtUtils::MakeMaker) GENERATES a file named
|
|
@@ -31,7 +31,7 @@ clean:
|
|
|
31
31
|
# dist build always happens inside .release/, never in place.
|
|
32
32
|
VERSION := $(shell sed -nE "s/.*VERSION *= *'([^']+)'.*/\1/p" lib/*SDK.pm | head -1)
|
|
33
33
|
TAG := perl/v$(VERSION)
|
|
34
|
-
|
|
34
|
+
BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
|
|
35
35
|
publish: test
|
|
36
36
|
@if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
|
|
37
37
|
echo "tag $(TAG) already exists — bump VERSION in lib/*SDK.pm first"; exit 1; fi
|
|
@@ -42,8 +42,8 @@ publish: test
|
|
|
42
42
|
{ [ -f README.md ] && cp README.md .release/ || true; }; \
|
|
43
43
|
(cd .release && $(PERL) Makefile.PL >/dev/null && echo "dist metadata OK"); \
|
|
44
44
|
rm -rf .release; \
|
|
45
|
-
if [ "$$token" = "$(
|
|
46
|
-
echo "[dry-run]
|
|
45
|
+
if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \
|
|
46
|
+
echo "[dry-run] boru filler token detected: would tag $(TAG); nothing pushed."; \
|
|
47
47
|
exit 0; \
|
|
48
48
|
fi; \
|
|
49
49
|
git tag -a "$(TAG)" -m "perl v$(VERSION)"; \
|
|
@@ -888,23 +888,14 @@ runset('prepareParams.basic', get_spec($PRIMARY, 'prepareParams', 'basic'), sub
|
|
|
888
888
|
|
|
889
889
|
# === preparePath ===
|
|
890
890
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
{
|
|
901
|
-
my $ctx = make_test_full_ctx($client, $utility);
|
|
902
|
-
$ctx->{point} = {
|
|
903
|
-
'parts' => ['items'],
|
|
904
|
-
'args' => { 'params' => [] },
|
|
905
|
-
};
|
|
906
|
-
is($utility->{prepare_path}->($ctx), 'items', 'prepare_path single');
|
|
907
|
-
}
|
|
891
|
+
# Was two hand-written cases that had drifted out of the shared corpus
|
|
892
|
+
# (the preparePath fixture shipped as an empty `set: []`).
|
|
893
|
+
runset('preparePath.basic', get_spec($PRIMARY, 'preparePath', 'basic'), sub {
|
|
894
|
+
my ($entry) = @_;
|
|
895
|
+
my $ctxmap = $entry->{ctx} || {};
|
|
896
|
+
my $ctx = make_ctx_from_map($ctxmap, $client, $utility);
|
|
897
|
+
return $utility->{prepare_path}->($ctx);
|
|
898
|
+
});
|
|
908
899
|
|
|
909
900
|
|
|
910
901
|
# === prepareQuery ===
|
|
@@ -13,20 +13,20 @@ clean:
|
|
|
13
13
|
# Packagist has no upload — it tracks the repo and indexes each git tag
|
|
14
14
|
# php/vX.Y.Z (a configured GitHub webhook, or the Packagist "Update" API,
|
|
15
15
|
# refreshes the package). So publishing a version means pushing the tag. Run
|
|
16
|
-
# headless under the
|
|
17
|
-
#
|
|
18
|
-
#
|
|
16
|
+
# headless under the boru key vault, which injects the GitHub token:
|
|
17
|
+
# boru vault exec --for=github=<alias> -- make publish
|
|
18
|
+
# boru `--dry-run` injects a filler token we detect to rehearse (no tag/push).
|
|
19
19
|
# set -e + tag-last: a failed push never leaves a tag behind.
|
|
20
20
|
VERSION := $(shell cat VERSION)
|
|
21
21
|
TAG := php/v$(VERSION)
|
|
22
|
-
|
|
22
|
+
BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
|
|
23
23
|
publish: test
|
|
24
24
|
@if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
|
|
25
25
|
echo "tag $(TAG) already exists — bump VERSION first"; exit 1; fi
|
|
26
26
|
@set -e; \
|
|
27
27
|
token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
|
|
28
|
-
if [ "$$token" = "$(
|
|
29
|
-
echo "[dry-run]
|
|
28
|
+
if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \
|
|
29
|
+
echo "[dry-run] boru filler token detected: would tag $(TAG) for Packagist; nothing pushed."; \
|
|
30
30
|
exit 0; \
|
|
31
31
|
fi; \
|
|
32
32
|
git tag -a "$(TAG)" -m "php v$(VERSION)"; \
|
|
@@ -48,11 +48,39 @@ class ProjectNameTestFeature extends ProjectNameBaseFeature
|
|
|
48
48
|
$entity->data = $entity_data;
|
|
49
49
|
|
|
50
50
|
$test_fetcher = function (ProjectNameContext $fctx, string $_fullurl, array $_fetchdef) use ($entity): array {
|
|
51
|
-
|
|
51
|
+
// Shape the mock payload the way the real API would, so the op's
|
|
52
|
+
// response transform recovers the entity from it. A point carrying
|
|
53
|
+
// transform.res of `body.item` describes an API that answers
|
|
54
|
+
// {"item": {...}}; handing back the bare entity means the
|
|
55
|
+
// transform unwraps a property that is not there and the caller
|
|
56
|
+
// gets null. The mock has to agree with the model, or it only
|
|
57
|
+
// ever simulates APIs whose responses happen to be unwrapped.
|
|
58
|
+
// Mirrors the ts/py mocks.
|
|
59
|
+
$envelope = function (mixed $data) use ($fctx): mixed {
|
|
60
|
+
$point = $fctx->point ?? null;
|
|
61
|
+
if ($data === null || !is_array($point)) {
|
|
62
|
+
return $data;
|
|
63
|
+
}
|
|
64
|
+
$transform = $point['transform'] ?? null;
|
|
65
|
+
if (!is_array($transform)) {
|
|
66
|
+
return $data;
|
|
67
|
+
}
|
|
68
|
+
$restf = $transform['res'] ?? null;
|
|
69
|
+
if (!is_string($restf)) {
|
|
70
|
+
return $data;
|
|
71
|
+
}
|
|
72
|
+
if (!preg_match('/^`body\.([^`.]+)`$/', $restf, $m)) {
|
|
73
|
+
return $data;
|
|
74
|
+
}
|
|
75
|
+
return [$m[1] => $data];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
$respond = function (int $status, mixed $data, ?array $extra = null) use ($envelope): array {
|
|
79
|
+
$payload = $envelope($data);
|
|
52
80
|
$out = [
|
|
53
81
|
'status' => $status,
|
|
54
82
|
'statusText' => 'OK',
|
|
55
|
-
'json' => function () use ($
|
|
83
|
+
'json' => function () use ($payload) { return $payload; },
|
|
56
84
|
'body' => 'not-used',
|
|
57
85
|
];
|
|
58
86
|
if ($extra) {
|
|
@@ -587,6 +587,10 @@ class PrimaryUtilityTest extends TestCase
|
|
|
587
587
|
{
|
|
588
588
|
$calls = [];
|
|
589
589
|
$live_client = new ProjectNameSDK([
|
|
590
|
+
// Concrete base: a live construction must satisfy any server
|
|
591
|
+
// variables a templated base URL declares; a literal base
|
|
592
|
+
// sidesteps the requirement.
|
|
593
|
+
'base' => 'http://localhost:8080',
|
|
590
594
|
'system' => [
|
|
591
595
|
'fetch' => function (string $url, array $fetchdef) use (&$calls) {
|
|
592
596
|
$calls[] = ['url' => $url, 'init' => $fetchdef];
|
|
@@ -614,6 +618,7 @@ class PrimaryUtilityTest extends TestCase
|
|
|
614
618
|
public function test_fetcher_blocked_test_mode(): void
|
|
615
619
|
{
|
|
616
620
|
$blocked_client = new ProjectNameSDK([
|
|
621
|
+
'base' => 'http://localhost:8080',
|
|
617
622
|
'system' => [
|
|
618
623
|
'fetch' => function (string $url, array $fetchdef) {
|
|
619
624
|
return [[], null];
|
|
@@ -1136,16 +1141,18 @@ class PrimaryUtilityTest extends TestCase
|
|
|
1136
1141
|
|
|
1137
1142
|
public function test_prepare_path_basic(): void
|
|
1138
1143
|
{
|
|
1144
|
+
// Was hand-written cases that had drifted out of the shared corpus
|
|
1145
|
+
// (the preparePath fixture shipped as an empty `set: []`).
|
|
1146
|
+
$spec = self::load_test_spec();
|
|
1147
|
+
$primary = self::get_spec($spec, 'primary');
|
|
1139
1148
|
$client = ProjectNameSDK::test(null, null);
|
|
1140
1149
|
$utility = $client->get_utility();
|
|
1141
|
-
$ctx = self::make_test_full_ctx($client, $utility);
|
|
1142
|
-
$ctx->point = [
|
|
1143
|
-
'parts' => ['api', 'planet', '{id}'],
|
|
1144
|
-
'args' => ['params' => []],
|
|
1145
|
-
];
|
|
1146
1150
|
|
|
1147
|
-
$
|
|
1148
|
-
|
|
1151
|
+
$this->runset(self::get_spec($primary, 'preparePath', 'basic'), function (array $entry) use ($client, $utility) {
|
|
1152
|
+
$ctxmap = $entry['ctx'] ?? [];
|
|
1153
|
+
$ctx = self::make_ctx_from_map($ctxmap, $client, $utility);
|
|
1154
|
+
return [($utility->prepare_path)($ctx), null];
|
|
1155
|
+
});
|
|
1149
1156
|
}
|
|
1150
1157
|
|
|
1151
1158
|
|
|
@@ -88,6 +88,11 @@ class ProjectNameMakeOptions
|
|
|
88
88
|
'system' => (object)[],
|
|
89
89
|
'test' => ['active' => false, 'entity' => ['`$OPEN`' => true]],
|
|
90
90
|
'clean' => ['keys' => 'key,token,id'],
|
|
91
|
+
// Server-variable values for a templated base URL (OpenAPI server
|
|
92
|
+
// variables): {name} placeholders in 'base' are substituted from
|
|
93
|
+
// this map at construction. Spec defaults arrive via the generated
|
|
94
|
+
// config; user values override them.
|
|
95
|
+
'server' => ['`$CHILD`' => ''],
|
|
91
96
|
];
|
|
92
97
|
|
|
93
98
|
// Empty [] would be treated as a list and clobber the map under merge;
|
|
@@ -101,6 +106,45 @@ class ProjectNameMakeOptions
|
|
|
101
106
|
$opts = [];
|
|
102
107
|
}
|
|
103
108
|
|
|
109
|
+
// Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
110
|
+
// Every placeholder must resolve to a non-empty value: from
|
|
111
|
+
// $options['server'] (user), else the config default. A placeholder
|
|
112
|
+
// that resolves to '' is a construction ERROR in live mode — the URL
|
|
113
|
+
// cannot work — but in test mode substitutes the deterministic value
|
|
114
|
+
// "test-<name>" so offline tests need no configuration.
|
|
115
|
+
$base = $opts['base'] ?? null;
|
|
116
|
+
if (is_string($base) && strpos($base, '{') !== false) {
|
|
117
|
+
$testmode =
|
|
118
|
+
\Voxgig\Struct\Struct::getpath($opts, 'test.active') === true
|
|
119
|
+
|| \Voxgig\Struct\Struct::getpath($opts, 'feature.test.active') === true;
|
|
120
|
+
$server = is_array($opts['server'] ?? null) ? $opts['server'] : [];
|
|
121
|
+
$sdkname = \Voxgig\Struct\Struct::getpath($config, 'main.name');
|
|
122
|
+
if (!is_string($sdkname) || $sdkname === '') {
|
|
123
|
+
$sdkname = 'SDK';
|
|
124
|
+
}
|
|
125
|
+
$opts['base'] = preg_replace_callback(
|
|
126
|
+
'/\{([A-Za-z0-9_]+)\}/',
|
|
127
|
+
function ($m) use ($server, $testmode, $sdkname, $base) {
|
|
128
|
+
$name = $m[1];
|
|
129
|
+
$val = $server[$name] ?? '';
|
|
130
|
+
if (!is_string($val)) {
|
|
131
|
+
$val = '';
|
|
132
|
+
}
|
|
133
|
+
if ($val === '') {
|
|
134
|
+
if ($testmode) {
|
|
135
|
+
return 'test-' . $name;
|
|
136
|
+
}
|
|
137
|
+
throw new \InvalidArgumentException(
|
|
138
|
+
$sdkname . ": the server variable '" . $name . "' is required: " .
|
|
139
|
+
"the API base URL is '" . $base . "' — pass " .
|
|
140
|
+
"['server' => ['" . $name . "' => '...']] in the SDK options");
|
|
141
|
+
}
|
|
142
|
+
return $val;
|
|
143
|
+
},
|
|
144
|
+
$base
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
104
148
|
if ($sys_fetch) {
|
|
105
149
|
if (!is_array($opts['system'] ?? null)) {
|
|
106
150
|
$opts['system'] = [];
|
|
@@ -10,16 +10,16 @@ clean:
|
|
|
10
10
|
find . -name __pycache__ -exec rm -rf {} + 2>/dev/null; true
|
|
11
11
|
|
|
12
12
|
# --- Release: publish to PyPI ---------------------------------------------
|
|
13
|
-
# Publish this package to PyPI, then tag py/vX.Y.Z. Run headless under the
|
|
13
|
+
# Publish this package to PyPI, then tag py/vX.Y.Z. Run headless under the boru
|
|
14
14
|
# key vault, which injects the PyPI + GitHub tokens as environment variables
|
|
15
15
|
# (never written to disk or argv):
|
|
16
|
-
#
|
|
17
|
-
#
|
|
16
|
+
# boru vault exec --for=pypi=<alias> --for=github=<alias> -- make publish
|
|
17
|
+
# boru `--dry-run` injects a filler token we detect to rehearse: builds the dist
|
|
18
18
|
# but performs no upload, tag, or push. set -e + tag-last: a failed upload never
|
|
19
19
|
# leaves a tag behind. Needs python `build` + `twine` (pip install build twine).
|
|
20
20
|
VERSION := $(shell sed -nE 's/^version *= *"([^"]+)".*/\1/p' pyproject.toml | head -1)
|
|
21
21
|
TAG := py/v$(VERSION)
|
|
22
|
-
|
|
22
|
+
BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
|
|
23
23
|
publish: test
|
|
24
24
|
@if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
|
|
25
25
|
echo "tag $(TAG) already exists — bump pyproject.toml version first"; exit 1; fi
|
|
@@ -27,8 +27,8 @@ publish: test
|
|
|
27
27
|
token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
|
|
28
28
|
rm -rf dist; \
|
|
29
29
|
python3 -m build; \
|
|
30
|
-
if [ "$$token" = "$(
|
|
31
|
-
echo "[dry-run]
|
|
30
|
+
if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ] || [ "$$TWINE_PASSWORD" = "$(BORU_DRY_RUN_FILLER)" ]; then \
|
|
31
|
+
echo "[dry-run] boru filler token detected: built the dist; would upload to PyPI and tag $(TAG); nothing pushed."; \
|
|
32
32
|
exit 0; \
|
|
33
33
|
fi; \
|
|
34
34
|
python3 -m twine upload dist/*; \
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# ProjectName SDK test feature
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
+
import re
|
|
4
5
|
import random
|
|
5
6
|
import time
|
|
6
7
|
|
|
@@ -8,6 +9,11 @@ from utility.voxgig_struct import voxgig_struct as vs
|
|
|
8
9
|
from feature.base_feature import ProjectNameBaseFeature
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
# The `body.<key>` form of an op's response transform: the mock wraps its
|
|
13
|
+
# payload in <key> so the transform can unwrap it again.
|
|
14
|
+
ENVELOPE_RES_RE = re.compile(r"^`body\.([^`.]+)`$")
|
|
15
|
+
|
|
16
|
+
|
|
11
17
|
class ProjectNameTestFeature(ProjectNameBaseFeature):
|
|
12
18
|
def __init__(self):
|
|
13
19
|
super().__init__()
|
|
@@ -36,11 +42,32 @@ class ProjectNameTestFeature(ProjectNameBaseFeature):
|
|
|
36
42
|
test_self = self
|
|
37
43
|
|
|
38
44
|
def test_fetcher(fctx, _fullurl, _fetchdef):
|
|
45
|
+
# Shape the mock payload the way the real API would, so the op's
|
|
46
|
+
# response transform recovers the entity from it. A point carrying
|
|
47
|
+
# transform.res of `body.item` describes an API that answers
|
|
48
|
+
# {"item": {...}}; handing back the bare entity means the transform
|
|
49
|
+
# unwraps a property that is not there and the caller gets None.
|
|
50
|
+
# The mock has to agree with the model, or it only ever simulates
|
|
51
|
+
# APIs whose responses happen to be unwrapped. Mirrors the ts mock.
|
|
52
|
+
def envelope(data):
|
|
53
|
+
point = getattr(fctx, "point", None)
|
|
54
|
+
if data is None or not isinstance(point, dict):
|
|
55
|
+
return data
|
|
56
|
+
transform = point.get("transform")
|
|
57
|
+
if not isinstance(transform, dict):
|
|
58
|
+
return data
|
|
59
|
+
restf = transform.get("res")
|
|
60
|
+
if not isinstance(restf, str):
|
|
61
|
+
return data
|
|
62
|
+
m = ENVELOPE_RES_RE.match(restf)
|
|
63
|
+
return data if m is None else {m.group(1): data}
|
|
64
|
+
|
|
39
65
|
def respond(status, data, extra=None):
|
|
66
|
+
payload = envelope(data)
|
|
40
67
|
out = {
|
|
41
68
|
"status": status,
|
|
42
69
|
"statusText": "OK",
|
|
43
|
-
"json": lambda:
|
|
70
|
+
"json": lambda: payload,
|
|
44
71
|
"body": "not-used",
|
|
45
72
|
}
|
|
46
73
|
if isinstance(extra, dict):
|
|
@@ -468,6 +468,10 @@ class TestPrimaryUtility:
|
|
|
468
468
|
return {"status": 200, "statusText": "OK"}, None
|
|
469
469
|
|
|
470
470
|
live_client = ProjectNameSDK({
|
|
471
|
+
# Concrete base: a live construction must satisfy any server
|
|
472
|
+
# variables a templated base URL declares; a literal base
|
|
473
|
+
# sidesteps the requirement.
|
|
474
|
+
"base": "http://localhost:8080",
|
|
471
475
|
"system": {
|
|
472
476
|
"fetch": mock_fetch,
|
|
473
477
|
},
|
|
@@ -490,6 +494,7 @@ class TestPrimaryUtility:
|
|
|
490
494
|
return {}, None
|
|
491
495
|
|
|
492
496
|
blocked_client = ProjectNameSDK({
|
|
497
|
+
"base": "http://localhost:8080",
|
|
493
498
|
"system": {
|
|
494
499
|
"fetch": mock_fetch,
|
|
495
500
|
},
|
|
@@ -945,28 +950,23 @@ class TestPrimaryUtility:
|
|
|
945
950
|
_runset(_get_spec(primary, "prepareParams", "basic"), subject)
|
|
946
951
|
|
|
947
952
|
def test_prepare_path_basic(self):
|
|
953
|
+
# Was two hand-written cases that had drifted out of the shared corpus
|
|
954
|
+
# (the preparePath fixture shipped as an empty `set: []`). Now driven
|
|
955
|
+
# by the corpus like every other section, so all ports assert the same
|
|
956
|
+
# separator / blank-segment behaviour.
|
|
957
|
+
spec = _load_test_spec()
|
|
958
|
+
primary = _get_spec(spec, "primary")
|
|
948
959
|
client = ProjectNameSDK.test(None, None)
|
|
949
960
|
utility = client._utility
|
|
950
|
-
ctx = _make_test_full_ctx(client, utility)
|
|
951
|
-
ctx.point = {
|
|
952
|
-
"parts": ["api", "planet", "{id}"],
|
|
953
|
-
"args": {"params": []},
|
|
954
|
-
}
|
|
955
961
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
ctx = _make_test_full_ctx(client, utility)
|
|
963
|
-
ctx.point = {
|
|
964
|
-
"parts": ["items"],
|
|
965
|
-
"args": {"params": []},
|
|
966
|
-
}
|
|
962
|
+
def subject(entry):
|
|
963
|
+
ctxmap = entry.get("ctx")
|
|
964
|
+
if not isinstance(ctxmap, dict):
|
|
965
|
+
ctxmap = {}
|
|
966
|
+
ctx = _make_ctx_from_map(ctxmap, client, utility)
|
|
967
|
+
return utility.prepare_path(ctx), None
|
|
967
968
|
|
|
968
|
-
|
|
969
|
-
assert path == "items"
|
|
969
|
+
_runset(_get_spec(primary, "preparePath", "basic"), subject)
|
|
970
970
|
|
|
971
971
|
def test_prepare_query_basic(self):
|
|
972
972
|
spec = _load_test_spec()
|
|
@@ -84,6 +84,13 @@ def make_options_util(ctx):
|
|
|
84
84
|
"clean": {
|
|
85
85
|
"keys": "key,token,id",
|
|
86
86
|
},
|
|
87
|
+
# Server-variable values for a templated base URL (OpenAPI server
|
|
88
|
+
# variables): {name} placeholders in "base" are substituted from this
|
|
89
|
+
# map at construction. Spec defaults arrive via the generated config;
|
|
90
|
+
# user values override them.
|
|
91
|
+
"server": {
|
|
92
|
+
"`$CHILD`": "",
|
|
93
|
+
},
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
# Preserve system.fetch before merge/validate.
|
|
@@ -95,6 +102,41 @@ def make_options_util(ctx):
|
|
|
95
102
|
validated = {}
|
|
96
103
|
opts = validated
|
|
97
104
|
|
|
105
|
+
# Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
106
|
+
# Every placeholder must resolve to a non-empty value: from
|
|
107
|
+
# options["server"] (user), else the config default. A placeholder that
|
|
108
|
+
# resolves to "" is a construction ERROR in live mode — the URL cannot
|
|
109
|
+
# work — but in test mode substitutes the deterministic value
|
|
110
|
+
# "test-<name>" so offline tests need no configuration.
|
|
111
|
+
base = opts.get("base")
|
|
112
|
+
if isinstance(base, str) and "{" in base:
|
|
113
|
+
import re as _re
|
|
114
|
+
testmode = (
|
|
115
|
+
vs.getpath(opts, "test.active") is True
|
|
116
|
+
or vs.getpath(opts, "feature.test.active") is True
|
|
117
|
+
)
|
|
118
|
+
server = opts.get("server") if isinstance(opts.get("server"), dict) else {}
|
|
119
|
+
sdkname = "SDK"
|
|
120
|
+
if isinstance(config, dict):
|
|
121
|
+
mn = vs.getpath(config, "main.name")
|
|
122
|
+
if isinstance(mn, str) and mn != "":
|
|
123
|
+
sdkname = mn
|
|
124
|
+
|
|
125
|
+
def _sub(m):
|
|
126
|
+
name = m.group(1)
|
|
127
|
+
val = server.get(name)
|
|
128
|
+
val = val if isinstance(val, str) else ""
|
|
129
|
+
if val == "":
|
|
130
|
+
if testmode:
|
|
131
|
+
return "test-" + name
|
|
132
|
+
raise ValueError(
|
|
133
|
+
sdkname + ": the server variable '" + name + "' is required: "
|
|
134
|
+
"the API base URL is '" + base + "' — pass "
|
|
135
|
+
'{"server": {"' + name + '": "..."}} in the SDK options')
|
|
136
|
+
return val
|
|
137
|
+
|
|
138
|
+
opts["base"] = _re.sub(r"\{([A-Za-z0-9_]+)\}", _sub, base)
|
|
139
|
+
|
|
98
140
|
# Restore system.fetch.
|
|
99
141
|
if sys_fetch is not None:
|
|
100
142
|
if isinstance(opts.get("system"), dict):
|
|
@@ -13,14 +13,14 @@ clean:
|
|
|
13
13
|
|
|
14
14
|
# --- Release: publish to RubyGems -----------------------------------------
|
|
15
15
|
# Build the gem and push it to RubyGems, then tag rb/vX.Y.Z. Run headless under
|
|
16
|
-
# the
|
|
16
|
+
# the boru key vault, which injects GEM_HOST_API_KEY + the GitHub token (never on
|
|
17
17
|
# disk or argv):
|
|
18
|
-
#
|
|
19
|
-
#
|
|
18
|
+
# boru vault exec --for=gem=<alias> --for=github=<alias> -- make publish
|
|
19
|
+
# boru `--dry-run` injects a filler token we detect to rehearse (build only, no
|
|
20
20
|
# push/tag). set -e + tag-last: a failed push never leaves a tag behind.
|
|
21
21
|
VERSION := $(shell sed -nE 's/.*\.version *= *"([^"]+)".*/\1/p' *.gemspec | head -1)
|
|
22
22
|
TAG := rb/v$(VERSION)
|
|
23
|
-
|
|
23
|
+
BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
|
|
24
24
|
publish: test
|
|
25
25
|
@if git rev-parse -q --verify "refs/tags/$(TAG)" >/dev/null; then \
|
|
26
26
|
echo "tag $(TAG) already exists — bump the gemspec version first"; exit 1; fi
|
|
@@ -28,8 +28,8 @@ publish: test
|
|
|
28
28
|
token="$${GITHUB_TOKEN:-$$GH_TOKEN}"; \
|
|
29
29
|
rm -f *.gem; \
|
|
30
30
|
gem build *.gemspec; \
|
|
31
|
-
if [ "$$token" = "$(
|
|
32
|
-
echo "[dry-run]
|
|
31
|
+
if [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ] || [ "$$GEM_HOST_API_KEY" = "$(BORU_DRY_RUN_FILLER)" ]; then \
|
|
32
|
+
echo "[dry-run] boru filler token detected: built the gem; would push to RubyGems and tag $(TAG); nothing pushed."; \
|
|
33
33
|
exit 0; \
|
|
34
34
|
fi; \
|
|
35
35
|
gem push *.gem; \
|
|
@@ -4,6 +4,10 @@ require_relative '../utility/struct/voxgig_struct'
|
|
|
4
4
|
require_relative 'base_feature'
|
|
5
5
|
|
|
6
6
|
class ProjectNameTestFeature < ProjectNameBaseFeature
|
|
7
|
+
# The `body.<key>` form of an op's response transform: the mock wraps its
|
|
8
|
+
# payload in <key> so the transform can unwrap it again.
|
|
9
|
+
ENVELOPE_RES_RE = /\A`body\.([^`.]+)`\z/
|
|
10
|
+
|
|
7
11
|
def initialize
|
|
8
12
|
super
|
|
9
13
|
@version = "0.0.1"
|
|
@@ -33,11 +37,30 @@ class ProjectNameTestFeature < ProjectNameBaseFeature
|
|
|
33
37
|
test_self = self
|
|
34
38
|
|
|
35
39
|
test_fetcher = ->(fctx, _fullurl, _fetchdef) {
|
|
40
|
+
# Shape the mock payload the way the real API would, so the op's
|
|
41
|
+
# response transform recovers the entity from it. A point carrying
|
|
42
|
+
# transform.res of `body.item` describes an API that answers
|
|
43
|
+
# {"item" => {...}}; handing back the bare entity means the transform
|
|
44
|
+
# unwraps a property that is not there and the caller gets nil. The mock
|
|
45
|
+
# has to agree with the model, or it only ever simulates APIs whose
|
|
46
|
+
# responses happen to be unwrapped. Mirrors the ts mock.
|
|
47
|
+
envelope = ->(data) {
|
|
48
|
+
point = fctx.point
|
|
49
|
+
next data if data.nil? || !point.is_a?(Hash)
|
|
50
|
+
transform = point["transform"]
|
|
51
|
+
next data unless transform.is_a?(Hash)
|
|
52
|
+
restf = transform["res"]
|
|
53
|
+
next data unless restf.is_a?(String)
|
|
54
|
+
m = ENVELOPE_RES_RE.match(restf)
|
|
55
|
+
m.nil? ? data : { m[1] => data }
|
|
56
|
+
}
|
|
57
|
+
|
|
36
58
|
respond = ->(status, data, extra) {
|
|
59
|
+
payload = envelope.call(data)
|
|
37
60
|
out = {
|
|
38
61
|
"status" => status,
|
|
39
62
|
"statusText" => "OK",
|
|
40
|
-
"json" => -> {
|
|
63
|
+
"json" => -> { payload },
|
|
41
64
|
"body" => "not-used",
|
|
42
65
|
}
|
|
43
66
|
extra&.each { |k, v| out[k] = v }
|