@voxgig/sdkgen 4.5.3 → 4.7.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 +22 -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/cmp/TestControl.d.ts +4 -0
- package/dist/cmp/TestControl.js +51 -0
- package/dist/cmp/TestControl.js.map +1 -0
- 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/featureSource.d.ts +3 -1
- package/dist/helpers/featureSource.js +105 -0
- package/dist/helpers/featureSource.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 +5 -3
- package/dist/sdkgen.js +16 -4
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utility.d.ts +2 -1
- package/dist/utility.js +59 -1
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aon +97 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/feature-index.aon +1 -0
- package/project/.sdk/model/feature/secrets.aon +200 -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/cpp/Main_cpp.ts +2 -1
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +5 -1
- package/project/.sdk/src/cmp/csharp/Config_csharp.ts +5 -1
- package/project/.sdk/src/cmp/csharp/Main_csharp.ts +2 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +30 -6
- package/project/.sdk/src/cmp/csharp/TestEntity_csharp.ts +29 -5
- package/project/.sdk/src/cmp/csharp/Test_csharp.ts +5 -1
- package/project/.sdk/src/cmp/dart/Config_dart.ts +5 -1
- package/project/.sdk/src/cmp/dart/Main_dart.ts +2 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +23 -6
- package/project/.sdk/src/cmp/dart/TestEntity_dart.ts +28 -7
- package/project/.sdk/src/cmp/dart/Test_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 +8 -3
- 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/Test_go.ts +5 -1
- 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 +7 -2
- 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/java/Test_java.ts +5 -1
- package/project/.sdk/src/cmp/js/Config_js.ts +5 -1
- package/project/.sdk/src/cmp/js/Main_js.ts +7 -2
- package/project/.sdk/src/cmp/js/Package_js.ts +4 -1
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +30 -5
- package/project/.sdk/src/cmp/js/TestEntity_js.ts +35 -5
- package/project/.sdk/src/cmp/js/Test_js.ts +5 -1
- package/project/.sdk/src/cmp/js/fragment/Direct.test.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/Entity.test.fragment.js +7 -1
- package/project/.sdk/src/cmp/kotlin/Config_kotlin.ts +5 -1
- package/project/.sdk/src/cmp/kotlin/Main_kotlin.ts +2 -1
- package/project/.sdk/src/cmp/kotlin/Test_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 +7 -2
- package/project/.sdk/src/cmp/lua/Package_lua.ts +4 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +28 -4
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +24 -4
- package/project/.sdk/src/cmp/lua/Test_lua.ts +5 -1
- package/project/.sdk/src/cmp/ocaml/Config_ocaml.ts +5 -1
- package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +1 -0
- package/project/.sdk/src/cmp/perl/Main_perl.ts +7 -2
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +25 -4
- package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +24 -4
- package/project/.sdk/src/cmp/perl/Test_perl.ts +5 -1
- package/project/.sdk/src/cmp/perl/utility_perl.ts +10 -0
- package/project/.sdk/src/cmp/php/Config_php.ts +5 -1
- package/project/.sdk/src/cmp/php/Main_php.ts +7 -2
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +24 -5
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +28 -4
- package/project/.sdk/src/cmp/php/Test_php.ts +5 -1
- package/project/.sdk/src/cmp/py/Config_py.ts +5 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +7 -2
- 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/py/Test_py.ts +5 -1
- package/project/.sdk/src/cmp/rb/Config_rb.ts +5 -1
- package/project/.sdk/src/cmp/rb/Main_rb.ts +7 -2
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +24 -5
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +24 -4
- package/project/.sdk/src/cmp/rb/Test_rb.ts +5 -1
- package/project/.sdk/src/cmp/rb/utility_rb.ts +3 -1
- package/project/.sdk/src/cmp/rust/Config_rust.ts +5 -1
- package/project/.sdk/src/cmp/rust/Main_rust.ts +7 -2
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +31 -4
- package/project/.sdk/src/cmp/rust/TestEntity_rust.ts +37 -4
- package/project/.sdk/src/cmp/rust/Test_rust.ts +5 -1
- package/project/.sdk/src/cmp/scala/Config_scala.ts +5 -1
- package/project/.sdk/src/cmp/scala/Main_scala.ts +7 -2
- package/project/.sdk/src/cmp/scala/Test_scala.ts +5 -1
- package/project/.sdk/src/cmp/swift/Config_swift.ts +5 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +55 -9
- package/project/.sdk/src/cmp/ts/Main_ts.ts +67 -3
- 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 +75 -8
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +36 -5
- package/project/.sdk/src/cmp/ts/Test_ts.ts +5 -1
- 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/test/Runner.cs +45 -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/dart/test/utility.dart +39 -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/js/test/sdk-test-control.json +19 -0
- package/project/.sdk/tm/js/test/utility.js +91 -1
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +21 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +12 -1
- package/project/.sdk/tm/lua/test/runner.lua +40 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +11 -0
- package/project/.sdk/tm/ocaml/test/harness.ml +14 -4
- package/project/.sdk/tm/perl/t/runner.pm +30 -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/test/Runner.php +36 -0
- 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/test/runner.rb +25 -0
- package/project/.sdk/tm/rb/utility/make_options.rb +17 -0
- package/project/.sdk/tm/rust/tests/common/mod.rs +32 -0
- package/project/.sdk/tm/rust/utility/make_options.rs +26 -1
- 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/Sekreto.ts +387 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sigv4.ts +175 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +51 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/Registry.ts +90 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +48 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/aws.ts +219 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/azuresecrets.ts +144 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/boru.ts +113 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/doppler.ts +77 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +51 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +31 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +54 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/gcpsecrets.ts +118 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/hashicorp.ts +159 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/http.ts +66 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/infisical.ts +107 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +33 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/onepassword.ts +120 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +176 -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 +694 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +244 -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 +24 -1
- 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 +24 -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/cmp/TestControl.ts +64 -0
- package/src/helpers/applicability.ts +123 -0
- package/src/helpers/collectDeps.ts +5 -1
- package/src/helpers/featureSource.ts +130 -0
- package/src/helpers/serverVars.ts +19 -0
- package/src/sdkgen.ts +16 -1
- package/src/utility.ts +71 -1
- package/project/.sdk/tm/ts/test/runner.ts +0 -425
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
rawStringLiteral,
|
|
17
17
|
resolveAuthPrefix,
|
|
18
18
|
serverVariables,
|
|
19
|
+
targetFeatures,
|
|
19
20
|
} from '@voxgig/sdkgen'
|
|
20
21
|
|
|
21
22
|
|
|
@@ -40,7 +41,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
40
41
|
const model: Model = ctx$.model
|
|
41
42
|
|
|
42
43
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
43
|
-
|
|
44
|
+
// Gated by the applicability tags, so this target never imports or
|
|
45
|
+
// registers a feature it has no source for. One rule, one place:
|
|
46
|
+
// helpers/applicability.
|
|
47
|
+
const feature = targetFeatures(model, target)
|
|
44
48
|
|
|
45
49
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
46
50
|
|
|
@@ -4,6 +4,8 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
|
+
targetFeatures,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
7
9
|
} from '@voxgig/sdkgen'
|
|
8
10
|
|
|
9
11
|
|
|
@@ -31,7 +33,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
31
33
|
const { model } = props.ctx$
|
|
32
34
|
|
|
33
35
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
34
|
-
|
|
36
|
+
// Gated by the applicability tags, so this target never imports or
|
|
37
|
+
// registers a feature it has no source for. One rule, one place:
|
|
38
|
+
// helpers/applicability.
|
|
39
|
+
const feature = targetFeatures(model, target)
|
|
35
40
|
|
|
36
41
|
Package({ target })
|
|
37
42
|
|
|
@@ -40,7 +45,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
40
45
|
// Copy tm/php files with replacements
|
|
41
46
|
Copy({
|
|
42
47
|
from: 'tm/' + target.name,
|
|
43
|
-
exclude: [/src
|
|
48
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
44
49
|
replace: {
|
|
45
50
|
...props.ctx$.stdrep,
|
|
46
51
|
}
|
|
@@ -11,9 +11,13 @@ import {
|
|
|
11
11
|
File,
|
|
12
12
|
cmp,
|
|
13
13
|
snakify,
|
|
14
|
-
isAuthActive, envName, envToken
|
|
14
|
+
isAuthActive, envName, envToken,
|
|
15
|
+
serverVarEnv,
|
|
16
|
+
serverVariables
|
|
15
17
|
} from '@voxgig/sdkgen'
|
|
16
18
|
|
|
19
|
+
import { formatPhpValue } from './utility_php'
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
function normalizePathParams(
|
|
19
23
|
parts: string[],
|
|
@@ -64,12 +68,25 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
64
68
|
|
|
65
69
|
const authActive = isAuthActive(model)
|
|
66
70
|
const apikeyEnvEntry = authActive
|
|
67
|
-
? `\n "${PROJECTNAME}_APIKEY" => "
|
|
71
|
+
? `\n "${PROJECTNAME}_APIKEY" => "",`
|
|
68
72
|
: ''
|
|
69
73
|
const apikeyLiveField = authActive
|
|
70
74
|
? `\n "apikey" => $env["${PROJECTNAME}_APIKEY"],`
|
|
71
75
|
: ''
|
|
72
76
|
|
|
77
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
78
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
79
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
80
|
+
// takes them from the environment the same way it takes the apikey.
|
|
81
|
+
const svars = serverVariables(model)
|
|
82
|
+
const serverEnvEntry = svars
|
|
83
|
+
.map((v: any) => `\n "${serverVarEnv(PROJECTNAME, v.name)}" => ${formatPhpValue(v.dflt)},`).join('')
|
|
84
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
85
|
+
"server" => [${svars
|
|
86
|
+
.map((v: any) => `
|
|
87
|
+
"${v.name}" => $env["${serverVarEnv(PROJECTNAME, v.name)}"],`).join('')}
|
|
88
|
+
],`
|
|
89
|
+
|
|
73
90
|
const opnames = Object.keys(entity.op || {})
|
|
74
91
|
const hasLoad = opnames.includes('load')
|
|
75
92
|
const hasList = opnames.includes('list')
|
|
@@ -356,14 +373,16 @@ function ${entity.name}_direct_setup($mockres)
|
|
|
356
373
|
|
|
357
374
|
$env = Runner::env_override([
|
|
358
375
|
"${entidEnvVar}" => [],
|
|
359
|
-
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}
|
|
376
|
+
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
360
377
|
]);
|
|
361
378
|
|
|
362
379
|
$live = $env["${PROJECTNAME}_TEST_LIVE"] === "TRUE";
|
|
363
380
|
|
|
364
381
|
if ($live) {
|
|
365
|
-
|
|
366
|
-
|
|
382
|
+
// Merged so the generated fields win: sdk-test-control.json's
|
|
383
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
384
|
+
$merged_opts = array_merge(Runner::live_client_options(), [${apikeyLiveField}${serverLiveField}
|
|
385
|
+
]);
|
|
367
386
|
$client = new ${model.const.Name}SDK($merged_opts);
|
|
368
387
|
return [
|
|
369
388
|
"client" => $client,
|
|
@@ -24,10 +24,14 @@ import {
|
|
|
24
24
|
buildIdNames,
|
|
25
25
|
getMatchEntries,
|
|
26
26
|
isAuthActive,
|
|
27
|
+
serverVarEnv,
|
|
28
|
+
serverVariables,
|
|
27
29
|
entityDataIdField, envName, envToken,
|
|
28
30
|
phpEntityAccessor,
|
|
29
31
|
} from '@voxgig/sdkgen'
|
|
30
32
|
|
|
33
|
+
import { formatPhpValue } from './utility_php'
|
|
34
|
+
|
|
31
35
|
|
|
32
36
|
// PHP's GenCtx mirrors the shared shape (see TestEntity_ts.ts) plus an
|
|
33
37
|
// `accessor` slot used to mangle the entity factory name when it collides
|
|
@@ -75,12 +79,25 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
75
79
|
|
|
76
80
|
const authActive = isAuthActive(model)
|
|
77
81
|
const apikeyEnvEntry = authActive
|
|
78
|
-
? `\n "${PROJUPPER}_APIKEY" => "
|
|
82
|
+
? `\n "${PROJUPPER}_APIKEY" => "",`
|
|
79
83
|
: ''
|
|
80
84
|
const apikeyLiveField = authActive
|
|
81
85
|
? `\n "apikey" => $env["${PROJUPPER}_APIKEY"],`
|
|
82
86
|
: ''
|
|
83
87
|
|
|
88
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
89
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
90
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
91
|
+
// takes them from the environment the same way it takes the apikey.
|
|
92
|
+
const svars = serverVariables(model)
|
|
93
|
+
const serverEnvEntry = svars
|
|
94
|
+
.map((v: any) => `\n "${serverVarEnv(PROJUPPER, v.name)}" => ${formatPhpValue(v.dflt)},`).join('')
|
|
95
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
96
|
+
"server" => [${svars
|
|
97
|
+
.map((v: any) => `
|
|
98
|
+
"${v.name}" => $env["${serverVarEnv(PROJUPPER, v.name)}"],`).join('')}
|
|
99
|
+
],`
|
|
100
|
+
|
|
84
101
|
const idnames = buildIdNames(entity, basicflow)
|
|
85
102
|
const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
|
|
86
103
|
|
|
@@ -246,7 +263,7 @@ ${hasList ? `
|
|
|
246
263
|
$env = Runner::env_override([
|
|
247
264
|
"${PROJUPPER}_TEST_${envToken(entity.name)}_ENTID" => $idmap,
|
|
248
265
|
"${PROJUPPER}_TEST_LIVE" => "FALSE",
|
|
249
|
-
"${PROJUPPER}_TEST_EXPLAIN" => "FALSE",${apikeyEnvEntry}
|
|
266
|
+
"${PROJUPPER}_TEST_EXPLAIN" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
250
267
|
]);
|
|
251
268
|
|
|
252
269
|
$idmap_resolved = Helpers::to_map(
|
|
@@ -267,9 +284,16 @@ ${hasList ? `
|
|
|
267
284
|
Content(`
|
|
268
285
|
if ($env["${PROJUPPER}_TEST_LIVE"] === "TRUE") {
|
|
269
286
|
$merged_opts = Vs::merge([
|
|
270
|
-
|
|
287
|
+
// FIRST, so the generated fields below win: sdk-test-control.json's
|
|
288
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
289
|
+
Runner::live_client_options(),
|
|
290
|
+
[${apikeyLiveField}${serverLiveField}
|
|
271
291
|
],
|
|
272
|
-
|
|
292
|
+
// ismap, not a plain "?? []" default: an empty PHP array is a
|
|
293
|
+
// LIST, and a non-map later entry REPLACES the accumulated map in
|
|
294
|
+
// merge - so the no-extras call discarded live_client_options()
|
|
295
|
+
// and the apikey/server map above it.
|
|
296
|
+
Vs::ismap($extra) ? $extra : new \\stdClass(),
|
|
273
297
|
]);
|
|
274
298
|
$client = new ${model.const.Name}SDK(Helpers::to_map($merged_opts));
|
|
275
299
|
}
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, File, Content, entityCollection
|
|
6
|
+
import { cmp, each, Folder, File, Content, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_php'
|
|
@@ -17,6 +18,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
17
18
|
|
|
18
19
|
Folder({ name: 'test' }, () => {
|
|
19
20
|
|
|
21
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
22
|
+
TestControl({ target, dir: 'test' })
|
|
23
|
+
|
|
20
24
|
// Generate exists test
|
|
21
25
|
File({ name: 'ExistsTest.' + target.ext }, () => {
|
|
22
26
|
Content(`<?php
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
isConfigData,
|
|
16
16
|
resolveAuthPrefix,
|
|
17
17
|
serverVariables,
|
|
18
|
+
targetFeatures,
|
|
18
19
|
} from '@voxgig/sdkgen'
|
|
19
20
|
|
|
20
21
|
|
|
@@ -39,7 +40,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
39
40
|
const model: Model = ctx$.model
|
|
40
41
|
|
|
41
42
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
42
|
-
|
|
43
|
+
// Gated by the applicability tags, so this target never imports or
|
|
44
|
+
// registers a feature it has no source for. One rule, one place:
|
|
45
|
+
// helpers/applicability.
|
|
46
|
+
const feature = targetFeatures(model, target)
|
|
43
47
|
|
|
44
48
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
45
49
|
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
entityClassName, entityCollection,
|
|
8
|
+
targetFeatures,
|
|
9
|
+
TEST_CONTROL_EXCLUDE
|
|
8
10
|
} from '@voxgig/sdkgen'
|
|
9
11
|
|
|
10
12
|
|
|
@@ -32,7 +34,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
32
34
|
const { model } = props.ctx$
|
|
33
35
|
|
|
34
36
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
35
|
-
|
|
37
|
+
// Gated by the applicability tags, so this target never imports or
|
|
38
|
+
// registers a feature it has no source for. One rule, one place:
|
|
39
|
+
// helpers/applicability.
|
|
40
|
+
const feature = targetFeatures(model, target)
|
|
36
41
|
|
|
37
42
|
// The one package directory everything the SDK owns lives in.
|
|
38
43
|
const pkgdir = model.const.Name.toLowerCase() + '_sdk'
|
|
@@ -46,7 +51,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
46
51
|
// below.
|
|
47
52
|
Copy({
|
|
48
53
|
from: 'tm/' + target.name,
|
|
49
|
-
exclude: [/src\//, /pkg
|
|
54
|
+
exclude: [/src\//, /pkg\//, TEST_CONTROL_EXCLUDE],
|
|
50
55
|
replace: {
|
|
51
56
|
...props.ctx$.stdrep,
|
|
52
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, each, Content, isAuthActive, envName, canonKey, canonScalarKey, opRequestShape, entityIdField, entityDataIdField, entityOps, safeVarName, exampleVarName, matchArg, idLiteral } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, each, Content, isAuthActive, envName, canonKey, canonScalarKey, opRequestShape, entityIdField, entityDataIdField, entityOps, safeVarName, exampleVarName, matchArg, idLiteral , serverVariables} from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -38,10 +38,23 @@ const ReadmeQuick = cmp(function ReadmeQuick(props: any) {
|
|
|
38
38
|
) as any
|
|
39
39
|
|
|
40
40
|
const authActive = isAuthActive(model)
|
|
41
|
+
|
|
42
|
+
// Server variables (a templated server URL) are REQUIRED at construction
|
|
43
|
+
// - the SDK refuses rather than request a URL with a literal
|
|
44
|
+
// {account_id} in it - so a quickstart that omits them is a quickstart
|
|
45
|
+
// that fails on its first line.
|
|
46
|
+
const svars = serverVariables(model)
|
|
47
|
+
const pyServerField = 0 === svars.length ? '' :
|
|
48
|
+
`\n "server": {` +
|
|
49
|
+
svars.map((v: any) => `\n "${v.name}": "<${v.name}>",`).join('') +
|
|
50
|
+
`\n },`
|
|
51
|
+
|
|
41
52
|
const apikeyImport = authActive ? `import os\n` : ''
|
|
42
53
|
const ctor = authActive
|
|
43
|
-
? `${model.const.Name}SDK({\n "apikey": os.environ.get("${envName(model)}_APIKEY")
|
|
44
|
-
:
|
|
54
|
+
? `${model.const.Name}SDK({\n "apikey": os.environ.get("${envName(model)}_APIKEY"),${pyServerField}\n})`
|
|
55
|
+
: ('' === pyServerField
|
|
56
|
+
? `${model.const.Name}SDK()`
|
|
57
|
+
: `${model.const.Name}SDK({${pyServerField}\n})`)
|
|
45
58
|
|
|
46
59
|
Content(`### 1. Create a client
|
|
47
60
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, isAuthActive, envName, canonKey, canonScalarKey, entityIdField, opRequestShape, safeVarName, exampleVarName, matchArg, idLiteral } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, isAuthActive, envName, canonKey, canonScalarKey, entityIdField, opRequestShape, safeVarName, exampleVarName, matchArg, idLiteral , serverVariables} from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -41,10 +41,23 @@ const ReadmeTopQuick = cmp(function ReadmeTopQuick(props: any) {
|
|
|
41
41
|
const exampleEntity = Object.values(entity).find((e: any) => e.active !== false) as any
|
|
42
42
|
|
|
43
43
|
const authActive = isAuthActive(model)
|
|
44
|
+
|
|
45
|
+
// Server variables (a templated server URL) are REQUIRED at construction
|
|
46
|
+
// - the SDK refuses rather than request a URL with a literal
|
|
47
|
+
// {account_id} in it - so a quickstart that omits them is a quickstart
|
|
48
|
+
// that fails on its first line.
|
|
49
|
+
const svars = serverVariables(model)
|
|
50
|
+
const pyServerField = 0 === svars.length ? '' :
|
|
51
|
+
`\n "server": {` +
|
|
52
|
+
svars.map((v: any) => `\n "${v.name}": "<${v.name}>",`).join('') +
|
|
53
|
+
`\n },`
|
|
54
|
+
|
|
44
55
|
const apikeyImport = authActive ? `import os\n` : ''
|
|
45
56
|
const ctor = authActive
|
|
46
|
-
? `${model.const.Name}SDK({\n "apikey": os.environ.get("${envName(model)}_APIKEY")
|
|
47
|
-
:
|
|
57
|
+
? `${model.const.Name}SDK({\n "apikey": os.environ.get("${envName(model)}_APIKEY"),${pyServerField}\n})`
|
|
58
|
+
: ('' === pyServerField
|
|
59
|
+
? `${model.const.Name}SDK()`
|
|
60
|
+
: `${model.const.Name}SDK({${pyServerField}\n})`)
|
|
48
61
|
|
|
49
62
|
Content(`\`\`\`python
|
|
50
63
|
${apikeyImport}from ${model.const.Name.toLowerCase()}_sdk import ${model.const.Name}SDK
|
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
File,
|
|
12
12
|
cmp,
|
|
13
13
|
snakify,
|
|
14
|
-
isAuthActive,
|
|
14
|
+
isAuthActive,
|
|
15
|
+
serverVarEnv,
|
|
16
|
+
serverVariables, envName, envToken
|
|
15
17
|
} from '@voxgig/sdkgen'
|
|
16
18
|
|
|
17
19
|
|
|
@@ -64,12 +66,26 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
64
66
|
|
|
65
67
|
const authActive = isAuthActive(model)
|
|
66
68
|
const apikeyEnvEntry = authActive
|
|
67
|
-
? `\n "${PROJECTNAME}_APIKEY": "
|
|
69
|
+
? `\n "${PROJECTNAME}_APIKEY": "",`
|
|
68
70
|
: ''
|
|
69
71
|
const apikeyLiveField = authActive
|
|
70
72
|
? `\n "apikey": env.get("${PROJECTNAME}_APIKEY"),`
|
|
71
73
|
: ''
|
|
72
74
|
|
|
75
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
76
|
+
// impossible to construct without values: make_options raises rather than
|
|
77
|
+
// request a URL with a literal `{account_id}` in it. Taken from the
|
|
78
|
+
// environment, the same way the apikey is.
|
|
79
|
+
const svars = serverVariables(model)
|
|
80
|
+
const serverEnvEntry = svars
|
|
81
|
+
.map((v: any) => `\n "${serverVarEnv(PROJECTNAME, v.name)}": ${JSON.stringify(v.dflt)},`).join('')
|
|
82
|
+
const serverLiveField = 0 === svars.length ? '' :
|
|
83
|
+
`\n "server": {` +
|
|
84
|
+
svars.map((v: any) =>
|
|
85
|
+
`\n "${v.name}": env.get("${serverVarEnv(PROJECTNAME, v.name)}"),`).join('') +
|
|
86
|
+
`\n },`
|
|
87
|
+
|
|
88
|
+
|
|
73
89
|
const opnames = Object.keys(entity.op || {})
|
|
74
90
|
const hasLoad = opnames.includes('load')
|
|
75
91
|
const hasList = opnames.includes('list')
|
|
@@ -337,14 +353,17 @@ def _${entity.name}_direct_setup(mockres):
|
|
|
337
353
|
|
|
338
354
|
env = runner.env_override({
|
|
339
355
|
"${entidEnvVar}": {},
|
|
340
|
-
"${PROJECTNAME}_TEST_LIVE": "FALSE",${apikeyEnvEntry}
|
|
356
|
+
"${PROJECTNAME}_TEST_LIVE": "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
341
357
|
})
|
|
342
358
|
|
|
343
359
|
live = env.get("${PROJECTNAME}_TEST_LIVE") == "TRUE"
|
|
344
360
|
|
|
345
361
|
if live:
|
|
346
|
-
|
|
347
|
-
|
|
362
|
+
# sdk-test-control.json's test.client.options seeds the live
|
|
363
|
+
# client; the generated fields below overwrite anything they name.
|
|
364
|
+
merged_opts = dict(runner.live_client_options())
|
|
365
|
+
merged_opts.update({${apikeyLiveField}${serverLiveField}
|
|
366
|
+
})
|
|
348
367
|
client = ${model.const.Name}SDK(merged_opts)
|
|
349
368
|
return {
|
|
350
369
|
"client": client,
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
buildIdNames,
|
|
25
25
|
getMatchEntries,
|
|
26
26
|
isAuthActive,
|
|
27
|
+
serverVarEnv,
|
|
28
|
+
serverVariables,
|
|
27
29
|
entityDataIdField, envName, envToken
|
|
28
30
|
} from '@voxgig/sdkgen'
|
|
29
31
|
|
|
@@ -60,12 +62,26 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
60
62
|
|
|
61
63
|
const authActive = isAuthActive(model)
|
|
62
64
|
const apikeyEnvEntry = authActive
|
|
63
|
-
? `\n "${PROJUPPER}_APIKEY": "
|
|
65
|
+
? `\n "${PROJUPPER}_APIKEY": "",`
|
|
64
66
|
: ''
|
|
65
67
|
const apikeyLiveField = authActive
|
|
66
68
|
? `\n "apikey": env.get("${PROJUPPER}_APIKEY"),`
|
|
67
69
|
: ''
|
|
68
70
|
|
|
71
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
72
|
+
// impossible to construct without values: make_options raises rather than
|
|
73
|
+
// request a URL with a literal `{account_id}` in it. Taken from the
|
|
74
|
+
// environment, the same way the apikey is.
|
|
75
|
+
const svars = serverVariables(model)
|
|
76
|
+
const serverEnvEntry = svars
|
|
77
|
+
.map((v: any) => `\n "${serverVarEnv(PROJUPPER, v.name)}": ${JSON.stringify(v.dflt)},`).join('')
|
|
78
|
+
const serverLiveField = 0 === svars.length ? '' :
|
|
79
|
+
`\n "server": {` +
|
|
80
|
+
svars.map((v: any) =>
|
|
81
|
+
`\n "${v.name}": env.get("${serverVarEnv(PROJUPPER, v.name)}"),`).join('') +
|
|
82
|
+
`\n },`
|
|
83
|
+
|
|
84
|
+
|
|
69
85
|
const idnames = buildIdNames(entity, basicflow)
|
|
70
86
|
const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
|
|
71
87
|
|
|
@@ -235,7 +251,7 @@ def _${entity.name}_basic_setup(extra):
|
|
|
235
251
|
env = runner.env_override({
|
|
236
252
|
"${PROJUPPER}_TEST_${envToken(entity.name)}_ENTID": idmap,
|
|
237
253
|
"${PROJUPPER}_TEST_LIVE": "FALSE",
|
|
238
|
-
"${PROJUPPER}_TEST_EXPLAIN": "FALSE",${apikeyEnvEntry}
|
|
254
|
+
"${PROJUPPER}_TEST_EXPLAIN": "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
239
255
|
})
|
|
240
256
|
|
|
241
257
|
idmap_resolved = helpers.to_map(
|
|
@@ -254,7 +270,11 @@ def _${entity.name}_basic_setup(extra):
|
|
|
254
270
|
Content(`
|
|
255
271
|
if env.get("${PROJUPPER}_TEST_LIVE") == "TRUE":
|
|
256
272
|
merged_opts = vs.merge([
|
|
257
|
-
|
|
273
|
+
# FIRST, so the generated fields below win: sdk-test-control.json's
|
|
274
|
+
# test.client.options adds to the live client, it does not
|
|
275
|
+
# redirect it.
|
|
276
|
+
runner.live_client_options(),
|
|
277
|
+
{${apikeyLiveField}${serverLiveField}
|
|
258
278
|
},
|
|
259
279
|
extra or {},
|
|
260
280
|
])
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, File, Content, entityCollection
|
|
6
|
+
import { cmp, each, Folder, File, Content, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_py'
|
|
@@ -17,6 +18,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
17
18
|
|
|
18
19
|
Folder({ name: 'test' }, () => {
|
|
19
20
|
|
|
21
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
22
|
+
TestControl({ target, dir: 'test' })
|
|
23
|
+
|
|
20
24
|
// Generate __init__.py for test package
|
|
21
25
|
File({ name: '__init__.' + target.ext }, () => {
|
|
22
26
|
Content(``)
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
rawStringLiteral,
|
|
17
17
|
resolveAuthPrefix,
|
|
18
18
|
serverVariables,
|
|
19
|
+
targetFeatures,
|
|
19
20
|
} from '@voxgig/sdkgen'
|
|
20
21
|
|
|
21
22
|
|
|
@@ -40,7 +41,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
40
41
|
const model: Model = ctx$.model
|
|
41
42
|
|
|
42
43
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
43
|
-
|
|
44
|
+
// Gated by the applicability tags, so this target never imports or
|
|
45
|
+
// registers a feature it has no source for. One rule, one place:
|
|
46
|
+
// helpers/applicability.
|
|
47
|
+
const feature = targetFeatures(model, target)
|
|
44
48
|
|
|
45
49
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
46
50
|
|
|
@@ -4,6 +4,8 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
|
+
targetFeatures,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
7
9
|
} from '@voxgig/sdkgen'
|
|
8
10
|
|
|
9
11
|
|
|
@@ -31,7 +33,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
31
33
|
const { model } = props.ctx$
|
|
32
34
|
|
|
33
35
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
34
|
-
|
|
36
|
+
// Gated by the applicability tags, so this target never imports or
|
|
37
|
+
// registers a feature it has no source for. One rule, one place:
|
|
38
|
+
// helpers/applicability.
|
|
39
|
+
const feature = targetFeatures(model, target)
|
|
35
40
|
|
|
36
41
|
Package({ target })
|
|
37
42
|
|
|
@@ -40,7 +45,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
40
45
|
// Copy tm/rb files with replacements
|
|
41
46
|
Copy({
|
|
42
47
|
from: 'tm/' + target.name,
|
|
43
|
-
exclude: [/src
|
|
48
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
44
49
|
replace: {
|
|
45
50
|
...props.ctx$.stdrep,
|
|
46
51
|
}
|
|
@@ -11,9 +11,13 @@ import {
|
|
|
11
11
|
File,
|
|
12
12
|
cmp,
|
|
13
13
|
snakify,
|
|
14
|
-
isAuthActive, envName, envToken
|
|
14
|
+
isAuthActive, envName, envToken,
|
|
15
|
+
serverVarEnv,
|
|
16
|
+
serverVariables
|
|
15
17
|
} from '@voxgig/sdkgen'
|
|
16
18
|
|
|
19
|
+
import { formatRubyValue } from './utility_rb'
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
function normalizePathParams(
|
|
19
23
|
parts: string[],
|
|
@@ -64,12 +68,25 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
64
68
|
|
|
65
69
|
const authActive = isAuthActive(model)
|
|
66
70
|
const apikeyEnvEntry = authActive
|
|
67
|
-
? `\n "${PROJECTNAME}_APIKEY" => "
|
|
71
|
+
? `\n "${PROJECTNAME}_APIKEY" => "",`
|
|
68
72
|
: ''
|
|
69
73
|
const apikeyLiveField = authActive
|
|
70
74
|
? `\n "apikey" => env["${PROJECTNAME}_APIKEY"],`
|
|
71
75
|
: ''
|
|
72
76
|
|
|
77
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
78
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
79
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
80
|
+
// takes them from the environment the same way it takes the apikey.
|
|
81
|
+
const svars = serverVariables(model)
|
|
82
|
+
const serverEnvEntry = svars
|
|
83
|
+
.map((v: any) => `\n "${serverVarEnv(PROJECTNAME, v.name)}" => ${formatRubyValue(v.dflt)},`).join('')
|
|
84
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
85
|
+
"server" => {${svars
|
|
86
|
+
.map((v: any) => `
|
|
87
|
+
"${v.name}" => env["${serverVarEnv(PROJECTNAME, v.name)}"],`).join('')}
|
|
88
|
+
},`
|
|
89
|
+
|
|
73
90
|
const opnames = Object.keys(entity.op || {})
|
|
74
91
|
const hasLoad = opnames.includes('load')
|
|
75
92
|
const hasList = opnames.includes('list')
|
|
@@ -349,14 +366,16 @@ def ${entity.name}_direct_setup(mockres)
|
|
|
349
366
|
|
|
350
367
|
env = Runner.env_override({
|
|
351
368
|
"${entidEnvVar}" => {},
|
|
352
|
-
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}
|
|
369
|
+
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
353
370
|
})
|
|
354
371
|
|
|
355
372
|
live = env["${PROJECTNAME}_TEST_LIVE"] == "TRUE"
|
|
356
373
|
|
|
357
374
|
if live
|
|
358
|
-
|
|
359
|
-
|
|
375
|
+
# Merged so the generated fields win: sdk-test-control.json's
|
|
376
|
+
# test.client.options adds to the live client, it does not redirect it.
|
|
377
|
+
merged_opts = Runner.live_client_options.merge({${apikeyLiveField}${serverLiveField}
|
|
378
|
+
})
|
|
360
379
|
client = ${model.const.Name}SDK.new(merged_opts)
|
|
361
380
|
return {
|
|
362
381
|
client: client,
|
|
@@ -24,9 +24,13 @@ import {
|
|
|
24
24
|
buildIdNames,
|
|
25
25
|
getMatchEntries,
|
|
26
26
|
isAuthActive,
|
|
27
|
-
entityDataIdField, envName, envToken
|
|
27
|
+
entityDataIdField, envName, envToken,
|
|
28
|
+
serverVarEnv,
|
|
29
|
+
serverVariables
|
|
28
30
|
} from '@voxgig/sdkgen'
|
|
29
31
|
|
|
32
|
+
import { formatRubyValue } from './utility_rb'
|
|
33
|
+
|
|
30
34
|
|
|
31
35
|
// See TestEntity_ts.ts for the GenCtx/OpGen contract.
|
|
32
36
|
type GenCtx = {
|
|
@@ -62,12 +66,25 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
62
66
|
|
|
63
67
|
const authActive = isAuthActive(model)
|
|
64
68
|
const apikeyEnvEntry = authActive
|
|
65
|
-
? `\n "${PROJUPPER}_APIKEY" => "
|
|
69
|
+
? `\n "${PROJUPPER}_APIKEY" => "",`
|
|
66
70
|
: ''
|
|
67
71
|
const apikeyLiveField = authActive
|
|
68
72
|
? `\n "apikey" => env["${PROJUPPER}_APIKEY"],`
|
|
69
73
|
: ''
|
|
70
74
|
|
|
75
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
76
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
77
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
78
|
+
// takes them from the environment the same way it takes the apikey.
|
|
79
|
+
const svars = serverVariables(model)
|
|
80
|
+
const serverEnvEntry = svars
|
|
81
|
+
.map((v: any) => `\n "${serverVarEnv(PROJUPPER, v.name)}" => ${formatRubyValue(v.dflt)},`).join('')
|
|
82
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
83
|
+
"server" => {${svars
|
|
84
|
+
.map((v: any) => `
|
|
85
|
+
"${v.name}" => env["${serverVarEnv(PROJUPPER, v.name)}"],`).join('')}
|
|
86
|
+
},`
|
|
87
|
+
|
|
71
88
|
const idnames = buildIdNames(entity, basicflow)
|
|
72
89
|
const idnamesStr = idnames.map(n => `"${n}"`).join(', ')
|
|
73
90
|
|
|
@@ -227,7 +244,7 @@ end
|
|
|
227
244
|
env = Runner.env_override({
|
|
228
245
|
"${PROJUPPER}_TEST_${envToken(entity.name)}_ENTID" => idmap,
|
|
229
246
|
"${PROJUPPER}_TEST_LIVE" => "FALSE",
|
|
230
|
-
"${PROJUPPER}_TEST_EXPLAIN" => "FALSE",${apikeyEnvEntry}
|
|
247
|
+
"${PROJUPPER}_TEST_EXPLAIN" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
231
248
|
})
|
|
232
249
|
|
|
233
250
|
idmap_resolved = Helpers.to_map(
|
|
@@ -248,7 +265,10 @@ end
|
|
|
248
265
|
Content(`
|
|
249
266
|
if env["${PROJUPPER}_TEST_LIVE"] == "TRUE"
|
|
250
267
|
merged_opts = Vs.merge([
|
|
251
|
-
|
|
268
|
+
# FIRST, so the generated fields below win: sdk-test-control.json's
|
|
269
|
+
# test.client.options adds to the live client, it does not redirect it.
|
|
270
|
+
Runner.live_client_options,
|
|
271
|
+
{${apikeyLiveField}${serverLiveField}
|
|
252
272
|
},
|
|
253
273
|
extra || {},
|
|
254
274
|
])
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, File, Content, entityCollection
|
|
6
|
+
import { cmp, each, Folder, File, Content, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_rb'
|
|
@@ -17,6 +18,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
17
18
|
|
|
18
19
|
Folder({ name: 'test' }, () => {
|
|
19
20
|
|
|
21
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
22
|
+
TestControl({ target, dir: 'test' })
|
|
23
|
+
|
|
20
24
|
// Generate exists test
|
|
21
25
|
File({ name: 'exists_test.' + target.ext }, () => {
|
|
22
26
|
Content(`# ${model.const.Name} SDK exists test
|
|
@@ -48,7 +48,9 @@ function formatRubyValue(val: any, indent: number = 0): string {
|
|
|
48
48
|
return 'nil'
|
|
49
49
|
}
|
|
50
50
|
if (typeof val === 'string') {
|
|
51
|
-
|
|
51
|
+
// `#` is escaped only where it OPENS an interpolation (#{, #$, #@), so
|
|
52
|
+
// this changes output solely for values that would otherwise interpolate.
|
|
53
|
+
return `"${val.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/#(?=[{$@])/g, '\\#')}"`
|
|
52
54
|
}
|
|
53
55
|
if (typeof val === 'number') {
|
|
54
56
|
return String(val)
|