@voxgig/sdkgen 4.2.1 → 4.2.2
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/package.json +1 -1
- package/project/.sdk/src/cmp/dart/TestEntity_dart.ts +6 -3
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +13 -1
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +2 -2
- package/project/.sdk/src/cmp/kotlin/TestEntity_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestEntity_perl.ts +6 -1
- package/project/.sdk/src/cmp/rust/utility_rust.ts +8 -1
- package/project/.sdk/src/cmp/swift/utility_swift.ts +16 -2
- package/project/.sdk/tm/elixir/lib/utility/struct/voxgig_struct.ex +13 -1
- package/project/sdkgen-package.json +1 -1
package/bin/voxgig-sdkgen
CHANGED
package/package.json
CHANGED
|
@@ -382,18 +382,21 @@ const generateList: OpGen = (ctx, step, index) => {
|
|
|
382
382
|
const hasRefData = validRef && allSteps.some(s => 'create' === s.op &&
|
|
383
383
|
((s.input.ref ?? entity.name + '_ref01') === validRef))
|
|
384
384
|
|
|
385
|
-
//
|
|
385
|
+
// listvar is ALREADY a list of data maps — the list call above maps
|
|
386
|
+
// .data() over the entity instances. Mapping .data() a second time here
|
|
387
|
+
// called it on a plain Map and every entity test died at runtime with
|
|
388
|
+
// "Class '_Map<String, dynamic>' has no instance method 'data'".
|
|
386
389
|
if ('ItemExists' === validator.apply && hasRefData) {
|
|
387
390
|
Content(`
|
|
388
391
|
ok(!isempty(select(
|
|
389
|
-
|
|
392
|
+
${listvar},
|
|
390
393
|
{'id': ${validRef}_data['id']})));
|
|
391
394
|
`)
|
|
392
395
|
}
|
|
393
396
|
else if ('ItemNotExists' === validator.apply && hasRefData) {
|
|
394
397
|
Content(`
|
|
395
398
|
ok(isempty(select(
|
|
396
|
-
|
|
399
|
+
${listvar},
|
|
397
400
|
{'id': ${validRef}_data['id']})));
|
|
398
401
|
`)
|
|
399
402
|
}
|
|
@@ -55,9 +55,21 @@ function normalizePathParams(
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
// Render a JSON value as a Java literal for query examples.
|
|
58
|
+
// A Java source literal for an example value from the model.
|
|
59
|
+
//
|
|
60
|
+
// An integer beyond Java's int range needs the L suffix: javac rejects a bare
|
|
61
|
+
// 120615523104 outright ("integer number too large"), so one large id in a
|
|
62
|
+
// spec's example makes the whole generated test package fail to compile.
|
|
63
|
+
// A non-integral double is fine unsuffixed.
|
|
58
64
|
function javaLiteral(v: any): string {
|
|
59
65
|
if (null == v) return 'null'
|
|
60
|
-
if ('
|
|
66
|
+
if ('boolean' === typeof v) return String(v)
|
|
67
|
+
if ('number' === typeof v) {
|
|
68
|
+
if (Number.isInteger(v) && (v > 2147483647 || v < -2147483648)) {
|
|
69
|
+
return String(v) + 'L'
|
|
70
|
+
}
|
|
71
|
+
return String(v)
|
|
72
|
+
}
|
|
61
73
|
return JSON.stringify(String(v))
|
|
62
74
|
}
|
|
63
75
|
|
|
@@ -158,7 +158,7 @@ class ${entity.Name}DirectTest {
|
|
|
158
158
|
: []
|
|
159
159
|
const listSkipBlock = listLiveIdKeys.length > 0
|
|
160
160
|
? ` if (setup.live) {
|
|
161
|
-
for (liveKey in arrayOf(${listLiveIdKeys.map((k: string) => `"${k}"`).join(', ')})) {
|
|
161
|
+
for (liveKey in arrayOf<String>(${listLiveIdKeys.map((k: string) => `"${k}"`).join(', ')})) {
|
|
162
162
|
Assumptions.assumeTrue(setup.idmap[liveKey] != null,
|
|
163
163
|
"live test needs " + liveKey + " via *_ENTID env var (synthetic IDs only)")
|
|
164
164
|
}
|
|
@@ -265,7 +265,7 @@ ${listSkipBlock} val client = setup.client
|
|
|
265
265
|
}
|
|
266
266
|
const loadSkipBlock = loadLiveIdKeys.length > 0
|
|
267
267
|
? ` if (setup.live) {
|
|
268
|
-
for (liveKey in arrayOf(${loadLiveIdKeys.map(k => `"${k}"`).join(', ')})) {
|
|
268
|
+
for (liveKey in arrayOf<String>(${loadLiveIdKeys.map(k => `"${k}"`).join(', ')})) {
|
|
269
269
|
Assumptions.assumeTrue(setup.idmap[liveKey] != null,
|
|
270
270
|
"live test needs " + liveKey + " via *_ENTID env var (synthetic IDs only)")
|
|
271
271
|
}
|
|
@@ -114,7 +114,7 @@ class ${entity.Name}EntityTest {
|
|
|
114
114
|
val setup = ${accessor}BasicSetup(null)
|
|
115
115
|
// Per-op sdk-test-control.json skip.
|
|
116
116
|
val mode = if (setup.live) "live" else "unit"
|
|
117
|
-
for (op in arrayOf(${stepOps.map(o => `"${o}"`).join(', ')})) {
|
|
117
|
+
for (op in arrayOf<String>(${stepOps.map(o => `"${o}"`).join(', ')})) {
|
|
118
118
|
val reason = RunnerSupport.skipReason("entityOp", "${entity.name}.\$op", mode)
|
|
119
119
|
Assumptions.assumeTrue(
|
|
120
120
|
reason == null,
|
|
@@ -70,6 +70,11 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
70
70
|
: []
|
|
71
71
|
const aliases = updateData.map(([k, v]: any) => [k, v])
|
|
72
72
|
|
|
73
|
+
// An entity whose basic flow has no steps yields an EMPTY list, and Perl's
|
|
74
|
+
// `for my $x () {` is a syntax error (unlike `for my $x (()) {`, which is a
|
|
75
|
+
// valid empty loop) — the whole test file then fails to compile. The loop
|
|
76
|
+
// below therefore wraps this in a second pair of parens, which is a no-op
|
|
77
|
+
// for a non-empty list because Perl flattens it.
|
|
73
78
|
const opsList = Array.from(new Set(
|
|
74
79
|
(allSteps as any[]).map((s: any) => s.op).filter(Boolean)))
|
|
75
80
|
.map(o => `'${o}'`).join(', ')
|
|
@@ -101,7 +106,7 @@ BASIC_FLOW: {
|
|
|
101
106
|
my $setup = ${entity.name}_basic_setup(undef);
|
|
102
107
|
my $_live = $setup->{live} ? 1 : 0;
|
|
103
108
|
# Per-op sdk-test-control.json skip.
|
|
104
|
-
for my $_op (${opsList}) {
|
|
109
|
+
for my $_op ((${opsList})) {
|
|
105
110
|
my ($_should_skip, $_reason) = ${N}TestRunner::is_control_skipped(
|
|
106
111
|
'entityOp', "${entity.name}." . $_op, $_live ? 'live' : 'unit');
|
|
107
112
|
if ($_should_skip) {
|
|
@@ -20,7 +20,14 @@ const RUST_RESERVED = new Set<string>([
|
|
|
20
20
|
|
|
21
21
|
// A collision-free snake_case rust identifier for a model name.
|
|
22
22
|
function rustVarName(name: string): string {
|
|
23
|
-
|
|
23
|
+
let snake = name.replace(/[^a-zA-Z0-9_]/g, '_').toLowerCase()
|
|
24
|
+
// No Rust identifier may begin with a digit. A `3d_id` field became
|
|
25
|
+
// `pub 3_d_id: String`, which does not compile ("expected identifier, found
|
|
26
|
+
// `3_d_id`") and took the whole crate with it. Prefixed with an underscore,
|
|
27
|
+
// the convention cmp/c/utility_c.ts already applies.
|
|
28
|
+
if (/^[0-9]/.test(snake)) {
|
|
29
|
+
snake = '_' + snake
|
|
30
|
+
}
|
|
24
31
|
return RUST_RESERVED.has(snake) ? snake + '_' : snake
|
|
25
32
|
}
|
|
26
33
|
|
|
@@ -22,13 +22,27 @@ function projectPath(suffix?: string): string {
|
|
|
22
22
|
function swiftVarName(name: string): string {
|
|
23
23
|
const pascal = camelify(name)
|
|
24
24
|
const lower = pascal.charAt(0).toLowerCase() + pascal.slice(1)
|
|
25
|
-
|
|
25
|
+
if (SWIFT_RESERVED.has(lower)) {
|
|
26
|
+
return lower + '_'
|
|
27
|
+
}
|
|
28
|
+
return leadingDigitSafe(lower)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// No Swift identifier may begin with a digit, but a model field may: a
|
|
33
|
+
// `3d_id` field camelifies to `3DId`, and `public var 3DId: String` does not
|
|
34
|
+
// merely fail to bind — the compiler reads it as a malformed number and the
|
|
35
|
+
// whole module dies on "'D' is not a valid digit in integer literal", naming
|
|
36
|
+
// nothing that leads back to the field. Prefixed with an underscore, the same
|
|
37
|
+
// convention cmp/c/utility_c.ts already applies.
|
|
38
|
+
function leadingDigitSafe(ident: string): string {
|
|
39
|
+
return /^[0-9]/.test(ident) ? '_' + ident : ident
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
|
|
29
43
|
// A PascalCase Swift identifier for a snake_case model name.
|
|
30
44
|
function swiftPascalName(name: string): string {
|
|
31
|
-
return camelify(name)
|
|
45
|
+
return leadingDigitSafe(camelify(name))
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
|
|
@@ -50,14 +50,26 @@ defmodule Voxgig.Struct do
|
|
|
50
50
|
id
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# ensure_heap here too, not only in alloc. A named ETS table belongs to the
|
|
54
|
+
# process that created it and dies with it — and ExUnit runs each test in its
|
|
55
|
+
# own process, so a table created by an alloc in one test is gone by the
|
|
56
|
+
# next. hget then raised ArgumentError ("the table identifier does not refer
|
|
57
|
+
# to an existing ETS table") from whichever unrelated test happened to run
|
|
58
|
+
# second, which is why this surfaced as a pipeline/netsim failure rather than
|
|
59
|
+
# as anything to do with the heap.
|
|
53
60
|
defp hget(id) do
|
|
61
|
+
ensure_heap()
|
|
62
|
+
|
|
54
63
|
case :ets.lookup(@heap, id) do
|
|
55
64
|
[{_, c}] -> c
|
|
56
65
|
_ -> nil
|
|
57
66
|
end
|
|
58
67
|
end
|
|
59
68
|
|
|
60
|
-
defp hset(id, contents)
|
|
69
|
+
defp hset(id, contents) do
|
|
70
|
+
ensure_heap()
|
|
71
|
+
:ets.insert(@heap, {id, contents})
|
|
72
|
+
end
|
|
61
73
|
|
|
62
74
|
defp vmap_new(pairs), do: {:vmap, alloc(pairs)}
|
|
63
75
|
defp vlist_new(items), do: {:vlist, alloc(items)}
|