@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
|
@@ -17,9 +17,13 @@ import {
|
|
|
17
17
|
each,
|
|
18
18
|
buildIdNames,
|
|
19
19
|
getMatchEntries,
|
|
20
|
-
isAuthActive, envName, envToken
|
|
20
|
+
isAuthActive, envName, envToken,
|
|
21
|
+
serverVarEnv,
|
|
22
|
+
serverVariables
|
|
21
23
|
} from '@voxgig/sdkgen'
|
|
22
24
|
|
|
25
|
+
import { perlStringLiteral } from './utility_perl'
|
|
26
|
+
|
|
23
27
|
|
|
24
28
|
// See TestEntity_ts.ts for the GenCtx/OpGen contract. Flow-step variables
|
|
25
29
|
// are held in a single declared perl hash (%V) so generated steps never
|
|
@@ -54,12 +58,25 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
54
58
|
|
|
55
59
|
const authActive = isAuthActive(model)
|
|
56
60
|
const apikeyEnvEntry = authActive
|
|
57
|
-
? `\n '${PROJUPPER}_APIKEY' => '
|
|
61
|
+
? `\n '${PROJUPPER}_APIKEY' => '',`
|
|
58
62
|
: ''
|
|
59
63
|
const apikeyLiveField = authActive
|
|
60
64
|
? `\n 'apikey' => $env->{'${PROJUPPER}_APIKEY'},`
|
|
61
65
|
: ''
|
|
62
66
|
|
|
67
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
68
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
69
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
70
|
+
// takes them from the environment the same way it takes the apikey.
|
|
71
|
+
const svars = serverVariables(model)
|
|
72
|
+
const serverEnvEntry = svars
|
|
73
|
+
.map((v: any) => `\n '${serverVarEnv(PROJUPPER, v.name)}' => ${perlStringLiteral(v.dflt)},`).join('')
|
|
74
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
75
|
+
'server' => {${svars
|
|
76
|
+
.map((v: any) => `
|
|
77
|
+
'${v.name}' => $env->{'${serverVarEnv(PROJUPPER, v.name)}'},`).join('')}
|
|
78
|
+
},`
|
|
79
|
+
|
|
63
80
|
const idnames = buildIdNames(entity, basicflow)
|
|
64
81
|
const idnamesStr = idnames.map(n => `'${n}'`).join(', ')
|
|
65
82
|
|
|
@@ -193,7 +210,7 @@ BASIC_FLOW: {
|
|
|
193
210
|
my $env = ${N}TestRunner::env_override({
|
|
194
211
|
'${ENTIDVAR}' => $idmap,
|
|
195
212
|
'${PROJUPPER}_TEST_LIVE' => 'FALSE',
|
|
196
|
-
'${PROJUPPER}_TEST_EXPLAIN' => 'FALSE',${apikeyEnvEntry}
|
|
213
|
+
'${PROJUPPER}_TEST_EXPLAIN' => 'FALSE',${apikeyEnvEntry}${serverEnvEntry}
|
|
197
214
|
});
|
|
198
215
|
|
|
199
216
|
my $idmap_resolved = ${N}Helpers::to_map($env->{'${ENTIDVAR}'});
|
|
@@ -213,7 +230,10 @@ BASIC_FLOW: {
|
|
|
213
230
|
Content(`
|
|
214
231
|
if ((($env->{'${PROJUPPER}_TEST_LIVE'}) || '') eq 'TRUE') {
|
|
215
232
|
my $merged_opts = Voxgig::Struct::merge([
|
|
216
|
-
|
|
233
|
+
# FIRST, so the generated fields below win: sdk-test-control.json's
|
|
234
|
+
# test.client.options adds to the live client, it does not redirect it.
|
|
235
|
+
${N}TestRunner::live_client_options(),
|
|
236
|
+
{${apikeyLiveField}${serverLiveField}
|
|
217
237
|
},
|
|
218
238
|
(Voxgig::Struct::ismap($extra) ? $extra : {}),
|
|
219
239
|
]);
|
|
@@ -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_perl'
|
|
@@ -17,6 +18,9 @@ const Test = cmp(function Test(props: any) {
|
|
|
17
18
|
|
|
18
19
|
Folder({ name: 't' }, () => {
|
|
19
20
|
|
|
21
|
+
// Write-once: a project's edited control file survives regeneration.
|
|
22
|
+
TestControl({ target, dir: 't' })
|
|
23
|
+
|
|
20
24
|
// Generate exists test
|
|
21
25
|
File({ name: 'exists.t' }, () => {
|
|
22
26
|
Content(`#!perl
|
|
@@ -75,7 +75,17 @@ function clean(o: any, dropDefaults?: boolean): any {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
// A Perl SINGLE-quoted string literal. Single quotes do not interpolate, so a
|
|
79
|
+
// spec-derived value containing $foo or @foo survives verbatim; only the
|
|
80
|
+
// backslash and the quote itself need escaping. A double-quoted literal (what
|
|
81
|
+
// JSON.stringify emits) would interpolate them.
|
|
82
|
+
function perlStringLiteral(val: string): string {
|
|
83
|
+
return "'" + String(val).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
78
87
|
export {
|
|
88
|
+
perlStringLiteral,
|
|
79
89
|
clean,
|
|
80
90
|
projectPath,
|
|
81
91
|
}
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
import {
|
|
32
|
-
clean,
|
|
33
32
|
formatPhpArray,
|
|
34
33
|
} from './utility_php'
|
|
35
34
|
|
|
@@ -239,12 +238,7 @@ ${serverBlock}${authBlock} "headers" => ${formatPhpArray(headers,
|
|
|
239
238
|
Content(` ],
|
|
240
239
|
],
|
|
241
240
|
"entity" => ${formatPhpArray(
|
|
242
|
-
|
|
243
|
-
fields: n.fields,
|
|
244
|
-
name: n.name,
|
|
245
|
-
op: n.op,
|
|
246
|
-
relations: n.relations,
|
|
247
|
-
}, true), a), {}), 3)},
|
|
241
|
+
configDef.entity, 3)},
|
|
248
242
|
];
|
|
249
243
|
`)
|
|
250
244
|
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
targetFeatures,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -44,7 +45,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
44
45
|
// Copy tm/php files with replacements
|
|
45
46
|
Copy({
|
|
46
47
|
from: 'tm/' + target.name,
|
|
47
|
-
exclude: [/src
|
|
48
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
48
49
|
replace: {
|
|
49
50
|
...props.ctx$.stdrep,
|
|
50
51
|
}
|
|
@@ -11,9 +11,14 @@ import {
|
|
|
11
11
|
File,
|
|
12
12
|
cmp,
|
|
13
13
|
snakify,
|
|
14
|
-
isAuthActive, envName, envToken
|
|
14
|
+
isAuthActive, envName, envToken,
|
|
15
|
+
serverVarEnv,
|
|
16
|
+
serverVariables,
|
|
17
|
+
pointParts,
|
|
15
18
|
} from '@voxgig/sdkgen'
|
|
16
19
|
|
|
20
|
+
import { formatPhpValue } from './utility_php'
|
|
21
|
+
|
|
17
22
|
|
|
18
23
|
function normalizePathParams(
|
|
19
24
|
parts: string[],
|
|
@@ -64,12 +69,25 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
64
69
|
|
|
65
70
|
const authActive = isAuthActive(model)
|
|
66
71
|
const apikeyEnvEntry = authActive
|
|
67
|
-
? `\n "${PROJECTNAME}_APIKEY" => "
|
|
72
|
+
? `\n "${PROJECTNAME}_APIKEY" => "",`
|
|
68
73
|
: ''
|
|
69
74
|
const apikeyLiveField = authActive
|
|
70
75
|
? `\n "apikey" => $env["${PROJECTNAME}_APIKEY"],`
|
|
71
76
|
: ''
|
|
72
77
|
|
|
78
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
79
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
80
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
81
|
+
// takes them from the environment the same way it takes the apikey.
|
|
82
|
+
const svars = serverVariables(model)
|
|
83
|
+
const serverEnvEntry = svars
|
|
84
|
+
.map((v: any) => `\n "${serverVarEnv(PROJECTNAME, v.name)}" => ${formatPhpValue(v.dflt)},`).join('')
|
|
85
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
86
|
+
"server" => [${svars
|
|
87
|
+
.map((v: any) => `
|
|
88
|
+
"${v.name}" => $env["${serverVarEnv(PROJECTNAME, v.name)}"],`).join('')}
|
|
89
|
+
],`
|
|
90
|
+
|
|
73
91
|
const opnames = Object.keys(entity.op || {})
|
|
74
92
|
const hasLoad = opnames.includes('load')
|
|
75
93
|
const hasList = opnames.includes('list')
|
|
@@ -82,7 +100,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
82
100
|
const listOp = entity.op?.list
|
|
83
101
|
|
|
84
102
|
const loadPoint = loadOp?.points?.[0]
|
|
85
|
-
const loadPath = loadPoint ? normalizePathParams(loadPoint
|
|
103
|
+
const loadPath = loadPoint ? normalizePathParams(pointParts(loadPoint), loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
86
104
|
const allLoadParams = loadPoint?.args?.params || []
|
|
87
105
|
// Some upstream OpenAPI specs declare a parameter as `in: path` even when
|
|
88
106
|
// that path has no `{name}` placeholder for it. Only path params that
|
|
@@ -90,7 +108,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
90
108
|
// setup and URL-substitution asserts; otherwise the SDK silently drops
|
|
91
109
|
// them and the URL-includes assert fails.
|
|
92
110
|
const _pathPlaceholders = new Set<string>()
|
|
93
|
-
for (const part of (loadPoint
|
|
111
|
+
for (const part of pointParts(loadPoint)) {
|
|
94
112
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
95
113
|
_pathPlaceholders.add(part.slice(1, -1))
|
|
96
114
|
}
|
|
@@ -107,7 +125,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
107
125
|
_renamedPlaceholders.has(p.name) || _renamedPlaceholders.has(p.orig))
|
|
108
126
|
|
|
109
127
|
const listPoint = listOp?.points?.[0]
|
|
110
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
128
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
111
129
|
const listParams = listPoint?.args?.params || []
|
|
112
130
|
|
|
113
131
|
// Required query params with spec-provided examples — needed in live mode.
|
|
@@ -356,14 +374,16 @@ function ${entity.name}_direct_setup($mockres)
|
|
|
356
374
|
|
|
357
375
|
$env = Runner::env_override([
|
|
358
376
|
"${entidEnvVar}" => [],
|
|
359
|
-
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}
|
|
377
|
+
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
360
378
|
]);
|
|
361
379
|
|
|
362
380
|
$live = $env["${PROJECTNAME}_TEST_LIVE"] === "TRUE";
|
|
363
381
|
|
|
364
382
|
if ($live) {
|
|
365
|
-
|
|
366
|
-
|
|
383
|
+
// Merged so the generated fields win: sdk-test-control.json's
|
|
384
|
+
// test.client.options adds to the live client, it does not redirect it.
|
|
385
|
+
$merged_opts = array_merge(Runner::live_client_options(), [${apikeyLiveField}${serverLiveField}
|
|
386
|
+
]);
|
|
367
387
|
$client = new ${model.const.Name}SDK($merged_opts);
|
|
368
388
|
return [
|
|
369
389
|
"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
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
import {
|
|
31
|
-
clean,
|
|
32
31
|
formatPyDict,
|
|
33
32
|
} from './utility_py'
|
|
34
33
|
|
|
@@ -180,12 +179,7 @@ ${serverBlock}${authBlock} "headers": ${formatPyDict(headers, 3)},
|
|
|
180
179
|
Content(` },
|
|
181
180
|
},
|
|
182
181
|
"entity": ${formatPyDict(
|
|
183
|
-
|
|
184
|
-
fields: n.fields,
|
|
185
|
-
name: n.name,
|
|
186
|
-
op: n.op,
|
|
187
|
-
relations: n.relations,
|
|
188
|
-
}, true), a), {}), 2)},
|
|
182
|
+
configDef.entity, 2)},
|
|
189
183
|
}
|
|
190
184
|
`)
|
|
191
185
|
})
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
entityClassName, entityCollection,
|
|
8
8
|
targetFeatures,
|
|
9
|
+
TEST_CONTROL_EXCLUDE
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
|
|
@@ -50,7 +51,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
50
51
|
// below.
|
|
51
52
|
Copy({
|
|
52
53
|
from: 'tm/' + target.name,
|
|
53
|
-
exclude: [/src\//, /pkg
|
|
54
|
+
exclude: [/src\//, /pkg\//, TEST_CONTROL_EXCLUDE],
|
|
54
55
|
replace: {
|
|
55
56
|
...props.ctx$.stdrep,
|
|
56
57
|
}
|
|
@@ -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
|
|
|
@@ -98,7 +99,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
98
99
|
const listOp = entity.op?.list
|
|
99
100
|
|
|
100
101
|
const loadPoint = loadOp?.points?.[0]
|
|
101
|
-
const loadPath = loadPoint ? normalizePathParams(loadPoint
|
|
102
|
+
const loadPath = loadPoint ? normalizePathParams(pointParts(loadPoint), loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
102
103
|
const allLoadParams = loadPoint?.args?.params || []
|
|
103
104
|
// Some upstream OpenAPI specs declare a parameter as `in: path` even when
|
|
104
105
|
// that path has no `{name}` placeholder for it. Only path params that
|
|
@@ -106,7 +107,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
106
107
|
// setup and URL-substitution asserts; otherwise the SDK silently drops
|
|
107
108
|
// them and the URL-includes assert fails.
|
|
108
109
|
const _pathPlaceholders = new Set<string>()
|
|
109
|
-
for (const part of (loadPoint
|
|
110
|
+
for (const part of pointParts(loadPoint)) {
|
|
110
111
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
111
112
|
_pathPlaceholders.add(part.slice(1, -1))
|
|
112
113
|
}
|
|
@@ -123,7 +124,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
123
124
|
_renamedPlaceholders.has(p.name) || _renamedPlaceholders.has(p.orig))
|
|
124
125
|
|
|
125
126
|
const listPoint = listOp?.points?.[0]
|
|
126
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
127
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
127
128
|
const listParams = listPoint?.args?.params || []
|
|
128
129
|
|
|
129
130
|
// 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, 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(``)
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
import {
|
|
32
|
-
clean,
|
|
33
32
|
formatRubyHash,
|
|
34
33
|
} from './utility_rb'
|
|
35
34
|
|
|
@@ -165,12 +164,7 @@ ${serverBlock}${authBlock} "headers" => ${formatRubyHash(headers, 4)},
|
|
|
165
164
|
Content(` },
|
|
166
165
|
},
|
|
167
166
|
"entity" => ${formatRubyHash(
|
|
168
|
-
|
|
169
|
-
fields: n.fields,
|
|
170
|
-
name: n.name,
|
|
171
|
-
op: n.op,
|
|
172
|
-
relations: n.relations,
|
|
173
|
-
}, true), a), {}), 3)},
|
|
167
|
+
configDef.entity, 3)},
|
|
174
168
|
}
|
|
175
169
|
end
|
|
176
170
|
`)
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
cmp, each, names, cmap,
|
|
6
6
|
List, File, Content, Copy, Folder, Fragment, Line, FeatureHook,
|
|
7
7
|
targetFeatures,
|
|
8
|
+
TEST_CONTROL_EXCLUDE
|
|
8
9
|
} from '@voxgig/sdkgen'
|
|
9
10
|
|
|
10
11
|
|
|
@@ -44,7 +45,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
44
45
|
// Copy tm/rb files with replacements
|
|
45
46
|
Copy({
|
|
46
47
|
from: 'tm/' + target.name,
|
|
47
|
-
exclude: [/src
|
|
48
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
48
49
|
replace: {
|
|
49
50
|
...props.ctx$.stdrep,
|
|
50
51
|
}
|
|
@@ -11,9 +11,14 @@ import {
|
|
|
11
11
|
File,
|
|
12
12
|
cmp,
|
|
13
13
|
snakify,
|
|
14
|
-
isAuthActive, envName, envToken
|
|
14
|
+
isAuthActive, envName, envToken,
|
|
15
|
+
serverVarEnv,
|
|
16
|
+
serverVariables,
|
|
17
|
+
pointParts,
|
|
15
18
|
} from '@voxgig/sdkgen'
|
|
16
19
|
|
|
20
|
+
import { formatRubyValue } from './utility_rb'
|
|
21
|
+
|
|
17
22
|
|
|
18
23
|
function normalizePathParams(
|
|
19
24
|
parts: string[],
|
|
@@ -64,12 +69,25 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
64
69
|
|
|
65
70
|
const authActive = isAuthActive(model)
|
|
66
71
|
const apikeyEnvEntry = authActive
|
|
67
|
-
? `\n "${PROJECTNAME}_APIKEY" => "
|
|
72
|
+
? `\n "${PROJECTNAME}_APIKEY" => "",`
|
|
68
73
|
: ''
|
|
69
74
|
const apikeyLiveField = authActive
|
|
70
75
|
? `\n "apikey" => env["${PROJECTNAME}_APIKEY"],`
|
|
71
76
|
: ''
|
|
72
77
|
|
|
78
|
+
// A templated server URL (OpenAPI server variables) makes a LIVE client
|
|
79
|
+
// impossible to construct without values: makeOptions raises rather than
|
|
80
|
+
// request a URL with a literal `{account_id}` in it. So the live suite
|
|
81
|
+
// takes them from the environment the same way it takes the apikey.
|
|
82
|
+
const svars = serverVariables(model)
|
|
83
|
+
const serverEnvEntry = svars
|
|
84
|
+
.map((v: any) => `\n "${serverVarEnv(PROJECTNAME, v.name)}" => ${formatRubyValue(v.dflt)},`).join('')
|
|
85
|
+
const serverLiveField = 0 === svars.length ? '' : `
|
|
86
|
+
"server" => {${svars
|
|
87
|
+
.map((v: any) => `
|
|
88
|
+
"${v.name}" => env["${serverVarEnv(PROJECTNAME, v.name)}"],`).join('')}
|
|
89
|
+
},`
|
|
90
|
+
|
|
73
91
|
const opnames = Object.keys(entity.op || {})
|
|
74
92
|
const hasLoad = opnames.includes('load')
|
|
75
93
|
const hasList = opnames.includes('list')
|
|
@@ -82,7 +100,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
82
100
|
const listOp = entity.op?.list
|
|
83
101
|
|
|
84
102
|
const loadPoint = loadOp?.points?.[0]
|
|
85
|
-
const loadPath = loadPoint ? normalizePathParams(loadPoint
|
|
103
|
+
const loadPath = loadPoint ? normalizePathParams(pointParts(loadPoint), loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
86
104
|
const allLoadParams = loadPoint?.args?.params || []
|
|
87
105
|
// Some upstream OpenAPI specs declare a parameter as `in: path` even when
|
|
88
106
|
// that path has no `{name}` placeholder for it. Only path params that
|
|
@@ -90,7 +108,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
90
108
|
// setup and URL-substitution asserts; otherwise the SDK silently drops
|
|
91
109
|
// them and the URL-includes assert fails.
|
|
92
110
|
const _pathPlaceholders = new Set<string>()
|
|
93
|
-
for (const part of (loadPoint
|
|
111
|
+
for (const part of pointParts(loadPoint)) {
|
|
94
112
|
if (typeof part === 'string' && part.startsWith('{') && part.endsWith('}')) {
|
|
95
113
|
_pathPlaceholders.add(part.slice(1, -1))
|
|
96
114
|
}
|
|
@@ -107,7 +125,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
107
125
|
_renamedPlaceholders.has(p.name) || _renamedPlaceholders.has(p.orig))
|
|
108
126
|
|
|
109
127
|
const listPoint = listOp?.points?.[0]
|
|
110
|
-
const listPath = listPoint ? normalizePathParams(listPoint
|
|
128
|
+
const listPath = listPoint ? normalizePathParams(pointParts(listPoint), listPoint?.args?.params || [], listPoint?.rename?.param) : ''
|
|
111
129
|
const listParams = listPoint?.args?.params || []
|
|
112
130
|
|
|
113
131
|
// Required query params with spec-provided examples — needed in live mode.
|
|
@@ -349,14 +367,16 @@ def ${entity.name}_direct_setup(mockres)
|
|
|
349
367
|
|
|
350
368
|
env = Runner.env_override({
|
|
351
369
|
"${entidEnvVar}" => {},
|
|
352
|
-
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}
|
|
370
|
+
"${PROJECTNAME}_TEST_LIVE" => "FALSE",${apikeyEnvEntry}${serverEnvEntry}
|
|
353
371
|
})
|
|
354
372
|
|
|
355
373
|
live = env["${PROJECTNAME}_TEST_LIVE"] == "TRUE"
|
|
356
374
|
|
|
357
375
|
if live
|
|
358
|
-
|
|
359
|
-
|
|
376
|
+
# Merged so the generated fields win: sdk-test-control.json's
|
|
377
|
+
# test.client.options adds to the live client, it does not redirect it.
|
|
378
|
+
merged_opts = Runner.live_client_options.merge({${apikeyLiveField}${serverLiveField}
|
|
379
|
+
})
|
|
360
380
|
client = ${model.const.Name}SDK.new(merged_opts)
|
|
361
381
|
return {
|
|
362
382
|
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)
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
File, Content, Copy, Folder, Fragment,
|
|
7
7
|
entityClassName,
|
|
8
8
|
targetFeatures,
|
|
9
|
+
TEST_CONTROL_EXCLUDE
|
|
9
10
|
} from '@voxgig/sdkgen'
|
|
10
11
|
|
|
11
12
|
|
|
@@ -54,7 +55,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
54
55
|
// here exactly like the go target.
|
|
55
56
|
Copy({
|
|
56
57
|
from: 'tm/' + target.name,
|
|
57
|
-
exclude: [/src
|
|
58
|
+
exclude: [/src\//, TEST_CONTROL_EXCLUDE],
|
|
58
59
|
replace: {
|
|
59
60
|
...props.ctx$.stdrep,
|
|
60
61
|
RUSTCRATE: rustcrate,
|