@voxgig/sdkgen 4.5.2 → 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/cmp/ReadmeTop.js +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/cmp/ReadmeTop.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
|
@@ -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
|
])
|
|
@@ -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,7 @@ 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,
|
|
7
8
|
} from '@voxgig/sdkgen'
|
|
8
9
|
|
|
9
10
|
|
|
@@ -31,7 +32,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
31
32
|
const { model } = props.ctx$
|
|
32
33
|
|
|
33
34
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
34
|
-
|
|
35
|
+
// Gated by the applicability tags, so this target never imports or
|
|
36
|
+
// registers a feature it has no source for. One rule, one place:
|
|
37
|
+
// helpers/applicability.
|
|
38
|
+
const feature = targetFeatures(model, target)
|
|
35
39
|
|
|
36
40
|
Package({ target })
|
|
37
41
|
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
isAuthActive,
|
|
10
10
|
isConfigData,
|
|
11
11
|
resolveAuthPrefix,
|
|
12
|
+
targetFeatures,
|
|
12
13
|
} from '@voxgig/sdkgen'
|
|
13
14
|
|
|
14
15
|
|
|
@@ -35,7 +36,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
35
36
|
const model: Model = ctx$.model
|
|
36
37
|
|
|
37
38
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
38
|
-
|
|
39
|
+
// Gated by the applicability tags, so this target never imports or
|
|
40
|
+
// registers a feature it has no source for. One rule, one place:
|
|
41
|
+
// helpers/applicability.
|
|
42
|
+
const feature = targetFeatures(model, target)
|
|
39
43
|
|
|
40
44
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
41
45
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each,
|
|
6
6
|
File, Content, Copy, Folder, Fragment,
|
|
7
7
|
entityClassName,
|
|
8
|
+
targetFeatures,
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -35,7 +36,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
35
36
|
const { model } = props.ctx$
|
|
36
37
|
|
|
37
38
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
38
|
-
|
|
39
|
+
// Gated by the applicability tags, so this target never imports or
|
|
40
|
+
// registers a feature it has no source for. One rule, one place:
|
|
41
|
+
// helpers/applicability.
|
|
42
|
+
const feature = targetFeatures(model, target)
|
|
39
43
|
|
|
40
44
|
// The rust crate identifier (RUSTCRATE placeholder), e.g. solar_sdk —
|
|
41
45
|
// used in every `use <crate>::...` path in the test templates.
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
each,
|
|
7
7
|
isAuthActive,
|
|
8
8
|
resolveAuthPrefix,
|
|
9
|
+
targetFeatures,
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
|
|
@@ -35,7 +36,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
35
36
|
const scalapackage = scalaPackage(model)
|
|
36
37
|
|
|
37
38
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
38
|
-
|
|
39
|
+
// Gated by the applicability tags, so this target never imports or
|
|
40
|
+
// registers a feature it has no source for. One rule, one place:
|
|
41
|
+
// helpers/applicability.
|
|
42
|
+
const feature = targetFeatures(model, target)
|
|
39
43
|
|
|
40
44
|
const headers = getModelPath(model, `main.${KIT}.config.headers`) || {}
|
|
41
45
|
|
|
@@ -4,6 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each,
|
|
6
6
|
File, Content, Copy, Folder, Fragment,
|
|
7
|
+
targetFeatures,
|
|
7
8
|
} from '@voxgig/sdkgen'
|
|
8
9
|
|
|
9
10
|
|
|
@@ -33,7 +34,10 @@ const Main = cmp(async function Main(props: any) {
|
|
|
33
34
|
const { model } = props.ctx$
|
|
34
35
|
|
|
35
36
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
36
|
-
|
|
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)
|
|
37
41
|
|
|
38
42
|
// The Scala package root for every runtime piece (like GOMODULE for go).
|
|
39
43
|
const scalapackage = scalaPackage(model)
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp,
|
|
6
6
|
configDefinition,
|
|
7
7
|
each,
|
|
8
|
+
targetFeatures,
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -26,7 +27,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
26
27
|
|
|
27
28
|
const model: Model = ctx$.model
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
// Gated by the applicability tags, so this target never imports or
|
|
31
|
+
// registers a feature it has no source for. One rule, one place:
|
|
32
|
+
// helpers/applicability.
|
|
33
|
+
const feature = targetFeatures(model, target)
|
|
30
34
|
|
|
31
35
|
// The config as data, built by the shared helper so every target embeds
|
|
32
36
|
// the same model by construction. Passing target.name opts this target
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
isHttpBasicAuth,
|
|
19
19
|
resolveAuthPrefix,
|
|
20
20
|
serverVariables,
|
|
21
|
+
targetFeatures,
|
|
21
22
|
} from '@voxgig/sdkgen'
|
|
22
23
|
|
|
23
24
|
|
|
@@ -41,7 +42,10 @@ const Config = cmp(async function Config(props: any) {
|
|
|
41
42
|
const model: Model = ctx$.model
|
|
42
43
|
|
|
43
44
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
44
|
-
|
|
45
|
+
// Gated by the applicability tags, so this target never imports or
|
|
46
|
+
// registers a feature it has no source for. One rule, one place:
|
|
47
|
+
// helpers/applicability.
|
|
48
|
+
const feature = targetFeatures(model, target)
|
|
45
49
|
|
|
46
50
|
const ff = Path.normalize(__dirname + '/../../../src/cmp/ts/fragment/')
|
|
47
51
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
entityClassName, entityCollection, srcFeatureExcludes, stationLibrary,
|
|
8
|
+
targetFeatures,
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -35,7 +36,14 @@ const Main = cmp(async function Main(props: any) {
|
|
|
35
36
|
const { model } = props.ctx$
|
|
36
37
|
|
|
37
38
|
const entity: ModelEntity = getModelPath(model, `main.${KIT}.entity`)
|
|
38
|
-
|
|
39
|
+
// Gated by the applicability tags, so this target never imports or
|
|
40
|
+
// registers a feature it has no source for. One rule, one place:
|
|
41
|
+
// helpers/applicability.
|
|
42
|
+
const feature = targetFeatures(model, target)
|
|
43
|
+
|
|
44
|
+
// Does the secrets feature apply here and is it switched on? Both, since
|
|
45
|
+
// targetFeatures already dropped it for a target with no sekreto port.
|
|
46
|
+
const secrets = null != feature.secrets
|
|
39
47
|
|
|
40
48
|
Package({ target })
|
|
41
49
|
|
|
@@ -74,6 +82,54 @@ const Main = cmp(async function Main(props: any) {
|
|
|
74
82
|
replace: {
|
|
75
83
|
...props.ctx$.stdrep,
|
|
76
84
|
|
|
85
|
+
// SECRETS. All five slots are emitted only when the secrets
|
|
86
|
+
// feature applies to this target AND the model activates it.
|
|
87
|
+
// An unconditional edit here would land in every generated SDK
|
|
88
|
+
// and break the inactive-output gate: a model without the
|
|
89
|
+
// feature must generate byte-identically to pre-migration.
|
|
90
|
+
//
|
|
91
|
+
// `feature` is already gated by targetFeatures, so a target
|
|
92
|
+
// that does not provide 'sekreto' never reaches these.
|
|
93
|
+
'// #SecretsImport': () => secrets ?
|
|
94
|
+
Line(`import * as sekreto from './feature/secrets/sekreto'`) : undefined,
|
|
95
|
+
|
|
96
|
+
'// #SecretsField': ({ indent }: any) => secrets ?
|
|
97
|
+
Line({ indent }, '_secrets?: any') : undefined,
|
|
98
|
+
|
|
99
|
+
// The LIVE instance, not a clone: sekreto holds provider and
|
|
100
|
+
// cache state, so a clone would resolve into a copy that
|
|
101
|
+
// prepareAuth never sees.
|
|
102
|
+
'// #SecretsAccessor': ({ indent }: any) => secrets ?
|
|
103
|
+
Content({ indent }, `
|
|
104
|
+
secrets() {
|
|
105
|
+
return this._secrets && this._secrets.sekreto()
|
|
106
|
+
}
|
|
107
|
+
`) : undefined,
|
|
108
|
+
|
|
109
|
+
// prepare() bypasses the feature hook pipeline, so the PreSpec
|
|
110
|
+
// hook that resolves the secret for entity ops never runs on
|
|
111
|
+
// this path and the resolve has to be explicit.
|
|
112
|
+
//
|
|
113
|
+
// It RETURNS the Error rather than rejecting: _rawRequest
|
|
114
|
+
// awaits prepare() outside its try, and direct()/graphql() are
|
|
115
|
+
// documented to return a value or an Error, never reject. The
|
|
116
|
+
// prototype rejected here, which would have turned a broken
|
|
117
|
+
// vault into an unhandled rejection on the direct path.
|
|
118
|
+
'// #SecretsResolve': ({ indent }: any) => secrets ?
|
|
119
|
+
Content({ indent }, `
|
|
120
|
+
if (null != this._secrets) {
|
|
121
|
+
try {
|
|
122
|
+
await this._secrets.resolve()
|
|
123
|
+
}
|
|
124
|
+
catch (err: any) {
|
|
125
|
+
return err instanceof Error ? err : new Error(String(err))
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
`) : undefined,
|
|
129
|
+
|
|
130
|
+
'// #SecretsExport': ({ indent }: any) => secrets ?
|
|
131
|
+
Line({ indent }, 'sekreto,') : undefined,
|
|
132
|
+
|
|
77
133
|
'#BuildFeatures': ({ indent }: any) => {
|
|
78
134
|
List({ item: feature, line: false }, ({ item }: any) =>
|
|
79
135
|
Line({ indent },
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
PUBLISHER_URL,
|
|
14
14
|
packageVersion,
|
|
15
15
|
authorInfo,
|
|
16
|
+
targetFeatures,
|
|
16
17
|
} from '@voxgig/sdkgen'
|
|
17
18
|
|
|
18
19
|
|
|
@@ -36,7 +37,9 @@ const Package = cmp(async function Package(props: any) {
|
|
|
36
37
|
// constant here did.
|
|
37
38
|
const author = authorInfo(model, target.name)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
// Gated by applicability: a feature that does not apply to this
|
|
41
|
+
// target must not inject its deps into the generated manifest.
|
|
42
|
+
const feature = targetFeatures(model, target)
|
|
40
43
|
|
|
41
44
|
const only = (kind: string, deps: any) =>
|
|
42
45
|
omap(deps, ([k, v]: any) => [v.active && kind === v.kind ? k : undefined, v.version])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, each, Content, isAuthActive, isHttpBasicAuth } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, each, Content, isAuthActive, isHttpBasicAuth, serverVariables } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -61,12 +61,24 @@ const ReadmeModel = cmp(function ReadmeModel(props: any) {
|
|
|
61
61
|
? '| `secret` | `string` | API secret for authentication. |\n'
|
|
62
62
|
: ''
|
|
63
63
|
|
|
64
|
+
// Server variables are not one option among many: without them the
|
|
65
|
+
// constructor THROWS, because the base URL is a template. Documented
|
|
66
|
+
// first for that reason, and named individually so a reader knows what
|
|
67
|
+
// to supply without going back to the spec.
|
|
68
|
+
const svars = serverVariables(model)
|
|
69
|
+
const serverOptionType = 0 === svars.length ? '' :
|
|
70
|
+
`\n server?: { ${svars.map((v: any) => `${v.name}: string`).join(', ')} }`
|
|
71
|
+
const serverOptionRow = 0 === svars.length ? '' :
|
|
72
|
+
'| `server` | `object` | **Required.** Values for the server-URL variables: ' +
|
|
73
|
+
svars.map((v: any) => '`' + v.name + '`').join(', ') +
|
|
74
|
+
'. The API base URL is a template over them. |\n'
|
|
75
|
+
|
|
64
76
|
Content(`### ${model.const.Name}SDK
|
|
65
77
|
|
|
66
78
|
#### Constructor
|
|
67
79
|
|
|
68
80
|
\`\`\`ts
|
|
69
|
-
new ${model.const.Name}SDK(options?: {${apikeyOptionType}${secretOptionType}
|
|
81
|
+
new ${model.const.Name}SDK(options?: {${apikeyOptionType}${secretOptionType}${serverOptionType}
|
|
70
82
|
base?: string
|
|
71
83
|
prefix?: string
|
|
72
84
|
suffix?: string
|
|
@@ -77,7 +89,7 @@ new ${model.const.Name}SDK(options?: {${apikeyOptionType}${secretOptionType}
|
|
|
77
89
|
|
|
78
90
|
| Option | Type | Description |
|
|
79
91
|
| --- | --- | --- |
|
|
80
|
-
${apikeyOptionRow}${secretOptionRow}| \`base\` | \`string\` | Base URL of the API server. |
|
|
92
|
+
${serverOptionRow}${apikeyOptionRow}${secretOptionRow}| \`base\` | \`string\` | Base URL of the API server. |
|
|
81
93
|
| \`prefix\` | \`string\` | URL path prefix prepended to all requests. |
|
|
82
94
|
| \`suffix\` | \`string\` | URL path suffix appended to all requests. |
|
|
83
95
|
| \`feature\` | \`object\` | Feature activation flags (e.g. \`{ test: { active: true } }\`). |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, each, Content, isAuthActive, isHttpBasicAuth, packageName, envName, opRequestShape, entityIdField, entityDataIdField, entityOps, safeVarName, exampleVarName, jsKey, matchArg, idLiteral } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, each, Content, isAuthActive, isHttpBasicAuth, packageName, envName, serverVariables, opRequestShape, entityIdField, entityDataIdField, entityOps, safeVarName, exampleVarName, jsKey, matchArg, idLiteral } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -40,10 +40,23 @@ const ReadmeQuick = cmp(function ReadmeQuick(props: any) {
|
|
|
40
40
|
!it.optional && it.name !== entityIdField(e))
|
|
41
41
|
) as any
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
// Server variables (a templated server URL) are REQUIRED at construction
|
|
44
|
+
// — makeOptions refuses rather than request a URL with a literal
|
|
45
|
+
// `{account_id}` in it — so a quickstart that omits them is a quickstart
|
|
46
|
+
// that throws on its first line.
|
|
47
|
+
const svarLines = serverVariables(model)
|
|
48
|
+
.map((v: any) => `\n ${v.name}: '<${v.name}>',`).join('')
|
|
49
|
+
const serverField = '' === svarLines ? '' :
|
|
50
|
+
`\n // Required: this API's server URL is templated on these.\n server: {${svarLines}\n },`
|
|
51
|
+
|
|
52
|
+
const ctorFields = (isAuthActive(model)
|
|
53
|
+
? `\n apikey: process.env.${envName(model)}_APIKEY,${
|
|
54
|
+
isHttpBasicAuth(model) ? `\n secret: process.env.${envName(model)}_SECRET,` : ''}`
|
|
55
|
+
: '') + serverField
|
|
56
|
+
|
|
57
|
+
const ctor = '' === ctorFields
|
|
58
|
+
? `new ${model.const.Name}SDK()`
|
|
59
|
+
: `new ${model.const.Name}SDK({${ctorFields}\n})`
|
|
47
60
|
|
|
48
61
|
Content(`### 1. Create a client
|
|
49
62
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, isAuthActive, isHttpBasicAuth, packageName, envName, entityIdField, entityOps, opRequestShape, safeVarName, exampleVarName, jsKey, matchArg, idLiteral } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, isAuthActive, isHttpBasicAuth, packageName, envName, entityIdField, entityOps, opRequestShape, safeVarName, exampleVarName, jsKey, matchArg, idLiteral , serverVariables} from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -28,10 +28,24 @@ const ReadmeTopQuick = cmp(function ReadmeTopQuick(props: any) {
|
|
|
28
28
|
const exampleEntity = Object.values(entity).find((e: any) => e.active !== false) as any
|
|
29
29
|
|
|
30
30
|
const authActive = isAuthActive(model)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
|
|
32
|
+
// Server variables (a templated server URL) are REQUIRED at construction
|
|
33
|
+
// - makeOptions refuses rather than request a URL with a literal
|
|
34
|
+
// {account_id} in it - so a quickstart that omits them is a quickstart
|
|
35
|
+
// that throws on its first line.
|
|
36
|
+
const svarLines = serverVariables(model)
|
|
37
|
+
.map((v: any) => `\n ${v.name}: '<${v.name}>',`).join('')
|
|
38
|
+
const serverField = '' === svarLines ? '' :
|
|
39
|
+
`\n // Required: this API's server URL is templated on these.\n server: {${svarLines}\n },`
|
|
40
|
+
|
|
41
|
+
const ctorFields = (authActive
|
|
42
|
+
? `\n apikey: process.env.${envName(model)}_APIKEY,${
|
|
43
|
+
isHttpBasicAuth(model) ? `\n secret: process.env.${envName(model)}_SECRET,` : ''}`
|
|
44
|
+
: '') + serverField
|
|
45
|
+
|
|
46
|
+
const ctor = '' === ctorFields
|
|
47
|
+
? `new ${model.const.Name}SDK()`
|
|
48
|
+
: `new ${model.const.Name}SDK({${ctorFields}\n})`
|
|
35
49
|
|
|
36
50
|
Content(`\`\`\`ts
|
|
37
51
|
import { ${model.const.Name}SDK } from '${packageName(model, target.name)}'
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
cmp,
|
|
18
18
|
snakify,
|
|
19
19
|
isAuthActive,
|
|
20
|
+
serverVarEnv,
|
|
21
|
+
serverVariables,
|
|
20
22
|
isHttpBasicAuth,
|
|
21
23
|
jsProp,
|
|
22
24
|
jsOptProp, envName, envToken, liveStrict
|
|
@@ -47,7 +49,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
47
49
|
const authActive = isAuthActive(model)
|
|
48
50
|
const authBasic = authActive && isHttpBasicAuth(model)
|
|
49
51
|
const apikeyEnvEntry = authActive
|
|
50
|
-
? `\n '${PROJECTNAME}_APIKEY': '
|
|
52
|
+
? `\n '${PROJECTNAME}_APIKEY': '',${authBasic ? `\n '${PROJECTNAME}_SECRET': 'NONE',` : ''}`
|
|
51
53
|
: ''
|
|
52
54
|
const apikeyLiveField = authActive
|
|
53
55
|
? `
|
|
@@ -55,6 +57,19 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
55
57
|
secret: env.${PROJECTNAME}_SECRET,` : ''}`
|
|
56
58
|
: ''
|
|
57
59
|
|
|
60
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
61
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
62
|
+
// request a URL with a literal `{account_id}` in it. Taken from the
|
|
63
|
+
// environment, the same way the apikey is.
|
|
64
|
+
const svars = serverVariables(model)
|
|
65
|
+
const serverEnvEntry = svars
|
|
66
|
+
.map((v: any) => `\n '${serverVarEnv(PROJECTNAME, v.name)}': ${JSON.stringify(v.dflt)},`).join('')
|
|
67
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
68
|
+
server: {${svars
|
|
69
|
+
.map((v: any) => `
|
|
70
|
+
${v.name}: env.${serverVarEnv(PROJECTNAME, v.name)},`).join('')}
|
|
71
|
+
},`
|
|
72
|
+
|
|
58
73
|
const opnames = Object.keys(entity.op || {})
|
|
59
74
|
const hasLoad = opnames.includes('load')
|
|
60
75
|
const hasList = opnames.includes('list')
|
|
@@ -86,14 +101,17 @@ function directSetup(mockres?: any) {
|
|
|
86
101
|
|
|
87
102
|
const env = envOverride({
|
|
88
103
|
'${entidEnvVar}': {},
|
|
89
|
-
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}
|
|
104
|
+
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}${serverEnvEntry}
|
|
90
105
|
})
|
|
91
106
|
|
|
92
107
|
const live = 'TRUE' === env.${PROJECTNAME}_TEST_LIVE
|
|
93
108
|
|
|
94
109
|
if (live) {
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
// Merged so the generated fields win: sdk-test-control.json's
|
|
111
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
112
|
+
const client = new ${nom(model.const, 'Name')}SDK(
|
|
113
|
+
Object.assign({}, liveClientOptions(), {${apikeyLiveField}${serverLiveField}
|
|
114
|
+
}))
|
|
97
115
|
|
|
98
116
|
let idmap: any = env['${entidEnvVar}']
|
|
99
117
|
if ('string' === typeof idmap && idmap.startsWith('{')) {
|
|
@@ -210,7 +228,21 @@ function generateDirectGraphql(
|
|
|
210
228
|
${varAsserts}`
|
|
211
229
|
|
|
212
230
|
const checks = strict ?
|
|
213
|
-
|
|
231
|
+
` if (setup.live) {
|
|
232
|
+
// STRICT live mode: a non-2xx is a real failure - this project owns
|
|
233
|
+
// the server it points at, so there is nothing to be lenient about.
|
|
234
|
+
//
|
|
235
|
+
// What is NOT asserted here is the MOCK's own fixtures. \`direct01\`
|
|
236
|
+
// is a scripted id and \`calls\` records the mock transport; neither
|
|
237
|
+
// exists on a live run, so asserting them made strict mode mean
|
|
238
|
+
// "compare the live server against the mock's script" - a suite that
|
|
239
|
+
// could not pass against any real API, including this project's own.
|
|
240
|
+
assert(result.ok === true,
|
|
241
|
+
'live request failed: ' + result.status + ' ' + JSON.stringify(result.data))
|
|
242
|
+
assert(result.status >= 200 && result.status < 300)
|
|
243
|
+
assert(null != result.data)
|
|
244
|
+
} else {
|
|
245
|
+
${offlineChecks} }` :
|
|
214
246
|
` if (setup.live) {
|
|
215
247
|
// Live mode is lenient: synthetic ids frequently fail server-side
|
|
216
248
|
// validation. Skip rather than fail when the call doesn't come back
|
|
@@ -429,7 +461,21 @@ ${loadParams.map((p: any, i: number) => ` ${jsProp('params', p.name)} = 'di
|
|
|
429
461
|
${paramAsserts}`
|
|
430
462
|
|
|
431
463
|
const loadChecks = strict ?
|
|
432
|
-
|
|
464
|
+
` if (setup.live) {
|
|
465
|
+
// STRICT live mode: a non-2xx is a real failure - this project owns
|
|
466
|
+
// the server it points at, so there is nothing to be lenient about.
|
|
467
|
+
//
|
|
468
|
+
// What is NOT asserted here is the MOCK's own fixtures. \`direct01\`
|
|
469
|
+
// is a scripted id and \`calls\` records the mock transport; neither
|
|
470
|
+
// exists on a live run, so asserting them made strict mode mean
|
|
471
|
+
// "compare the live server against the mock's script" - a suite that
|
|
472
|
+
// could not pass against any real API, including this project's own.
|
|
473
|
+
assert(result.ok === true,
|
|
474
|
+
'live request failed: ' + result.status + ' ' + JSON.stringify(result.data))
|
|
475
|
+
assert(result.status >= 200 && result.status < 300)
|
|
476
|
+
assert(null != result.data)
|
|
477
|
+
} else {
|
|
478
|
+
${offlineChecks} }` :
|
|
433
479
|
` if (setup.live) {
|
|
434
480
|
// Live mode is lenient: synthetic IDs frequently 4xx. Skip rather
|
|
435
481
|
// than fail when the load endpoint isn't reachable with the IDs we
|
|
@@ -543,7 +589,21 @@ ${mockLines}
|
|
|
543
589
|
${paramAsserts}`
|
|
544
590
|
|
|
545
591
|
const listChecks = strict ?
|
|
546
|
-
|
|
592
|
+
` if (setup.live) {
|
|
593
|
+
// STRICT live mode: a non-2xx is a real failure - this project owns
|
|
594
|
+
// the server it points at, so there is nothing to be lenient about.
|
|
595
|
+
//
|
|
596
|
+
// What is NOT asserted here is the MOCK's own fixtures. \`direct01\`
|
|
597
|
+
// is a scripted id and \`calls\` records the mock transport; neither
|
|
598
|
+
// exists on a live run, so asserting them made strict mode mean
|
|
599
|
+
// "compare the live server against the mock's script" - a suite that
|
|
600
|
+
// could not pass against any real API, including this project's own.
|
|
601
|
+
assert(result.ok === true,
|
|
602
|
+
'live request failed: ' + result.status + ' ' + JSON.stringify(result.data))
|
|
603
|
+
assert(result.status >= 200 && result.status < 300)
|
|
604
|
+
assert(null != result.data)
|
|
605
|
+
} else {
|
|
606
|
+
${offlineChecks} }` :
|
|
547
607
|
` if (setup.live) {
|
|
548
608
|
// Live mode is lenient: synthetic IDs frequently 4xx and the list-
|
|
549
609
|
// response shape varies wildly across public APIs. Skip rather than
|