@voxgig/sdkgen 4.6.0 → 4.8.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/cmp/Feature.js +5 -0
- package/dist/cmp/Feature.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/featureSource.d.ts +3 -1
- package/dist/helpers/featureSource.js +105 -0
- package/dist/helpers/featureSource.js.map +1 -1
- package/dist/helpers/opShape.js +8 -11
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/helpers/pointPath.d.ts +10 -0
- package/dist/helpers/pointPath.js +54 -0
- package/dist/helpers/pointPath.js.map +1 -0
- package/dist/sdkgen.d.ts +6 -3
- package/dist/sdkgen.js +14 -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 +78 -1
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aon +58 -0
- package/package.json +2 -2
- package/project/.sdk/model/feature/secrets.aon +82 -0
- package/project/.sdk/src/cmp/c/Config_c.ts +7 -8
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +4 -3
- package/project/.sdk/src/cmp/cpp/Main_cpp.ts +2 -1
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +4 -3
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +5 -1
- package/project/.sdk/src/cmp/csharp/Main_csharp.ts +2 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +34 -9
- 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 +7 -8
- package/project/.sdk/src/cmp/dart/Main_dart.ts +2 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +28 -10
- 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 +9 -8
- package/project/.sdk/src/cmp/go/Config_go.ts +1 -7
- package/project/.sdk/src/cmp/go/Main_go.ts +2 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +5 -4
- package/project/.sdk/src/cmp/go/Test_go.ts +5 -1
- package/project/.sdk/src/cmp/java/Config_java.ts +7 -7
- package/project/.sdk/src/cmp/java/Main_java.ts +2 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +5 -4
- package/project/.sdk/src/cmp/java/Test_java.ts +5 -1
- package/project/.sdk/src/cmp/js/Config_js.ts +7 -8
- package/project/.sdk/src/cmp/js/Main_js.ts +2 -1
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +34 -8
- 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 +7 -7
- package/project/.sdk/src/cmp/kotlin/Main_kotlin.ts +2 -1
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +5 -4
- package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +5 -1
- package/project/.sdk/src/cmp/lean/Config_lean.ts +9 -8
- package/project/.sdk/src/cmp/lua/Config_lua.ts +1 -7
- package/project/.sdk/src/cmp/lua/Main_lua.ts +2 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +32 -7
- 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/Gitignore_ocaml.ts +1 -0
- package/project/.sdk/src/cmp/perl/Main_perl.ts +2 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +29 -7
- 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 +1 -7
- package/project/.sdk/src/cmp/php/Main_php.ts +2 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +28 -8
- 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 +1 -7
- package/project/.sdk/src/cmp/py/Main_py.ts +2 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +5 -4
- package/project/.sdk/src/cmp/py/Test_py.ts +5 -1
- package/project/.sdk/src/cmp/rb/Config_rb.ts +1 -7
- package/project/.sdk/src/cmp/rb/Main_rb.ts +2 -1
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +28 -8
- 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/Main_rust.ts +2 -1
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +35 -7
- 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 +9 -7
- package/project/.sdk/src/cmp/scala/Main_scala.ts +2 -1
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +4 -3
- package/project/.sdk/src/cmp/scala/Test_scala.ts +5 -1
- package/project/.sdk/src/cmp/seneca-provider/Extras_seneca-provider.ts +3 -1
- package/project/.sdk/src/cmp/seneca-provider/Main_seneca-provider.ts +9 -5
- package/project/.sdk/src/cmp/ts/Config_ts.ts +57 -16
- package/project/.sdk/src/cmp/ts/Main_ts.ts +10 -2
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +15 -7
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +11 -3
- package/project/.sdk/src/cmp/ts/Test_ts.ts +5 -1
- package/project/.sdk/tm/csharp/test/Runner.cs +45 -0
- package/project/.sdk/tm/dart/test/utility.dart +39 -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/lua/test/runner.lua +40 -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/php/test/Runner.php +36 -0
- package/project/.sdk/tm/rb/test/runner.rb +25 -0
- package/project/.sdk/tm/rust/tests/common/mod.rs +32 -0
- package/project/.sdk/tm/rust/utility/make_options.rs +1 -1
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +8 -2
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sigv4.ts +29 -5
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +30 -21
- 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/test/vendor/omni/Runner.ts +15 -13
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +25 -19
- package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +1 -1
- package/project/.sdk/tm/ts/test/vendor/omni/index.ts +1 -1
- package/project/.sdk/tm/zig/core/utility.zig +1 -1
- package/project/sdkgen-package.json +1 -1
- package/src/cmp/Feature.ts +5 -0
- package/src/cmp/TestControl.ts +64 -0
- package/src/helpers/featureSource.ts +130 -0
- package/src/helpers/opShape.ts +9 -14
- package/src/helpers/pointPath.ts +88 -0
- package/src/sdkgen.ts +18 -0
- package/src/utility.ts +92 -1
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Providers.ts +0 -1221
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, entityCollection
|
|
6
|
+
import { cmp, each, Folder, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_csharp'
|
|
@@ -21,6 +22,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
21
22
|
// tests are generated here.
|
|
22
23
|
Folder({ name: 'test' }, () => {
|
|
23
24
|
|
|
25
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
26
|
+
TestControl({ target, dir: 'test' })
|
|
27
|
+
|
|
24
28
|
const entity = each(entityCollection(model))
|
|
25
29
|
.filter((e: any) => false !== e.active)
|
|
26
30
|
|
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
import {
|
|
29
|
-
clean,
|
|
30
29
|
dartStringLiteral,
|
|
31
30
|
dartValue,
|
|
32
31
|
} from './utility_dart'
|
|
@@ -159,13 +158,13 @@ const Config = cmp(async function Config(props: any) {
|
|
|
159
158
|
Line(` '${entity.name}': <String, dynamic>{},`)
|
|
160
159
|
}),
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
// configDefinition's `def.entity` verbatim, NOT rebuilt here. This
|
|
162
|
+
// reduce was a second copy of that function's entityDefs loop, and
|
|
163
|
+
// when configDefinition started reconstructing a point's `parts`
|
|
164
|
+
// from apidef's segment vector (its ADR-003), only the data
|
|
165
|
+
// representation got it — the literal one emitted empty paths. The
|
|
166
|
+
// config-repr equivalence test caught it, which is what it is for.
|
|
167
|
+
"'ENTITYMAP'": dartValue(configDef.entity, 1),
|
|
169
168
|
}
|
|
170
169
|
})
|
|
171
170
|
})
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each,
|
|
6
6
|
List, File, Copy, Folder, Fragment, Line,
|
|
7
7
|
entityClassName, entityCollection,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -45,7 +46,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
45
46
|
// lib/feature/), so they are excluded from the generated package.
|
|
46
47
|
Copy({
|
|
47
48
|
from: 'tm/' + target.name,
|
|
48
|
-
exclude: [/src
|
|
49
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
49
50
|
replace: {
|
|
50
51
|
...props.ctx$.stdrep,
|
|
51
52
|
}
|
|
@@ -16,14 +16,16 @@ import {
|
|
|
16
16
|
Slot,
|
|
17
17
|
cmp,
|
|
18
18
|
snakify,
|
|
19
|
-
isAuthActive, envName, envToken
|
|
19
|
+
isAuthActive, envName, envToken,
|
|
20
|
+
serverVarEnv,
|
|
21
|
+
serverVariables,
|
|
22
|
+
pointParts,
|
|
20
23
|
} from '@voxgig/sdkgen'
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
import {
|
|
24
27
|
projectPath,
|
|
25
|
-
dartValue,
|
|
26
|
-
} from './utility_dart'
|
|
28
|
+
dartValue, dartStringLiteral} from './utility_dart'
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
const TestDirect = cmp(function TestDirect(props: any) {
|
|
@@ -40,13 +42,26 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
40
42
|
|
|
41
43
|
const authActive = isAuthActive(model)
|
|
42
44
|
const apikeyEnvEntry = authActive
|
|
43
|
-
? `\n '${PROJECTNAME}_APIKEY': '
|
|
45
|
+
? `\n '${PROJECTNAME}_APIKEY': '',`
|
|
44
46
|
: ''
|
|
45
47
|
const apikeyLiveField = authActive
|
|
46
48
|
? `
|
|
47
49
|
'apikey': env['${PROJECTNAME}_APIKEY'],`
|
|
48
50
|
: ''
|
|
49
51
|
|
|
52
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
53
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
54
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
55
|
+
// takes them from the environment the same way it takes the apikey.
|
|
56
|
+
const svars = serverVariables(model)
|
|
57
|
+
const serverEnvEntry = svars
|
|
58
|
+
.map((v: any) => `\n '${serverVarEnv(PROJECTNAME, v.name)}': ${dartStringLiteral(v.dflt)},`).join('')
|
|
59
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
60
|
+
'server': <String, dynamic>{${svars
|
|
61
|
+
.map((v: any) => `
|
|
62
|
+
'${v.name}': env['${serverVarEnv(PROJECTNAME, v.name)}'],`).join('')}
|
|
63
|
+
},`
|
|
64
|
+
|
|
50
65
|
const opnames = Object.keys(entity.op || {})
|
|
51
66
|
const hasLoad = opnames.includes('load')
|
|
52
67
|
const hasList = opnames.includes('list')
|
|
@@ -78,13 +93,16 @@ Map<String, dynamic> directSetup([dynamic mockres]) {
|
|
|
78
93
|
|
|
79
94
|
final env = envOverride({
|
|
80
95
|
'${entidEnvVar}': <String, dynamic>{},
|
|
81
|
-
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}
|
|
96
|
+
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}${serverEnvEntry}
|
|
82
97
|
});
|
|
83
98
|
|
|
84
99
|
final live = 'TRUE' == env['${PROJECTNAME}_TEST_LIVE'];
|
|
85
100
|
|
|
86
101
|
if (live) {
|
|
87
|
-
|
|
102
|
+
// Spread FIRST, so the generated fields below win: sdk-test-control.json's
|
|
103
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
104
|
+
final client = ${nom(model.const, 'Name')}SDK(<String, dynamic>{
|
|
105
|
+
...liveClientOptions(),${apikeyLiveField}${serverLiveField}
|
|
88
106
|
});
|
|
89
107
|
|
|
90
108
|
dynamic idmap = env['${entidEnvVar}'];
|
|
@@ -165,12 +183,12 @@ function generateDirectLoad(model: Model, entity: ModelEntity) {
|
|
|
165
183
|
}
|
|
166
184
|
|
|
167
185
|
const allLoadParams = loadPoint.args?.params || []
|
|
168
|
-
const loadPath = normalizePathParams(loadPoint
|
|
186
|
+
const loadPath = normalizePathParams(pointParts(loadPoint), allLoadParams, loadPoint.rename?.param)
|
|
169
187
|
|
|
170
188
|
// Only path params that actually appear in the URL template drive the
|
|
171
189
|
// direct-test path-param setup and URL-substitution asserts.
|
|
172
190
|
const pathPlaceholders = new Set<string>()
|
|
173
|
-
for (const part of (loadPoint
|
|
191
|
+
for (const part of pointParts(loadPoint)) {
|
|
174
192
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
175
193
|
pathPlaceholders.add(part.slice(1, -1))
|
|
176
194
|
}
|
|
@@ -200,7 +218,7 @@ function generateDirectLoad(model: Model, entity: ModelEntity) {
|
|
|
200
218
|
const listOp = entity.op?.list
|
|
201
219
|
const listPoint = listOp?.points?.[0]
|
|
202
220
|
const listParams = listPoint?.args?.params || []
|
|
203
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
221
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listParams, listPoint.rename?.param) : ''
|
|
204
222
|
const hasList = null != listPoint
|
|
205
223
|
|
|
206
224
|
// Ancestor params (not 'id') for live mode
|
|
@@ -358,7 +376,7 @@ function generateDirectList(model: Model, entity: ModelEntity) {
|
|
|
358
376
|
}
|
|
359
377
|
|
|
360
378
|
const listParams = listPoint.args?.params || []
|
|
361
|
-
const listPath = normalizePathParams(listPoint
|
|
379
|
+
const listPath = normalizePathParams(pointParts(listPoint), listParams, listPoint.rename?.param)
|
|
362
380
|
|
|
363
381
|
const listQuery = listPoint.args?.query || []
|
|
364
382
|
const liveQueryLines = listQuery
|
|
@@ -23,13 +23,14 @@ import {
|
|
|
23
23
|
Slot,
|
|
24
24
|
cmp,
|
|
25
25
|
each,
|
|
26
|
-
isAuthActive, envName, envToken
|
|
26
|
+
isAuthActive, envName, envToken,
|
|
27
|
+
serverVarEnv,
|
|
28
|
+
serverVariables
|
|
27
29
|
} from '@voxgig/sdkgen'
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
import {
|
|
31
|
-
projectPath
|
|
32
|
-
} from './utility_dart'
|
|
33
|
+
projectPath, dartStringLiteral} from './utility_dart'
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
// GenCtx is the per-language generation context passed to every OpGen.
|
|
@@ -54,13 +55,26 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
54
55
|
const ENTENVNAME = envToken(entity.name)
|
|
55
56
|
const authActive = isAuthActive(model)
|
|
56
57
|
const apikeyEnvEntry = authActive
|
|
57
|
-
? `\n '${PROJENVNAME}_APIKEY': '
|
|
58
|
+
? `\n '${PROJENVNAME}_APIKEY': '',`
|
|
58
59
|
: ''
|
|
59
60
|
const apikeyLiveField = authActive
|
|
60
61
|
? `
|
|
61
62
|
'apikey': env['${PROJENVNAME}_APIKEY'],`
|
|
62
63
|
: ''
|
|
63
64
|
|
|
65
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
66
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
67
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
68
|
+
// takes them from the environment the same way it takes the apikey.
|
|
69
|
+
const svars = serverVariables(model)
|
|
70
|
+
const serverEnvEntry = svars
|
|
71
|
+
.map((v: any) => `\n '${serverVarEnv(PROJENVNAME, v.name)}': ${dartStringLiteral(v.dflt)},`).join('')
|
|
72
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
73
|
+
'server': <String, dynamic>{${svars
|
|
74
|
+
.map((v: any) => `
|
|
75
|
+
'${v.name}': env['${serverVarEnv(PROJENVNAME, v.name)}'],`).join('')}
|
|
76
|
+
},`
|
|
77
|
+
|
|
64
78
|
const ff = projectPath('src/cmp/dart/fragment/')
|
|
65
79
|
|
|
66
80
|
Folder({ name: entity.name }, () => {
|
|
@@ -191,7 +205,7 @@ Map<String, dynamic> basicSetup([dynamic extra]) {
|
|
|
191
205
|
final env = envOverride({
|
|
192
206
|
'${PROJENVNAME}_TEST_${ENTENVNAME}_ENTID': idmap,
|
|
193
207
|
'${PROJENVNAME}_TEST_LIVE': 'FALSE',
|
|
194
|
-
'${PROJENVNAME}_TEST_EXPLAIN': 'FALSE',${apikeyEnvEntry}
|
|
208
|
+
'${PROJENVNAME}_TEST_EXPLAIN': 'FALSE',${apikeyEnvEntry}${serverEnvEntry}
|
|
195
209
|
});
|
|
196
210
|
|
|
197
211
|
idmap = env['${PROJENVNAME}_TEST_${ENTENVNAME}_ENTID'];
|
|
@@ -200,9 +214,16 @@ Map<String, dynamic> basicSetup([dynamic extra]) {
|
|
|
200
214
|
|
|
201
215
|
if (live) {
|
|
202
216
|
client = ${model.Name}SDK(merge([
|
|
203
|
-
|
|
217
|
+
// FIRST, so the generated fields below win: sdk-test-control.json's
|
|
218
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
219
|
+
liveClientOptions(),
|
|
220
|
+
<String, dynamic>{${apikeyLiveField}${serverLiveField}
|
|
204
221
|
},
|
|
205
|
-
extra
|
|
222
|
+
// 'extra ?? {}', not a bare 'extra': merge returns null when the last
|
|
223
|
+
// entry is null, and basicSetup is normally called with no argument at
|
|
224
|
+
// all - so a bare 'extra' silently discarded the apikey and server
|
|
225
|
+
// values above and handed the SDK null.
|
|
226
|
+
extra ?? <String, dynamic>{}
|
|
206
227
|
]));
|
|
207
228
|
}
|
|
208
229
|
|
|
@@ -7,7 +7,8 @@ import type {
|
|
|
7
7
|
ModelEntity
|
|
8
8
|
} from '@voxgig/apidef'
|
|
9
9
|
|
|
10
|
-
import { cmp, each, snakify, Folder, File, Content, entityCollection
|
|
10
|
+
import { cmp, each, snakify, Folder, File, Content, entityCollection,
|
|
11
|
+
TestControl } from '@voxgig/sdkgen'
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
import { TestDirect } from './TestDirect_dart'
|
|
@@ -24,6 +25,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
24
25
|
|
|
25
26
|
Folder({ name: 'test' }, () => {
|
|
26
27
|
|
|
28
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
29
|
+
TestControl({ target, dir: 'test' })
|
|
30
|
+
|
|
27
31
|
// Suite entry: registers every static suite plus the generated
|
|
28
32
|
// per-entity suites, then runs them (Makefile: dart run test/main.dart).
|
|
29
33
|
File({ name: 'main.' + target.ext }, () => {
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
|
-
clean,
|
|
26
25
|
formatElixir,
|
|
27
26
|
elixirString,
|
|
28
27
|
} from './utility_elixir'
|
|
@@ -53,13 +52,6 @@ const Config = cmp(async function Config(props: any) {
|
|
|
53
52
|
? ` "auth" => %{"prefix" => ${elixirString(authPrefix)}},\n`
|
|
54
53
|
: ''
|
|
55
54
|
|
|
56
|
-
const entityClean = Object.values(entity).reduce((a: any, n: any) => (a[n.name] = clean({
|
|
57
|
-
fields: n.fields,
|
|
58
|
-
name: n.name,
|
|
59
|
-
op: n.op,
|
|
60
|
-
relations: n.relations,
|
|
61
|
-
}, true), a), {})
|
|
62
|
-
|
|
63
55
|
Folder({ name: 'lib' }, () => {
|
|
64
56
|
// The same config as an OBJECT, built by the shared helper so this
|
|
65
57
|
// target's literal and the data that replaces it above the threshold are
|
|
@@ -72,6 +64,15 @@ const Config = cmp(async function Config(props: any) {
|
|
|
72
64
|
const { def: configDef, json: configJson } = configDefinition(model, target.name)
|
|
73
65
|
const asData = isConfigData(configJson, configReprSetting(model))
|
|
74
66
|
|
|
67
|
+
// configDefinition's `def.entity` verbatim, NOT rebuilt here. The reduce
|
|
68
|
+
// this replaces was one of fourteen copies of that function's entityDefs
|
|
69
|
+
// loop, and when configDefinition started reconstructing a point's
|
|
70
|
+
// `parts` from apidef's segment vector (its ADR-003), only the copies
|
|
71
|
+
// that read `configDef` got it — this target's literal config emitted
|
|
72
|
+
// paths with no parts at all while its data config had them. One rule,
|
|
73
|
+
// one place.
|
|
74
|
+
const entityClean = configDef.entity
|
|
75
|
+
|
|
75
76
|
File({ name: 'config.ex' }, () => {
|
|
76
77
|
|
|
77
78
|
// ABOVE THE THRESHOLD: emit the model as DATA.
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
Line,
|
|
10
10
|
cmp,
|
|
11
11
|
each,
|
|
12
|
-
clean,
|
|
13
12
|
configDefinition,
|
|
14
13
|
configReprSetting,
|
|
15
14
|
isAuthActive,
|
|
@@ -200,12 +199,7 @@ ${serverBlock}${authBlock} "headers": ${formatGoMap(headers, 3)},
|
|
|
200
199
|
Content(` },
|
|
201
200
|
},
|
|
202
201
|
"entity": ${formatGoMap(
|
|
203
|
-
|
|
204
|
-
fields: n.fields,
|
|
205
|
-
name: n.name,
|
|
206
|
-
op: n.op,
|
|
207
|
-
relations: n.relations,
|
|
208
|
-
}, true), a), {}), 2)},
|
|
202
|
+
configDef.entity, 2)},
|
|
209
203
|
}
|
|
210
204
|
}
|
|
211
205
|
`)
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
entityClassName, entityCollection, goModule, goPackageIdent,
|
|
8
8
|
targetFeatures,
|
|
9
|
+
TEST_CONTROL_EXCLUDE
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
|
|
@@ -59,7 +60,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
59
60
|
// downstream consumers.
|
|
60
61
|
Copy({
|
|
61
62
|
from: 'tm/' + target.name,
|
|
62
|
-
exclude: [/src\//, /utility\/struct\/go\.mod
|
|
63
|
+
exclude: [/src\//, /utility\/struct\/go\.mod$/, TEST_CONTROL_EXCLUDE],
|
|
63
64
|
replace: {
|
|
64
65
|
...props.ctx$.stdrep,
|
|
65
66
|
GOMODULE: gomodule,
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
snakify,
|
|
14
14
|
isAuthActive,
|
|
15
15
|
serverVarEnv,
|
|
16
|
-
serverVariables, envName, envToken, liveStrict
|
|
16
|
+
serverVariables, envName, envToken, liveStrict,
|
|
17
|
+
pointParts,
|
|
17
18
|
} from '@voxgig/sdkgen'
|
|
18
19
|
|
|
19
20
|
|
|
@@ -109,7 +110,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
109
110
|
// Get load point info
|
|
110
111
|
const loadPoint = loadOp?.points?.[0]
|
|
111
112
|
const loadIsGraphql = 'graphql' === (loadPoint as any)?.kind
|
|
112
|
-
const loadPath = loadPoint ? normalizePathParams(loadPoint
|
|
113
|
+
const loadPath = loadPoint ? normalizePathParams(pointParts(loadPoint), loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
113
114
|
const allLoadParams = loadPoint?.args?.params || []
|
|
114
115
|
// Some upstream OpenAPI specs declare a parameter as `in: path` even when
|
|
115
116
|
// that path has no `{name}` placeholder for it. Only path params that
|
|
@@ -117,7 +118,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
117
118
|
// setup and URL-substitution asserts; otherwise the SDK silently drops
|
|
118
119
|
// them and the URL-includes assert fails.
|
|
119
120
|
const _pathPlaceholders = new Set<string>()
|
|
120
|
-
for (const part of (loadPoint
|
|
121
|
+
for (const part of pointParts(loadPoint)) {
|
|
121
122
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
122
123
|
_pathPlaceholders.add(part.slice(1, -1))
|
|
123
124
|
}
|
|
@@ -136,7 +137,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
136
137
|
// Get list point info
|
|
137
138
|
const listPoint = listOp?.points?.[0]
|
|
138
139
|
const listIsGraphql = 'graphql' === (listPoint as any)?.kind
|
|
139
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
140
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
140
141
|
const listParams = listPoint?.args?.params || []
|
|
141
142
|
|
|
142
143
|
// Required query params with spec-provided examples — needed in live mode
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, File, Content, goModule, entityCollection
|
|
6
|
+
import { cmp, each, Folder, File, Content, goModule, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_go'
|
|
@@ -21,6 +22,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
21
22
|
|
|
22
23
|
Folder({ name: 'test' }, () => {
|
|
23
24
|
|
|
25
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
26
|
+
TestControl({ target, dir: 'test' })
|
|
27
|
+
|
|
24
28
|
// Generate exists_test.go programmatically to avoid duplication
|
|
25
29
|
// with any scaffolded test file (e.g. projectname_sdk_test.go).
|
|
26
30
|
File({ name: 'exists_test.' + target.ext }, () => {
|
|
@@ -98,13 +98,13 @@ const Config = cmp(async function Config(props: any) {
|
|
|
98
98
|
options.headers = headers
|
|
99
99
|
options.entity = optionsEntity
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
// configDefinition's `def.entity` verbatim, NOT rebuilt here. This reduce
|
|
102
|
+
// was one of fourteen copies of that function's entityDefs loop, and when
|
|
103
|
+
// configDefinition started reconstructing a point's `parts` from apidef's
|
|
104
|
+
// segment vector (its ADR-003), only the copies that read `configDef` got
|
|
105
|
+
// it — this target's literal config emitted paths with no parts at all
|
|
106
|
+
// while its data config had them. One rule, one place.
|
|
107
|
+
const entityConfig = configDef.entity
|
|
108
108
|
|
|
109
109
|
const config = {
|
|
110
110
|
main: configDef.main,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each,
|
|
6
6
|
File, Content, Copy, Folder, Fragment,
|
|
7
7
|
targetFeatures,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -52,7 +53,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
52
53
|
// token used throughout the templates (package/import statements).
|
|
53
54
|
Copy({
|
|
54
55
|
from: 'tm/' + target.name,
|
|
55
|
-
exclude: [/src
|
|
56
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
56
57
|
replace: {
|
|
57
58
|
...props.ctx$.stdrep,
|
|
58
59
|
JAVAPACKAGE: javapackage,
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
snakify,
|
|
14
14
|
isAuthActive,
|
|
15
15
|
serverVarEnv,
|
|
16
|
-
serverVariables, envName, envToken
|
|
16
|
+
serverVariables, envName, envToken,
|
|
17
|
+
pointParts,
|
|
17
18
|
} from '@voxgig/sdkgen'
|
|
18
19
|
|
|
19
20
|
|
|
@@ -116,12 +117,12 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
116
117
|
|
|
117
118
|
// Get load point info
|
|
118
119
|
const loadPoint = loadOp?.points?.[0]
|
|
119
|
-
const loadPath = loadPoint ? normalizePathParams(loadPoint
|
|
120
|
+
const loadPath = loadPoint ? normalizePathParams(pointParts(loadPoint), loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
120
121
|
const allLoadParams = loadPoint?.args?.params || []
|
|
121
122
|
// Only path params that actually appear in the URL template drive
|
|
122
123
|
// direct-test path-param setup and URL-substitution asserts.
|
|
123
124
|
const _pathPlaceholders = new Set<string>()
|
|
124
|
-
for (const part of (loadPoint
|
|
125
|
+
for (const part of pointParts(loadPoint)) {
|
|
125
126
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
126
127
|
_pathPlaceholders.add(part.slice(1, -1))
|
|
127
128
|
}
|
|
@@ -139,7 +140,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
139
140
|
|
|
140
141
|
// Get list point info
|
|
141
142
|
const listPoint = listOp?.points?.[0]
|
|
142
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
143
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
143
144
|
const listParams = listPoint?.args?.params || []
|
|
144
145
|
|
|
145
146
|
// Required query params with spec-provided examples — needed in live mode.
|
|
@@ -3,7 +3,8 @@ import type {
|
|
|
3
3
|
ModelEntity
|
|
4
4
|
} from '@voxgig/apidef'
|
|
5
5
|
|
|
6
|
-
import { cmp, each, Folder, entityCollection
|
|
6
|
+
import { cmp, each, Folder, entityCollection,
|
|
7
|
+
TestControl } from '@voxgig/sdkgen'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
import { TestEntity } from './TestEntity_java'
|
|
@@ -20,6 +21,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
20
21
|
|
|
21
22
|
Folder({ name: 'test' }, () => {
|
|
22
23
|
|
|
24
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
25
|
+
TestControl({ target, dir: 'test' })
|
|
26
|
+
|
|
23
27
|
// The shared test infrastructure (RunnerSupport, FeatureHarness,
|
|
24
28
|
// PipelineTest, FeatureTest, NetsimTest, PrimaryUtilityTest,
|
|
25
29
|
// CustomUtilityTest, StructRunner/StructCorpusTest, ExistsTest and
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
Fragment,
|
|
9
9
|
Line,
|
|
10
10
|
cmp,
|
|
11
|
-
clean,
|
|
12
11
|
configDefinition,
|
|
13
12
|
configReprSetting,
|
|
14
13
|
each,
|
|
@@ -161,13 +160,13 @@ const Config = cmp(async function Config(props: any) {
|
|
|
161
160
|
`)
|
|
162
161
|
}),
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
163
|
+
// configDefinition's `def.entity` verbatim, NOT rebuilt here. This
|
|
164
|
+
// reduce was a second copy of that function's entityDefs loop, and
|
|
165
|
+
// when configDefinition started reconstructing a point's `parts`
|
|
166
|
+
// from apidef's segment vector (its ADR-003), only the data
|
|
167
|
+
// representation got it — the literal one emitted empty paths. The
|
|
168
|
+
// config-repr equivalence test caught it, which is what it is for.
|
|
169
|
+
"'ENTITYMAP'": formatJson(configDef.entity, { margin: 2 }).trim(),
|
|
171
170
|
}
|
|
172
171
|
})
|
|
173
172
|
})
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
entityClassName, entityCollection, srcFeatureExcludes, stationLibrary,
|
|
8
8
|
targetFeatures,
|
|
9
|
+
TEST_CONTROL_EXCLUDE
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
|
|
@@ -49,7 +50,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
49
50
|
from: 'tm/' + target.name,
|
|
50
51
|
// Root copies src/feature/<name>/ per ACTIVE feature; keep this blanket
|
|
51
52
|
// copy from restoring one that was switched off after `target add`.
|
|
52
|
-
exclude: srcFeatureExcludes(model),
|
|
53
|
+
exclude: [...srcFeatureExcludes(model), TEST_CONTROL_EXCLUDE],
|
|
53
54
|
replace: {
|
|
54
55
|
...props.ctx$.stdrep,
|
|
55
56
|
}
|
|
@@ -17,7 +17,11 @@ import {
|
|
|
17
17
|
cmp,
|
|
18
18
|
snakify,
|
|
19
19
|
isAuthActive,
|
|
20
|
-
|
|
20
|
+
serverVarEnv,
|
|
21
|
+
serverVariables,
|
|
22
|
+
jsProp, envName, envToken,
|
|
23
|
+
jsKey,
|
|
24
|
+
pointParts,
|
|
21
25
|
} from '@voxgig/sdkgen'
|
|
22
26
|
|
|
23
27
|
|
|
@@ -41,13 +45,32 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
41
45
|
|
|
42
46
|
const authActive = isAuthActive(model)
|
|
43
47
|
const apikeyEnvEntry = authActive
|
|
44
|
-
? `\n '${PROJECTNAME}_APIKEY': '
|
|
48
|
+
? `\n '${PROJECTNAME}_APIKEY': '',`
|
|
45
49
|
: ''
|
|
46
50
|
const apikeyLiveField = authActive
|
|
47
51
|
? `
|
|
48
52
|
apikey: env.${PROJECTNAME}_APIKEY,`
|
|
49
53
|
: ''
|
|
50
54
|
|
|
55
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
56
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
57
|
+
// request a URL with a literal `{account_id}` in it. Taken from the
|
|
58
|
+
// environment, the same way the apikey is.
|
|
59
|
+
//
|
|
60
|
+
// Keys are quoted and the env read is bracketed via jsKey/jsProp: a server
|
|
61
|
+
// variable name is spec-derived and need not be a JS identifier — the URL
|
|
62
|
+
// grammar admits a leading digit ({2fa}), and a declared-but-unreferenced
|
|
63
|
+
// variable ({edge-zone}) is not constrained at all. Bare `name:` and
|
|
64
|
+
// `env.PROJ_SERVER_EDGE-ZONE` are both syntax errors.
|
|
65
|
+
const svars = serverVariables(model)
|
|
66
|
+
const serverEnvEntry = svars
|
|
67
|
+
.map((v: any) => `\n '${serverVarEnv(PROJECTNAME, v.name)}': ${JSON.stringify(v.dflt)},`).join('')
|
|
68
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
69
|
+
server: {${svars
|
|
70
|
+
.map((v: any) => `
|
|
71
|
+
${jsKey(v.name)}: ${jsProp('env', serverVarEnv(PROJECTNAME, v.name))},`).join('')}
|
|
72
|
+
},`
|
|
73
|
+
|
|
51
74
|
const opnames = Object.keys(entity.op || {})
|
|
52
75
|
const hasLoad = opnames.includes('load')
|
|
53
76
|
const hasList = opnames.includes('list')
|
|
@@ -78,14 +101,17 @@ function directSetup(mockres) {
|
|
|
78
101
|
|
|
79
102
|
const env = envOverride({
|
|
80
103
|
'${entidEnvVar}': {},
|
|
81
|
-
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}
|
|
104
|
+
'${PROJECTNAME}_TEST_LIVE': 'FALSE',${apikeyEnvEntry}${serverEnvEntry}
|
|
82
105
|
})
|
|
83
106
|
|
|
84
107
|
const live = 'TRUE' === env.${PROJECTNAME}_TEST_LIVE
|
|
85
108
|
|
|
86
109
|
if (live) {
|
|
87
|
-
|
|
88
|
-
|
|
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
|
+
}))
|
|
89
115
|
|
|
90
116
|
let idmap = env['${entidEnvVar}']
|
|
91
117
|
if ('string' === typeof idmap && idmap.startsWith('{')) {
|
|
@@ -147,13 +173,13 @@ function generateDirectLoad(model: Model, entity: ModelEntity) {
|
|
|
147
173
|
}
|
|
148
174
|
|
|
149
175
|
const loadParams = loadPoint.args?.params || []
|
|
150
|
-
const loadPath = normalizePathParams(loadPoint
|
|
176
|
+
const loadPath = normalizePathParams(pointParts(loadPoint), loadParams, loadPoint.rename?.param)
|
|
151
177
|
|
|
152
178
|
// Get list info for live mode bootstrapping
|
|
153
179
|
const listOp = entity.op?.list
|
|
154
180
|
const listPoint = listOp?.points?.[0]
|
|
155
181
|
const listParams = listPoint?.args?.params || []
|
|
156
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
182
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listParams, listPoint.rename?.param) : ''
|
|
157
183
|
const hasList = null != listPoint
|
|
158
184
|
|
|
159
185
|
// Ancestor params (not 'id') for live mode
|
|
@@ -249,7 +275,7 @@ function generateDirectList(model: Model, entity: ModelEntity) {
|
|
|
249
275
|
}
|
|
250
276
|
|
|
251
277
|
const listParams = listPoint.args?.params || []
|
|
252
|
-
const listPath = normalizePathParams(listPoint
|
|
278
|
+
const listPath = normalizePathParams(pointParts(listPoint), listParams, listPoint.rename?.param)
|
|
253
279
|
|
|
254
280
|
// Build live params
|
|
255
281
|
const liveParams = listParams.map((p: any) => {
|