@voxgig/sdkgen 4.5.3 → 4.6.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 +1 -1
- package/dist/action/check.js +15 -0
- package/dist/action/check.js.map +1 -1
- package/dist/cmp/AgentGuide.js +1 -1
- package/dist/cmp/AgentGuide.js.map +1 -1
- package/dist/cmp/AgentGuideContent.d.ts +1 -1
- package/dist/cmp/AgentGuideContent.js +8 -2
- package/dist/cmp/AgentGuideContent.js.map +1 -1
- package/dist/cmp/Feature.js +17 -0
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/cmp/FeatureDocs.d.ts +1 -1
- package/dist/cmp/FeatureDocs.js +6 -1
- package/dist/cmp/FeatureDocs.js.map +1 -1
- package/dist/cmp/ReadmeExplanation.js +3 -1
- package/dist/cmp/ReadmeExplanation.js.map +1 -1
- package/dist/cmp/ReadmeFeatures.js +1 -1
- package/dist/cmp/ReadmeFeatures.js.map +1 -1
- package/dist/cmp/ReadmeRefFeatures.js +1 -1
- package/dist/cmp/ReadmeRefFeatures.js.map +1 -1
- package/dist/helpers/applicability.d.ts +6 -0
- package/dist/helpers/applicability.js +103 -0
- package/dist/helpers/applicability.js.map +1 -0
- package/dist/helpers/collectDeps.js +4 -2
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/serverVars.d.ts +2 -1
- package/dist/helpers/serverVars.js +17 -0
- package/dist/helpers/serverVars.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -2
- package/dist/sdkgen.js +9 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.js +7 -1
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aon +39 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/feature-index.aon +1 -0
- package/project/.sdk/model/feature/secrets.aon +118 -0
- package/project/.sdk/model/target/ts.aon +8 -1
- package/project/.sdk/src/cmp/c/Config_c.ts +5 -1
- package/project/.sdk/src/cmp/cpp/Config_cpp.ts +5 -1
- package/project/.sdk/src/cmp/csharp/Config_csharp.ts +5 -1
- package/project/.sdk/src/cmp/dart/Config_dart.ts +5 -1
- package/project/.sdk/src/cmp/elixir/Config_elixir.ts +5 -1
- package/project/.sdk/src/cmp/elixir/Main_elixir.ts +5 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +5 -1
- package/project/.sdk/src/cmp/go/Main_go.ts +6 -2
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +16 -3
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +16 -3
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +28 -4
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +43 -10
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +5 -5
- package/project/.sdk/src/cmp/java/Config_java.ts +22 -1
- package/project/.sdk/src/cmp/java/Main_java.ts +5 -1
- package/project/.sdk/src/cmp/java/ReadmeQuick_java.ts +17 -3
- package/project/.sdk/src/cmp/java/ReadmeTopQuick_java.ts +17 -3
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +23 -4
- package/project/.sdk/src/cmp/java/TestEntity_java.ts +29 -4
- package/project/.sdk/src/cmp/js/Config_js.ts +5 -1
- package/project/.sdk/src/cmp/js/Main_js.ts +5 -1
- package/project/.sdk/src/cmp/js/Package_js.ts +4 -1
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +5 -1
- package/project/.sdk/src/cmp/lean/Config_lean.ts +5 -1
- package/project/.sdk/src/cmp/lua/Config_lua.ts +5 -1
- package/project/.sdk/src/cmp/lua/Main_lua.ts +5 -1
- package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -1
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +5 -1
- package/project/.sdk/src/cmp/perl/Main_perl.ts +5 -1
- package/project/.sdk/src/cmp/php/Config_php.ts +5 -1
- package/project/.sdk/src/cmp/php/Main_php.ts +5 -1
- package/project/.sdk/src/cmp/py/Config_py.ts +5 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +5 -1
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +16 -3
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +16 -3
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +24 -5
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +23 -3
- package/project/.sdk/src/cmp/rb/Config_rb.ts +5 -1
- package/project/.sdk/src/cmp/rb/Main_rb.ts +5 -1
- package/project/.sdk/src/cmp/rust/Config_rust.ts +5 -1
- package/project/.sdk/src/cmp/rust/Main_rust.ts +5 -1
- package/project/.sdk/src/cmp/scala/Config_scala.ts +5 -1
- package/project/.sdk/src/cmp/scala/Main_scala.ts +5 -1
- package/project/.sdk/src/cmp/swift/Config_swift.ts +5 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +5 -1
- package/project/.sdk/src/cmp/ts/Main_ts.ts +57 -1
- package/project/.sdk/src/cmp/ts/Package_ts.ts +4 -1
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +15 -3
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +18 -5
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +19 -5
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +67 -7
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +27 -4
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +9 -2
- package/project/.sdk/src/cmp/ts/fragment/Entity.test.fragment.ts +9 -2
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +7 -0
- package/project/.sdk/src/cmp/zig/Config_zig.ts +5 -1
- package/project/.sdk/tm/c/utility/make_options.c +22 -0
- package/project/.sdk/tm/clojure/src/sdk/core.clj +18 -1
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +23 -0
- package/project/.sdk/tm/csharp/test/CustomUtilityTest.cs +15 -0
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +23 -0
- package/project/.sdk/tm/dart/lib/utility/MakeOptionsUtility.dart +22 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +19 -0
- package/project/.sdk/tm/go/core/context.go +1 -1
- package/project/.sdk/tm/go/feature/cost_feature.go +1 -1
- package/project/.sdk/tm/go/feature/paging_feature.go +5 -5
- package/project/.sdk/tm/go/feature/test_feature.go +12 -5
- package/project/.sdk/tm/go/test/custom_utility_test.go +15 -0
- package/project/.sdk/tm/go/test/feature_corpus_test.go +7 -0
- package/project/.sdk/tm/go/test/runner_test.go +46 -0
- package/project/.sdk/tm/go/test/struct_runner_test.go +7 -7
- package/project/.sdk/tm/go/test/struct_utility_test.go +63 -27
- package/project/.sdk/tm/go/utility/fetcher.go +2 -2
- package/project/.sdk/tm/go/utility/make_options.go +24 -5
- package/project/.sdk/tm/go/utility/make_point.go +1 -1
- package/project/.sdk/tm/go/utility/make_spec.go +17 -1
- package/project/.sdk/tm/go/utility/prepare_auth.go +1 -1
- package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +370 -307
- package/project/.sdk/tm/go/utility/transform_request.go +29 -1
- package/project/.sdk/tm/go/utility/transform_response.go +20 -1
- package/project/.sdk/tm/java/test/CustomUtilityTest.java +10 -0
- package/project/.sdk/tm/java/test/FeatureCorpusTest.java +7 -0
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +6 -0
- package/project/.sdk/tm/java/test/RunnerSupport.java +43 -0
- package/project/.sdk/tm/java/utility/MakeOptions.java +84 -1
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +24 -0
- package/project/.sdk/tm/js/src/utility/StructUtility.js +2076 -1837
- package/project/.sdk/tm/js/test/feature/Corpus.test.js +9 -0
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +21 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +12 -1
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +11 -0
- package/project/.sdk/tm/perl/utility/make_options.pm +18 -0
- package/project/.sdk/tm/php/test/FeatureCorpusTest.php +10 -1
- package/project/.sdk/tm/php/utility/MakeOptions.php +24 -0
- package/project/.sdk/tm/py/pkg/utility/make_options.py +20 -0
- package/project/.sdk/tm/py/test/runner.py +32 -0
- package/project/.sdk/tm/py/test/test_feature_corpus.py +10 -1
- package/project/.sdk/tm/rb/test/feature_corpus_test.rb +9 -1
- package/project/.sdk/tm/rb/utility/make_options.rb +17 -0
- package/project/.sdk/tm/rust/utility/make_options.rs +25 -0
- package/project/.sdk/tm/scala/utility/Make.scala +17 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +21 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +419 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Providers.ts +1221 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +381 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sigv4.ts +151 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +42 -0
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +18 -0
- package/project/.sdk/tm/ts/src/utility/StructUtility.ts +1321 -710
- package/project/.sdk/tm/ts/test/feature/Corpus.test.ts +9 -0
- package/project/.sdk/tm/ts/test/feature/secrets/Secrets.test.ts +764 -0
- package/project/.sdk/tm/ts/test/omni.test.ts +84 -0
- package/project/.sdk/tm/ts/test/omni.ts +86 -0
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +6 -2
- package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +2 -2
- package/project/.sdk/tm/ts/test/utility.ts +122 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +692 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +238 -0
- package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +188 -0
- package/project/.sdk/tm/ts/test/vendor/omni/index.ts +38 -0
- package/project/.sdk/tm/zig/core/utility.zig +23 -0
- package/project/sdkgen-package.json +2 -1
- package/src/action/check.ts +18 -0
- package/src/cmp/AgentGuide.ts +1 -1
- package/src/cmp/AgentGuideContent.ts +9 -2
- package/src/cmp/Feature.ts +19 -0
- package/src/cmp/FeatureDocs.ts +7 -1
- package/src/cmp/ReadmeExplanation.ts +4 -1
- package/src/cmp/ReadmeFeatures.ts +1 -1
- package/src/cmp/ReadmeRefFeatures.ts +1 -1
- package/src/helpers/applicability.ts +123 -0
- package/src/helpers/collectDeps.ts +5 -1
- package/src/helpers/serverVars.ts +19 -0
- package/src/sdkgen.ts +9 -1
- package/src/utility.ts +10 -1
- package/project/.sdk/tm/ts/test/runner.ts +0 -425
|
@@ -24,9 +24,37 @@ func transformRequestUtil(ctx *core.Context) any {
|
|
|
24
24
|
return ctx.Reqdata
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
// Transform gained an error return in struct go 0.1.3. The TS reference
|
|
28
|
+
// wraps this call in try/catch and returns makeError(ctx, err) — but ts's
|
|
29
|
+
// makeError THROWS unless ctrl.throw is false, so that `return` is only
|
|
30
|
+
// ever reached on the non-throwing path. go's makeError cannot throw; it
|
|
31
|
+
// returns the error instead. Handing that back as the `any` this seam
|
|
32
|
+
// returns would make it the request BODY, so makeSpec re-raises it (see
|
|
33
|
+
// the abort there). On the ctrl.throw-false path makeError yields
|
|
34
|
+
// result.Resdata and this returns a real value, as ts does.
|
|
35
|
+
reqdata, terr := vs.Transform(map[string]any{
|
|
28
36
|
"reqdata": ctx.Reqdata,
|
|
29
37
|
}, reqform)
|
|
30
38
|
|
|
39
|
+
if terr != nil {
|
|
40
|
+
// Only the NON-throwing path goes through makeError here. With
|
|
41
|
+
// ctrl.throw false, ts's makeError returns result.resdata and the
|
|
42
|
+
// pipeline continues with it as the body; mirror that.
|
|
43
|
+
//
|
|
44
|
+
// On the throwing path the error is handed back raw, for makeSpec to
|
|
45
|
+
// re-raise and the operation to process once. Calling makeError here
|
|
46
|
+
// as well would report the same failure TWICE — it fires the
|
|
47
|
+
// PreUnexpected hook, and the operation fires it again when it
|
|
48
|
+
// handles what makeSpec re-raised. The built-in observability
|
|
49
|
+
// features happen to dedupe on a per-context marker, but a
|
|
50
|
+
// project-supplied feature may legitimately count or log on every
|
|
51
|
+
// dispatch, and ts dispatches once.
|
|
52
|
+
if ctx.Ctrl != nil && ctx.Ctrl.Throw != nil && !*ctx.Ctrl.Throw {
|
|
53
|
+
out, _ := makeErrorUtil(ctx, terr)
|
|
54
|
+
return out
|
|
55
|
+
}
|
|
56
|
+
return terr
|
|
57
|
+
}
|
|
58
|
+
|
|
31
59
|
return reqdata
|
|
32
60
|
}
|
|
@@ -29,7 +29,12 @@ func transformResponseUtil(ctx *core.Context) any {
|
|
|
29
29
|
return nil
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// Transform gained an error return in struct go 0.1.3. Both callers
|
|
33
|
+
// (makeResponse, makeResult) DISCARD this function's return value, so an
|
|
34
|
+
// error handed back that way would vanish. The convention they do honour
|
|
35
|
+
// is result.Err — makeResponse sets result.Ok only when it is nil, and
|
|
36
|
+
// GraphqlErrors reports the same way — so report there.
|
|
37
|
+
resdata, terr := vs.Transform(map[string]any{
|
|
33
38
|
"ok": result.Ok,
|
|
34
39
|
"status": result.Status,
|
|
35
40
|
"statusText": result.StatusText,
|
|
@@ -40,6 +45,20 @@ func transformResponseUtil(ctx *core.Context) any {
|
|
|
40
45
|
"resmatch": result.Resmatch,
|
|
41
46
|
}, resform)
|
|
42
47
|
|
|
48
|
+
if terr != nil {
|
|
49
|
+
// Ok must be cleared as well as Err. This runs from BOTH makeResponse
|
|
50
|
+
// and makeResult, and only the makeResult call actually reaches the
|
|
51
|
+
// transform: resultBasic never sets Ok, so the makeResponse call
|
|
52
|
+
// returns at the !result.Ok guard above, and makeResponse then sets
|
|
53
|
+
// Ok true. By the time the transform really runs, Ok is already true —
|
|
54
|
+
// and doneUtil returns result.Resdata whenever Ok is true, without
|
|
55
|
+
// ever consulting Err. Recording only the error would leave a failed
|
|
56
|
+
// response transform resolving successfully.
|
|
57
|
+
result.Err = ctx.MakeError("resform", "resform: "+terr.Error())
|
|
58
|
+
result.Ok = false
|
|
59
|
+
return nil
|
|
60
|
+
}
|
|
61
|
+
|
|
43
62
|
result.Resdata = resdata
|
|
44
63
|
return resdata
|
|
45
64
|
}
|
|
@@ -86,7 +86,12 @@ public class CustomUtilityTest {
|
|
|
86
86
|
// transport: 'base' - it REPLACES the transport by design - so a client in
|
|
87
87
|
// test mode would shadow the scripted fetcher and this would assert
|
|
88
88
|
// nothing.
|
|
89
|
+
// "test" is the OPTION, not the `test` FEATURE: it says "this client is
|
|
90
|
+
// not live", so a REQUIRED OpenAPI server variable resolves to a
|
|
91
|
+
// deterministic test-<name> instead of failing construction. It installs
|
|
92
|
+
// no transport, so the scripted fetcher still stands.
|
|
89
93
|
ProjectNameSDK client = new ProjectNameSDK(fhMap(
|
|
94
|
+
"test", fhMap("active", true),
|
|
90
95
|
"utility", fhMap("fetcher", scripted)));
|
|
91
96
|
|
|
92
97
|
Utility u = client.getUtility();
|
|
@@ -106,7 +111,12 @@ public class CustomUtilityTest {
|
|
|
106
111
|
// halves cannot be satisfied by a switch that also swallows extras.
|
|
107
112
|
@Test
|
|
108
113
|
public void anUnknownKeyIsStillAttached() {
|
|
114
|
+
// "test" is the OPTION, not the `test` FEATURE: it says "this client is
|
|
115
|
+
// not live", so a REQUIRED OpenAPI server variable resolves to a
|
|
116
|
+
// deterministic test-<name> instead of failing construction. It installs
|
|
117
|
+
// no transport, so the scripted fetcher still stands.
|
|
109
118
|
ProjectNameSDK client = new ProjectNameSDK(fhMap(
|
|
119
|
+
"test", fhMap("active", true),
|
|
110
120
|
"utility", fhMap("notAUtilityMember", (Supplier<String>) () -> "EXTRA")));
|
|
111
121
|
assertTrue(client.getUtility().custom.containsKey("notAUtilityMember"),
|
|
112
122
|
"an unknown utility key was dropped instead of kept in custom");
|
|
@@ -128,7 +128,14 @@ public class FeatureCorpusTest {
|
|
|
128
128
|
Map<String, Object> utility = new LinkedHashMap<>();
|
|
129
129
|
utility.put("fetcher", scriptedFetcher(kase.get("res")));
|
|
130
130
|
|
|
131
|
+
// "test" is the OPTION, not the `test` FEATURE: it says "this client is
|
|
132
|
+
// not live", so a REQUIRED OpenAPI server variable resolves to a
|
|
133
|
+
// deterministic test-<name> instead of failing construction. It installs
|
|
134
|
+
// no transport, so the scripted fetcher still stands.
|
|
131
135
|
Map<String, Object> opts = new LinkedHashMap<>();
|
|
136
|
+
Map<String, Object> testopt = new LinkedHashMap<>();
|
|
137
|
+
testopt.put("active", true);
|
|
138
|
+
opts.put("test", testopt);
|
|
132
139
|
opts.put("utility", utility);
|
|
133
140
|
if (kase.get("feature") != null) {
|
|
134
141
|
opts.put("feature", kase.get("feature"));
|
|
@@ -271,7 +271,10 @@ public class PrimaryUtilityTest {
|
|
|
271
271
|
@Test
|
|
272
272
|
public void fetcherLive() {
|
|
273
273
|
final List<Map<String, Object>> calls = new ArrayList<>();
|
|
274
|
+
// Concrete base: a live construction must satisfy any server variables a
|
|
275
|
+
// templated base URL declares; a literal base sidesteps the requirement.
|
|
274
276
|
ProjectNameSDK liveClient = new ProjectNameSDK(fhMap(
|
|
277
|
+
"base", "http://localhost:8080",
|
|
275
278
|
"system", fhMap(
|
|
276
279
|
"fetch", (BiFunction<String, Map<String, Object>, Map<String, Object>>)
|
|
277
280
|
(url, fetchdef) -> {
|
|
@@ -296,7 +299,10 @@ public class PrimaryUtilityTest {
|
|
|
296
299
|
public void fetcherBlockedTestMode() {
|
|
297
300
|
// Create a live SDK then set mode to test (not using testSDK, which
|
|
298
301
|
// installs the test feature).
|
|
302
|
+
// Concrete base: a live construction must satisfy any server variables a
|
|
303
|
+
// templated base URL declares; a literal base sidesteps the requirement.
|
|
299
304
|
ProjectNameSDK blockedClient = new ProjectNameSDK(fhMap(
|
|
305
|
+
"base", "http://localhost:8080",
|
|
300
306
|
"system", fhMap(
|
|
301
307
|
"fetch", (BiFunction<String, Map<String, Object>, Map<String, Object>>)
|
|
302
308
|
(url, fetchdef) -> new LinkedHashMap<>())));
|
|
@@ -172,6 +172,49 @@ public final class RunnerSupport {
|
|
|
172
172
|
return null;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
// liveClientOptions returns the extra SDK options every LIVE client is
|
|
176
|
+
// constructed with, from sdk-test-control.json `test.client.options`.
|
|
177
|
+
//
|
|
178
|
+
// The generated live client knows two things: the base URL (from the
|
|
179
|
+
// spec) and the credential (from the environment). Everything else about
|
|
180
|
+
// how a particular API wants to be talked to - which features to switch
|
|
181
|
+
// on, and with what settings - is a property of THAT API, known to the
|
|
182
|
+
// project and to nothing in the toolchain.
|
|
183
|
+
//
|
|
184
|
+
// Merged UNDER the generated fields, so the suite's own base/apikey/server
|
|
185
|
+
// values win: this ADDS to the live client, it does not redirect it.
|
|
186
|
+
//
|
|
187
|
+
// That contract is enforced HERE rather than left to each merge site: the
|
|
188
|
+
// generated map only names a field when the model calls for one, so a
|
|
189
|
+
// "base" in this block would face no competing value and would silently
|
|
190
|
+
// redirect the whole suite - credential included - to another host.
|
|
191
|
+
private static final List<String> LIVE_RESERVED = List.of(
|
|
192
|
+
"base", "prefix", "suffix", "server", "apikey", "secret");
|
|
193
|
+
|
|
194
|
+
public static Map<String, Object> liveClientOptions() {
|
|
195
|
+
Map<String, Object> ctrl = loadTestControl();
|
|
196
|
+
Map<String, Object> test = Helpers.toMapAny(ctrl.get("test"));
|
|
197
|
+
if (test == null) {
|
|
198
|
+
return new LinkedHashMap<>();
|
|
199
|
+
}
|
|
200
|
+
Map<String, Object> client = Helpers.toMapAny(test.get("client"));
|
|
201
|
+
if (client == null) {
|
|
202
|
+
return new LinkedHashMap<>();
|
|
203
|
+
}
|
|
204
|
+
Map<String, Object> opts = Helpers.toMapAny(client.get("options"));
|
|
205
|
+
if (opts == null) {
|
|
206
|
+
return new LinkedHashMap<>();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
Map<String, Object> out = new LinkedHashMap<>();
|
|
210
|
+
for (Map.Entry<String, Object> e : opts.entrySet()) {
|
|
211
|
+
if (!LIVE_RESERVED.contains(e.getKey())) {
|
|
212
|
+
out.put(e.getKey(), e.getValue());
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
|
|
175
218
|
// liveDelayMs returns the configured per-test live delay in ms; default 500.
|
|
176
219
|
public static int liveDelayMs() {
|
|
177
220
|
Map<String, Object> ctrl = loadTestControl();
|
|
@@ -4,6 +4,8 @@ import java.util.ArrayList;
|
|
|
4
4
|
import java.util.LinkedHashMap;
|
|
5
5
|
import java.util.List;
|
|
6
6
|
import java.util.Map;
|
|
7
|
+
import java.util.regex.Matcher;
|
|
8
|
+
import java.util.regex.Pattern;
|
|
7
9
|
|
|
8
10
|
import JAVAPACKAGE.core.Context;
|
|
9
11
|
import JAVAPACKAGE.core.Helpers;
|
|
@@ -12,6 +14,9 @@ import JAVAPACKAGE.utility.struct.Struct;
|
|
|
12
14
|
@SuppressWarnings({"unchecked"})
|
|
13
15
|
final class MakeOptions {
|
|
14
16
|
|
|
17
|
+
// {name} placeholders in a templated server URL (OpenAPI server variables).
|
|
18
|
+
private static final Pattern SERVER_VAR = Pattern.compile("\\{([A-Za-z0-9_]+)\\}");
|
|
19
|
+
|
|
15
20
|
private MakeOptions() {}
|
|
16
21
|
|
|
17
22
|
static Map<String, Object> makeOptions(Context ctx) {
|
|
@@ -36,8 +41,24 @@ final class MakeOptions {
|
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
// `auth: null` is the documented way to disable auth outright, and
|
|
45
|
+
// PrepareAuth honours it before it ever reads the apikey. It cannot
|
|
46
|
+
// survive validate: depending on the struct port a stored null is either
|
|
47
|
+
// REPLACED by the optspec default - transmitting the credential the
|
|
48
|
+
// caller withheld - or REJECTED outright. Withhold the key for validate,
|
|
49
|
+
// then put the null back. Same fix as ts/js/go makeOptions.
|
|
50
|
+
//
|
|
51
|
+
// Suppliedness cannot be recovered after validate, hence here, and it
|
|
52
|
+
// must tell an ABSENT auth from a present null: containsKey rather than
|
|
53
|
+
// a get() null check, which cannot distinguish them.
|
|
54
|
+
boolean authSuppressed = options.containsKey("auth") && null == options.get("auth");
|
|
55
|
+
|
|
39
56
|
Map<String, Object> opts = (Map<String, Object>) Struct.clone(options);
|
|
40
57
|
|
|
58
|
+
if (authSuppressed) {
|
|
59
|
+
opts.remove("auth");
|
|
60
|
+
}
|
|
61
|
+
|
|
41
62
|
// Feature add-order. options.feature may be given as an ordered LIST of
|
|
42
63
|
// { name, active, ...opts } entries (the list position IS the order in
|
|
43
64
|
// which features are added), or as a { name: {opts} } map. Normalize a
|
|
@@ -91,7 +112,12 @@ final class MakeOptions {
|
|
|
91
112
|
+ "\"utility\": {},"
|
|
92
113
|
+ "\"system\": {},"
|
|
93
114
|
+ "\"test\": { \"active\": false, \"entity\": { \"`$OPEN`\": true } },"
|
|
94
|
-
+ "\"clean\": { \"keys\": \"key,token,id\" }"
|
|
115
|
+
+ "\"clean\": { \"keys\": \"key,token,id\" },"
|
|
116
|
+
// Server-variable values for a templated base URL (OpenAPI server
|
|
117
|
+
// variables): {name} placeholders in `base` are substituted from
|
|
118
|
+
// this map at construction. Spec defaults arrive via the generated
|
|
119
|
+
// Config; user values override them.
|
|
120
|
+
+ "\"server\": { \"`$CHILD`\": \"\" }"
|
|
95
121
|
+ "}");
|
|
96
122
|
|
|
97
123
|
// Preserve system.fetch before merge/validate.
|
|
@@ -115,6 +141,11 @@ final class MakeOptions {
|
|
|
115
141
|
Object validated = Struct.validate(merged, optspec, vopts);
|
|
116
142
|
opts = (Map<String, Object>) validated;
|
|
117
143
|
|
|
144
|
+
// Restore the suppression the optspec default would otherwise erase.
|
|
145
|
+
if (authSuppressed) {
|
|
146
|
+
opts.put("auth", null);
|
|
147
|
+
}
|
|
148
|
+
|
|
118
149
|
// Restore system.fetch.
|
|
119
150
|
if (sysFetch != null) {
|
|
120
151
|
Map<String, Object> sys = Helpers.toMapAny(opts.get("system"));
|
|
@@ -128,6 +159,58 @@ final class MakeOptions {
|
|
|
128
159
|
}
|
|
129
160
|
}
|
|
130
161
|
|
|
162
|
+
// Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
163
|
+
//
|
|
164
|
+
// Every placeholder must resolve to a non-empty value: from
|
|
165
|
+
// options["server"] (user), else the Config default. A placeholder that
|
|
166
|
+
// resolves to "" is a construction ERROR in live mode - the URL cannot
|
|
167
|
+
// work - but in test mode substitutes the deterministic value
|
|
168
|
+
// `test-<name>` so offline tests need no configuration.
|
|
169
|
+
Object baseObj = opts.get("base");
|
|
170
|
+
if (baseObj instanceof String && ((String) baseObj).indexOf('{') >= 0) {
|
|
171
|
+
String base = (String) baseObj;
|
|
172
|
+
|
|
173
|
+
boolean testmode =
|
|
174
|
+
Boolean.TRUE.equals(Struct.getpath(opts, List.of("test", "active")))
|
|
175
|
+
|| Boolean.TRUE.equals(
|
|
176
|
+
Struct.getpath(opts, List.of("feature", "test", "active")));
|
|
177
|
+
|
|
178
|
+
Map<String, Object> server = Helpers.toMapAny(opts.get("server"));
|
|
179
|
+
|
|
180
|
+
Matcher m = SERVER_VAR.matcher(base);
|
|
181
|
+
StringBuilder resolved = new StringBuilder();
|
|
182
|
+
int at = 0;
|
|
183
|
+
while (m.find()) {
|
|
184
|
+
String name = m.group(1);
|
|
185
|
+
Object raw = server == null ? null : server.get(name);
|
|
186
|
+
String val = raw instanceof String ? (String) raw : "";
|
|
187
|
+
|
|
188
|
+
if ("".equals(val)) {
|
|
189
|
+
if (testmode) {
|
|
190
|
+
val = "test-" + name;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
String sdkname = "SDK";
|
|
194
|
+
Object mainName = Struct.getpath(config, List.of("main", "name"));
|
|
195
|
+
if (mainName instanceof String) {
|
|
196
|
+
sdkname = (String) mainName;
|
|
197
|
+
}
|
|
198
|
+
throw new IllegalArgumentException(
|
|
199
|
+
sdkname + ": the server variable '" + name + "' is required: "
|
|
200
|
+
+ "the API base URL is '" + base + "' - pass "
|
|
201
|
+
+ "options.put(\"server\", Map.of(\"" + name + "\", \"...\")) "
|
|
202
|
+
+ "in the SDK options");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
resolved.append(base, at, m.start()).append(val);
|
|
207
|
+
at = m.end();
|
|
208
|
+
}
|
|
209
|
+
resolved.append(base.substring(at));
|
|
210
|
+
|
|
211
|
+
opts.put("base", resolved.toString());
|
|
212
|
+
}
|
|
213
|
+
|
|
131
214
|
// Derived clean config.
|
|
132
215
|
String cleanKeys = "key,token,id";
|
|
133
216
|
Object ck = Struct.getpath(opts, List.of("clean", "keys"));
|
|
@@ -9,8 +9,27 @@ function makeOptions(ctx) {
|
|
|
9
9
|
const validate = struct.validate
|
|
10
10
|
const escre = struct.escre
|
|
11
11
|
|
|
12
|
+
// `auth: null` is the documented way to disable auth outright, and
|
|
13
|
+
// prepareAuth honours it before it ever reads the apikey. But it cannot
|
|
14
|
+
// survive validate: this target's struct rejects a stored null outright
|
|
15
|
+
// ("Expected field auth to be map, but found no value"), so passing it
|
|
16
|
+
// through turns the documented suppression into a CONSTRUCTION ERROR.
|
|
17
|
+
//
|
|
18
|
+
// Withhold the key for validate, then put the null back. Deleting rather
|
|
19
|
+
// than leaving it is what avoids the throw; restoring it afterwards is
|
|
20
|
+
// what stops the optspec's `auth` default from taking its place, which
|
|
21
|
+
// would transmit the credential the caller asked to withhold.
|
|
22
|
+
//
|
|
23
|
+
// Suppliedness cannot be recovered after validate, hence here. `null ===`
|
|
24
|
+
// rather than `null ==`, so an OMITTED auth is not read as a suppression.
|
|
25
|
+
const authsuppressed = null === (options || {}).auth
|
|
26
|
+
|
|
12
27
|
let opts = { ...(options || {}) }
|
|
13
28
|
|
|
29
|
+
if (authsuppressed) {
|
|
30
|
+
delete opts.auth
|
|
31
|
+
}
|
|
32
|
+
|
|
14
33
|
// Feature add-order. `options.feature` may be given as an ordered ARRAY of
|
|
15
34
|
// { name, active, ...opts } entries (the array position IS the order in
|
|
16
35
|
// which features are added), or as a { name: {opts} } map. Normalize an
|
|
@@ -108,6 +127,11 @@ function makeOptions(ctx) {
|
|
|
108
127
|
|
|
109
128
|
opts = validate(opts, optspec)
|
|
110
129
|
|
|
130
|
+
// Restore the suppression the optspec default would otherwise erase.
|
|
131
|
+
if (authsuppressed) {
|
|
132
|
+
opts.auth = null
|
|
133
|
+
}
|
|
134
|
+
|
|
111
135
|
// Resolve a templated base URL (e.g. https://{tenant_id}.hanko.io).
|
|
112
136
|
// Every placeholder must resolve to a non-empty value: from
|
|
113
137
|
// options.server (user), else the Config default. A placeholder that
|