@voxgig/sdkgen 1.3.17 → 1.3.18
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/Entity.js +5 -1
- package/dist/cmp/Entity.js.map +1 -1
- package/dist/cmp/Feature.js +2 -1
- package/dist/cmp/Feature.js.map +1 -1
- package/dist/helpers/canonType.js +8 -3
- package/dist/helpers/canonType.js.map +1 -1
- package/dist/helpers/collectDeps.d.ts +1 -1
- package/dist/helpers/collectDeps.js +36 -13
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/naming.d.ts +3 -1
- package/dist/helpers/naming.js +53 -0
- package/dist/helpers/naming.js.map +1 -1
- package/dist/helpers/opShape.d.ts +3 -1
- package/dist/helpers/opShape.js +87 -8
- package/dist/helpers/opShape.js.map +1 -1
- package/dist/sdkgen.d.ts +3 -3
- package/dist/sdkgen.js +6 -2
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -10
- package/project/.sdk/model/target/cpp.aontu +4 -4
- package/project/.sdk/model/target/go-cli.aontu +17 -17
- package/project/.sdk/model/target/go-mcp.aontu +11 -11
- package/project/.sdk/model/target/go.aontu +1 -1
- package/project/.sdk/model/target/java.aontu +4 -4
- package/project/.sdk/model/target/kotlin.aontu +4 -4
- package/project/.sdk/model/target/lean.aontu +51 -0
- package/project/.sdk/model/target/scala.aontu +4 -4
- package/project/.sdk/src/cmp/c/EntityTypes_c.ts +3 -4
- package/project/.sdk/src/cmp/c/Entity_c.ts +3 -3
- package/project/.sdk/src/cmp/c/ReadmeExamplesTest_c.ts +24 -7
- package/project/.sdk/src/cmp/c/TestDirect_c.ts +3 -3
- package/project/.sdk/src/cmp/c/TestEntity_c.ts +1 -1
- package/project/.sdk/src/cmp/clojure/Entity_clojure.ts +1 -1
- package/project/.sdk/src/cmp/clojure/ReadmeExamplesTest_clojure.ts +19 -8
- package/project/.sdk/src/cmp/cpp/EntityTypes_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/Entity_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/MainEntity_cpp.ts +2 -2
- package/project/.sdk/src/cmp/cpp/ReadmeExamplesTest_cpp.ts +136 -0
- package/project/.sdk/src/cmp/cpp/TestDirect_cpp.ts +3 -3
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +4 -0
- package/project/.sdk/src/cmp/csharp/EntityTypes_csharp.ts +2 -3
- package/project/.sdk/src/cmp/csharp/Entity_csharp.ts +3 -3
- package/project/.sdk/src/cmp/csharp/MainEntity_csharp.ts +2 -2
- package/project/.sdk/src/cmp/csharp/Package_csharp.ts +1 -1
- package/project/.sdk/src/cmp/csharp/ReadmeExamplesTest_csharp.ts +13 -1
- package/project/.sdk/src/cmp/csharp/TestDirect_csharp.ts +3 -3
- package/project/.sdk/src/cmp/dart/EntityTypes_dart.ts +2 -3
- package/project/.sdk/src/cmp/dart/Entity_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/MainEntity_dart.ts +2 -2
- package/project/.sdk/src/cmp/dart/Main_dart.ts +3 -3
- package/project/.sdk/src/cmp/dart/Package_dart.ts +1 -1
- package/project/.sdk/src/cmp/dart/TestDirect_dart.ts +4 -4
- package/project/.sdk/src/cmp/elixir/EntityTypes_elixir.ts +2 -3
- package/project/.sdk/src/cmp/elixir/Entity_elixir.ts +1 -1
- package/project/.sdk/src/cmp/elixir/ReadmeExamplesTest_elixir.ts +21 -3
- package/project/.sdk/src/cmp/go/Config_go.ts +4 -1
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +110 -18
- package/project/.sdk/src/cmp/go/Entity_go.ts +3 -3
- package/project/.sdk/src/cmp/go/Main_go.ts +7 -6
- package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
- package/project/.sdk/src/cmp/go/TestDirect_go.ts +3 -3
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
- package/project/.sdk/src/cmp/go/utility_go.ts +25 -0
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +9 -1
- package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +9 -1
- package/project/.sdk/src/cmp/haskell/ReadmeExamplesTest_haskell.ts +28 -18
- package/project/.sdk/src/cmp/java/EntityTypes_java.ts +2 -3
- package/project/.sdk/src/cmp/java/Entity_java.ts +3 -3
- package/project/.sdk/src/cmp/java/MainEntity_java.ts +2 -2
- package/project/.sdk/src/cmp/java/Package_java.ts +1 -1
- package/project/.sdk/src/cmp/java/ReadmeExamplesTest_java.ts +23 -1
- package/project/.sdk/src/cmp/java/TestDirect_java.ts +3 -3
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +2 -3
- package/project/.sdk/src/cmp/js/Entity_js.ts +3 -3
- package/project/.sdk/src/cmp/js/MainEntity_js.ts +2 -2
- package/project/.sdk/src/cmp/js/Main_js.ts +2 -2
- package/project/.sdk/src/cmp/js/TestDirect_js.ts +4 -4
- package/project/.sdk/src/cmp/kotlin/EntityTypes_kotlin.ts +2 -3
- package/project/.sdk/src/cmp/kotlin/Entity_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/kotlin/MainEntity_kotlin.ts +2 -2
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +1 -1
- package/project/.sdk/src/cmp/kotlin/ReadmeExamplesTest_kotlin.ts +27 -2
- package/project/.sdk/src/cmp/kotlin/TestDirect_kotlin.ts +3 -3
- package/project/.sdk/src/cmp/lean/Config_lean.ts +88 -0
- package/project/.sdk/src/cmp/lean/Entity_lean.ts +9 -0
- package/project/.sdk/src/cmp/lean/Gitignore_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Main_lean.ts +120 -0
- package/project/.sdk/src/cmp/lean/Package_lean.ts +68 -0
- package/project/.sdk/src/cmp/lean/ReadmeEntity_lean.ts +29 -0
- package/project/.sdk/src/cmp/lean/ReadmeExplanation_lean.ts +19 -0
- package/project/.sdk/src/cmp/lean/ReadmeHowto_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +38 -0
- package/project/.sdk/src/cmp/lean/ReadmeIntro_lean.ts +25 -0
- package/project/.sdk/src/cmp/lean/ReadmeModel_lean.ts +24 -0
- package/project/.sdk/src/cmp/lean/ReadmeOptions_lean.ts +22 -0
- package/project/.sdk/src/cmp/lean/ReadmeQuick_lean.ts +50 -0
- package/project/.sdk/src/cmp/lean/ReadmeRef_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopHowto_lean.ts +16 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopQuick_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +18 -0
- package/project/.sdk/src/cmp/lean/Test_lean.ts +207 -0
- package/project/.sdk/src/cmp/lean/utility_lean.ts +78 -0
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +2 -3
- package/project/.sdk/src/cmp/lua/Entity_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/Package_lua.ts +1 -1
- package/project/.sdk/src/cmp/lua/TestDirect_lua.ts +3 -3
- package/project/.sdk/src/cmp/lua/TestEntity_lua.ts +1 -1
- package/project/.sdk/src/cmp/ocaml/ReadmeExamplesTest_ocaml.ts +29 -14
- package/project/.sdk/src/cmp/perl/Entity_perl.ts +3 -3
- package/project/.sdk/src/cmp/perl/MainEntity_perl.ts +2 -2
- package/project/.sdk/src/cmp/perl/Package_perl.ts +1 -1
- package/project/.sdk/src/cmp/perl/TestDirect_perl.ts +3 -3
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +2 -3
- package/project/.sdk/src/cmp/php/Entity_php.ts +3 -3
- package/project/.sdk/src/cmp/php/MainEntity_php.ts +2 -2
- package/project/.sdk/src/cmp/php/Package_php.ts +1 -1
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +3 -3
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +1 -1
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +2 -3
- package/project/.sdk/src/cmp/py/Entity_py.ts +3 -3
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Main_py.ts +2 -2
- package/project/.sdk/src/cmp/py/Package_py.ts +1 -1
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +3 -3
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +1 -1
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +15 -5
- package/project/.sdk/src/cmp/rb/Entity_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/Package_rb.ts +2 -2
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +3 -3
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +1 -1
- package/project/.sdk/src/cmp/rust/EntityBase_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/EntityTypes_rust.ts +3 -4
- package/project/.sdk/src/cmp/rust/Entity_rust.ts +3 -3
- package/project/.sdk/src/cmp/rust/MainEntity_rust.ts +2 -2
- package/project/.sdk/src/cmp/rust/Package_rust.ts +1 -1
- package/project/.sdk/src/cmp/rust/ReadmeExamplesTest_rust.ts +22 -10
- package/project/.sdk/src/cmp/rust/TestDirect_rust.ts +3 -3
- package/project/.sdk/src/cmp/scala/EntityTypes_scala.ts +2 -3
- package/project/.sdk/src/cmp/scala/Entity_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/MainEntity_scala.ts +2 -2
- package/project/.sdk/src/cmp/scala/ReadmeExamplesTest_scala.ts +22 -3
- package/project/.sdk/src/cmp/scala/TestDirect_scala.ts +3 -3
- package/project/.sdk/src/cmp/scala/Test_scala.ts +1 -1
- package/project/.sdk/src/cmp/swift/EntityTypes_swift.ts +3 -4
- package/project/.sdk/src/cmp/swift/Entity_swift.ts +3 -3
- package/project/.sdk/src/cmp/swift/MainEntity_swift.ts +2 -2
- package/project/.sdk/src/cmp/swift/Package_swift.ts +1 -1
- package/project/.sdk/src/cmp/swift/ReadmeExamplesTest_swift.ts +18 -1
- package/project/.sdk/src/cmp/swift/TestDirect_swift.ts +1 -1
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +2 -3
- package/project/.sdk/src/cmp/ts/Entity_ts.ts +3 -3
- package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/Main_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/TestDirect_ts.ts +4 -4
- package/project/.sdk/src/cmp/zig/Entity_zig.ts +3 -3
- package/project/.sdk/src/cmp/zig/MainEntity_zig.ts +2 -2
- package/project/.sdk/src/cmp/zig/Package_zig.ts +10 -2
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +8 -16
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
- package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
- package/project/.sdk/tm/go/feature/test_feature.go +33 -1
- package/project/.sdk/tm/go/test/primary_utility_test.go +41 -42
- package/project/.sdk/tm/go/test/runner_test.go +30 -1
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +8 -0
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +7 -20
- package/project/.sdk/tm/lean/LICENSE +21 -0
- package/project/.sdk/tm/lean/VERSION +1 -0
- package/project/.sdk/tm/lean/src/SdkFeature.lean +171 -0
- package/project/.sdk/tm/lean/src/SdkFeatures.lean +602 -0
- package/project/.sdk/tm/lean/src/SdkJson.lean +134 -0
- package/project/.sdk/tm/lean/src/SdkRuntime.lean +356 -0
- package/project/.sdk/tm/lean/src/SdkUtility.lean +617 -0
- package/project/.sdk/tm/lean/src/VoxgigStruct.lean +2880 -0
- package/project/.sdk/tm/lean/src/Vregex.lean +412 -0
- package/project/.sdk/tm/lean/src/feature/README.md +5 -0
- package/project/.sdk/tm/lean/src/feature/audit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/cache/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/clienttrack/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/debug/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/idempotency/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/metrics/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/netsim/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/paging/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/proxy/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/ratelimit/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/rbac/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/retry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/streaming/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/telemetry/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/lean/src/feature/timeout/.gitkeep +0 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +697 -0
- package/project/.sdk/tm/lean/test/TFeature.lean +268 -0
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +349 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +10 -8
- package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +9 -7
- package/project/.sdk/tm/py/feature/test_feature.py +28 -1
- package/project/.sdk/tm/py/test/test_primary_utility.py +13 -18
- package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +7 -8
- package/project/.sdk/tm/rust/tests/common/mod.rs +37 -1
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +12 -26
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +65 -21
- package/src/cmp/Entity.ts +5 -1
- package/src/cmp/Feature.ts +2 -1
- package/src/helpers/canonType.ts +8 -3
- package/src/helpers/collectDeps.ts +39 -12
- package/src/helpers/naming.ts +59 -0
- package/src/helpers/opShape.ts +99 -12
- package/src/sdkgen.ts +7 -3
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
File, Content,
|
|
35
35
|
} from '@voxgig/sdkgen'
|
|
36
36
|
|
|
37
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
37
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
38
38
|
|
|
39
39
|
import {
|
|
40
40
|
KIT,
|
|
@@ -133,11 +133,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
133
133
|
// filter, so inactive entities still get class files referencing these
|
|
134
134
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
135
135
|
// with the go emitter's fix.
|
|
136
|
-
const entityList =
|
|
136
|
+
const entityList = deriveEntityNames(entity)
|
|
137
137
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
138
138
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
139
139
|
// `Name = undefined` below. Parity with the go/py emitter's fix.
|
|
140
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
141
140
|
|
|
142
141
|
// Surface duplicate generated type names (two entities with the same
|
|
143
142
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, camelify, names,
|
|
6
6
|
Content, File, Folder, Fragment,
|
|
7
|
-
entityClassName,
|
|
7
|
+
entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -22,7 +22,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
22
22
|
// Collision-free entity CLASS name (see entityClassName): normally
|
|
23
23
|
// `<Name>Entity`, but disambiguated when it would clash with another
|
|
24
24
|
// entity's data-type name.
|
|
25
|
-
const entityColl =
|
|
25
|
+
const entityColl = entityCollection(model)
|
|
26
26
|
const cls = entityClassName(entity, entityColl)
|
|
27
27
|
|
|
28
28
|
const entrep = {
|
|
@@ -38,7 +38,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
38
38
|
|
|
39
39
|
File({ name: cls + '.' + target.ext }, () => {
|
|
40
40
|
|
|
41
|
-
const opnames = Object.keys(entity.op)
|
|
41
|
+
const opnames = Object.keys(entity.op || {})
|
|
42
42
|
|
|
43
43
|
// For each CRUD op: if the spec defines it, splice in the real
|
|
44
44
|
// implementation (an override). Otherwise leave the base-class
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, entityClassName } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, entityClassName, entityCollection } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
KIT,
|
|
@@ -12,7 +12,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
12
12
|
const { model } = props.ctx$
|
|
13
13
|
|
|
14
14
|
// Collision-free entity CLASS name (see entityClassName).
|
|
15
|
-
const entityColl =
|
|
15
|
+
const entityColl = entityCollection(model)
|
|
16
16
|
const cls = entityClassName(entity, entityColl)
|
|
17
17
|
|
|
18
18
|
// C# keeps the PascalCase accessor: public members are PascalCase, so a
|
|
@@ -31,7 +31,7 @@ const Package = cmp(async function Package(props: any) {
|
|
|
31
31
|
const { repoUrl } = repoInfo(model)
|
|
32
32
|
|
|
33
33
|
const deps: Record<string, string> = {}
|
|
34
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
34
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
35
35
|
deps[d.name] = d.source === 'target' ? (d.version || '0.0.0') : d.version
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -160,13 +160,25 @@ public class ReadmeExamplesTest
|
|
|
160
160
|
public void AllCsharpBlocksAreStructurallyBalanced()
|
|
161
161
|
{
|
|
162
162
|
var failures = new List<string>();
|
|
163
|
+
var fence = new string((char)96, 3);
|
|
163
164
|
foreach (var doc in Docs())
|
|
164
165
|
{
|
|
165
166
|
if (!System.IO.File.Exists(doc.path))
|
|
166
167
|
{
|
|
167
168
|
continue;
|
|
168
169
|
}
|
|
169
|
-
var
|
|
170
|
+
var text = System.IO.File.ReadAllText(doc.path);
|
|
171
|
+
// A well-formed document has an EVEN number of triple-backtick fence
|
|
172
|
+
// markers — every block that opens also closes. An odd count means a
|
|
173
|
+
// fence was opened but never closed at end-of-document; because block
|
|
174
|
+
// extraction keys off fence parity, such an unterminated csharp block
|
|
175
|
+
// can silently vanish instead of being checked. Fail loudly.
|
|
176
|
+
if ((text.Split(fence).Length - 1) % 2 != 0)
|
|
177
|
+
{
|
|
178
|
+
failures.Add(doc.label +
|
|
179
|
+
" has an unclosed code fence (odd number of triple-backtick markers)");
|
|
180
|
+
}
|
|
181
|
+
var blocks = CsharpBlocks(text);
|
|
170
182
|
var balanced = 0;
|
|
171
183
|
for (var i = 0; i < blocks.Count; i++)
|
|
172
184
|
{
|
|
@@ -73,7 +73,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
73
73
|
? `\n ["apikey"] = env["${PROJECTNAME}_APIKEY"],`
|
|
74
74
|
: ''
|
|
75
75
|
|
|
76
|
-
const opnames = Object.keys(entity.op)
|
|
76
|
+
const opnames = Object.keys(entity.op || {})
|
|
77
77
|
const hasLoad = opnames.includes('load')
|
|
78
78
|
const hasList = opnames.includes('list')
|
|
79
79
|
|
|
@@ -81,8 +81,8 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
81
81
|
return
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const loadOp = entity.op
|
|
85
|
-
const listOp = entity.op
|
|
84
|
+
const loadOp = entity.op?.load
|
|
85
|
+
const listOp = entity.op?.list
|
|
86
86
|
|
|
87
87
|
// Get load point info
|
|
88
88
|
const loadPoint = loadOp?.points?.[0]
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
File, Content,
|
|
24
24
|
} from '@voxgig/sdkgen'
|
|
25
25
|
|
|
26
|
-
import { canonKey, canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
26
|
+
import { canonKey, canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions, deriveEntityNames } from '@voxgig/sdkgen'
|
|
27
27
|
|
|
28
28
|
import {
|
|
29
29
|
KIT,
|
|
@@ -147,11 +147,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
147
147
|
// filter, so inactive entities still get class files referencing these
|
|
148
148
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
149
149
|
// with the go emitter's fix.
|
|
150
|
-
const entityList =
|
|
150
|
+
const entityList = deriveEntityNames(entity)
|
|
151
151
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
152
152
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
153
153
|
// `Name = undefined` below. Parity with the go emitter's fix.
|
|
154
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
155
154
|
|
|
156
155
|
// Surface duplicate generated type names (two entities with the same
|
|
157
156
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, camelify, names,
|
|
6
6
|
Content, File, Folder, Fragment,
|
|
7
|
-
entityClassName,
|
|
7
|
+
entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -23,7 +23,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
23
23
|
// `<Name>Entity`, disambiguated when it would clash with another entity's
|
|
24
24
|
// data-type name. The class file name and the Main accessor both use
|
|
25
25
|
// this, so they always agree.
|
|
26
|
-
const entityColl =
|
|
26
|
+
const entityColl = entityCollection(model)
|
|
27
27
|
const cls = entityClassName(entity, entityColl)
|
|
28
28
|
|
|
29
29
|
const entrep = {
|
|
@@ -38,7 +38,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
38
38
|
|
|
39
39
|
File({ name: cls + '.' + target.ext }, () => {
|
|
40
40
|
|
|
41
|
-
const opnames = Object.keys(entity.op)
|
|
41
|
+
const opnames = Object.keys(entity.op || {})
|
|
42
42
|
|
|
43
43
|
const opfrags =
|
|
44
44
|
(['load', 'list', 'create', 'update', 'remove']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import { cmp, Content, entityClassName } from '@voxgig/sdkgen'
|
|
3
|
+
import { cmp, Content, entityClassName, entityCollection } from '@voxgig/sdkgen'
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
KIT,
|
|
@@ -15,7 +15,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
15
15
|
// Return the collision-free class TYPE (entityClassName); the accessor
|
|
16
16
|
// METHOD name (entity.Name) is unchanged so callers still write
|
|
17
17
|
// client.<Name>().
|
|
18
|
-
const cls = entityClassName(entity,
|
|
18
|
+
const cls = entityClassName(entity, entityCollection(model))
|
|
19
19
|
|
|
20
20
|
Content(`
|
|
21
21
|
// Entity access: \`client.${entity.Name}().list()\` / \`client.${entity.Name}().load({'id': ...})\`.
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each,
|
|
6
6
|
List, File, Copy, Folder, Fragment, Line,
|
|
7
|
-
entityClassName,
|
|
7
|
+
entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
|
|
@@ -61,7 +61,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
61
61
|
Line(``)
|
|
62
62
|
|
|
63
63
|
List({ item: entity }, ({ item }: any) => {
|
|
64
|
-
const cls = entityClassName(item,
|
|
64
|
+
const cls = entityClassName(item, entityCollection(model))
|
|
65
65
|
return Line(`import 'entity/${cls}.dart';`)
|
|
66
66
|
})
|
|
67
67
|
|
|
@@ -70,7 +70,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
70
70
|
Line(``)
|
|
71
71
|
Line(`export '${model.const.Name}Types.dart';`)
|
|
72
72
|
List({ item: entity }, ({ item }: any) => {
|
|
73
|
-
const cls = entityClassName(item,
|
|
73
|
+
const cls = entityClassName(item, entityCollection(model))
|
|
74
74
|
return Line(`export 'entity/${cls}.dart';`)
|
|
75
75
|
})
|
|
76
76
|
|
|
@@ -59,7 +59,7 @@ topics:
|
|
|
59
59
|
// Runtime is dependency-free (dart:io + dart:convert + vendored struct);
|
|
60
60
|
// target/feature deps, when declared, land here.
|
|
61
61
|
const deps: Record<string, string> = {}
|
|
62
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
62
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
63
63
|
deps[d.name] = d.source === 'target' ? (d.version || 'any') : d.version
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -47,7 +47,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
47
47
|
'apikey': env['${PROJECTNAME}_APIKEY'],`
|
|
48
48
|
: ''
|
|
49
49
|
|
|
50
|
-
const opnames = Object.keys(entity.op)
|
|
50
|
+
const opnames = Object.keys(entity.op || {})
|
|
51
51
|
const hasLoad = opnames.includes('load')
|
|
52
52
|
const hasList = opnames.includes('list')
|
|
53
53
|
|
|
@@ -157,7 +157,7 @@ dynamic unwrapListData(dynamic data) {
|
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
function generateDirectLoad(model: Model, entity: ModelEntity) {
|
|
160
|
-
const loadOp = entity.op
|
|
160
|
+
const loadOp = entity.op?.load
|
|
161
161
|
const loadPoint: ModelPoint | undefined = loadOp?.points?.[0]
|
|
162
162
|
|
|
163
163
|
if (null == loadPoint) {
|
|
@@ -197,7 +197,7 @@ function generateDirectLoad(model: Model, entity: ModelEntity) {
|
|
|
197
197
|
.join('\n')
|
|
198
198
|
|
|
199
199
|
// Get list info for live mode bootstrapping
|
|
200
|
-
const listOp = entity.op
|
|
200
|
+
const listOp = entity.op?.list
|
|
201
201
|
const listPoint = listOp?.points?.[0]
|
|
202
202
|
const listParams = listPoint?.args?.params || []
|
|
203
203
|
const listPath = listPoint ? normalizePathParams(listPoint.parts || [], listParams, listPoint.rename?.param) : ''
|
|
@@ -350,7 +350,7 @@ ${paramAsserts} }
|
|
|
350
350
|
|
|
351
351
|
|
|
352
352
|
function generateDirectList(model: Model, entity: ModelEntity) {
|
|
353
|
-
const listOp = entity.op
|
|
353
|
+
const listOp = entity.op?.list
|
|
354
354
|
const listPoint: ModelPoint | undefined = listOp?.points?.[0]
|
|
355
355
|
|
|
356
356
|
if (null == listPoint) {
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
File, Folder, Content,
|
|
30
30
|
} from '@voxgig/sdkgen'
|
|
31
31
|
|
|
32
|
-
import { opRequestShape, OP_SUFFIX, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
32
|
+
import { opRequestShape, OP_SUFFIX, warnEntityTypeCollisions, deriveEntityNames } from '@voxgig/sdkgen'
|
|
33
33
|
|
|
34
34
|
import {
|
|
35
35
|
KIT,
|
|
@@ -89,10 +89,9 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
89
89
|
// each generated module carries @specs referencing its Types aliases, so an
|
|
90
90
|
// alias is required for each or the project won't compile. Filter on `name`
|
|
91
91
|
// (always present), NOT `active` — parity with the go emitter's fix.
|
|
92
|
-
const entityList =
|
|
92
|
+
const entityList = deriveEntityNames(entity)
|
|
93
93
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
94
94
|
// entity not yet named would otherwise read `Name = undefined` below.
|
|
95
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
96
95
|
|
|
97
96
|
// Surface duplicate generated type names (two entities with the same
|
|
98
97
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -23,7 +23,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
23
23
|
Folder({ name: 'entity' }, () => {
|
|
24
24
|
File({ name: entity.name + '_entity.' + target.ext }, () => {
|
|
25
25
|
|
|
26
|
-
const opnames = Object.keys(entity.op)
|
|
26
|
+
const opnames = Object.keys(entity.op || {})
|
|
27
27
|
|
|
28
28
|
const opfrags =
|
|
29
29
|
(['load', 'list', 'create', 'update', 'remove']
|
|
@@ -71,9 +71,18 @@ defmodule ${Name}.ReadmeExamplesTest do
|
|
|
71
71
|
end)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
# True when every opening fence in \`text\` has a matching closing fence.
|
|
75
|
+
# Splitting on the fence yields (fence_count + 1) segments, so an even fence
|
|
76
|
+
# count (odd segment count) means all fences are paired. An unclosed
|
|
77
|
+
# \`\`\`elixir fence at EOF would otherwise leave a truncated/empty block that
|
|
78
|
+
# parses cleanly and slips through the syntax gate silently.
|
|
79
|
+
defp fences_balanced?(text) do
|
|
80
|
+
rem(length(String.split(text, @fence)) - 1, 2) == 0
|
|
81
|
+
end
|
|
82
|
+
|
|
74
83
|
defp doc_blocks(path) do
|
|
75
84
|
case File.read(path) do
|
|
76
|
-
{:ok, text} -> {:present, elixir_blocks(text)}
|
|
85
|
+
{:ok, text} -> {:present, elixir_blocks(text), fences_balanced?(text)}
|
|
77
86
|
_ -> :absent
|
|
78
87
|
end
|
|
79
88
|
end
|
|
@@ -85,7 +94,16 @@ defmodule ${Name}.ReadmeExamplesTest do
|
|
|
85
94
|
:absent ->
|
|
86
95
|
{fails, present, total}
|
|
87
96
|
|
|
88
|
-
{:present, blocks} ->
|
|
97
|
+
{:present, blocks, balanced?} ->
|
|
98
|
+
# An unclosed fence is a malformed doc — fail rather than silently
|
|
99
|
+
# scanning past the truncated block.
|
|
100
|
+
fence_fails =
|
|
101
|
+
if balanced? do
|
|
102
|
+
[]
|
|
103
|
+
else
|
|
104
|
+
[label <> " has an unclosed " <> @fence <> "elixir fence (odd fence count)"]
|
|
105
|
+
end
|
|
106
|
+
|
|
89
107
|
block_fails =
|
|
90
108
|
blocks
|
|
91
109
|
|> Enum.with_index()
|
|
@@ -105,7 +123,7 @@ defmodule ${Name}.ReadmeExamplesTest do
|
|
|
105
123
|
end
|
|
106
124
|
end)
|
|
107
125
|
|
|
108
|
-
{fails ++ block_fails, present + 1, total + length(blocks)}
|
|
126
|
+
{fails ++ fence_fails ++ block_fails, present + 1, total + length(blocks)}
|
|
109
127
|
end
|
|
110
128
|
end)
|
|
111
129
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
clean,
|
|
27
27
|
formatGoMap,
|
|
28
|
+
goFeatureName,
|
|
28
29
|
} from './utility_go'
|
|
29
30
|
|
|
30
31
|
|
|
@@ -102,7 +103,9 @@ func makeFeature(name string) Feature {
|
|
|
102
103
|
`)
|
|
103
104
|
|
|
104
105
|
each(feature, (f: any) => {
|
|
105
|
-
|
|
106
|
+
// MUST match Main_go.ts, which DECLARES these identifiers in registry.go
|
|
107
|
+
// and the root init(); see goFeatureName.
|
|
108
|
+
const fname = goFeatureName(f)
|
|
106
109
|
if (f.name !== 'base') {
|
|
107
110
|
Content(` case "${f.name}":
|
|
108
111
|
if New${fname}FeatureFunc != nil {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
// with every field optional (Go's analog of TS `Partial<Name>`).
|
|
28
28
|
|
|
29
29
|
import {
|
|
30
|
-
cmp, each,
|
|
30
|
+
cmp, each,
|
|
31
31
|
File, Content, Folder,
|
|
32
32
|
} from '@voxgig/sdkgen'
|
|
33
33
|
|
|
34
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
34
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
35
35
|
|
|
36
36
|
import {
|
|
37
37
|
KIT,
|
|
@@ -62,16 +62,105 @@ function goField(name: string): string {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
// The json struct tag is the WIRE CONTRACT: it decides the key requests
|
|
66
|
+
// marshal under and the key responses populate from.
|
|
67
|
+
//
|
|
68
|
+
// Can this spec-derived name be carried in a Go json struct tag AT ALL?
|
|
69
|
+
//
|
|
70
|
+
// It cannot always be. `encoding/json`'s isValidTag accepts letters, digits and
|
|
71
|
+
// a fixed punctuation set; a name containing a double quote, a backtick or a
|
|
72
|
+
// backslash is REJECTED, and Go then silently falls back to the Go FIELD name.
|
|
73
|
+
// Verified against go1.24 — for a field named `na"me`:
|
|
74
|
+
//
|
|
75
|
+
// raw literal `json:"na"me"` -> marshals as {"na": ...} (truncated)
|
|
76
|
+
// escaped literal "json:\"na\\\"me\"" -> marshals as {"NaMe": ...} (tag ignored)
|
|
77
|
+
//
|
|
78
|
+
// So there is no encoding that preserves such a name. An earlier version here
|
|
79
|
+
// stripped the offending characters, which is worse than either: it silently
|
|
80
|
+
// changed the wire contract, marshalling under a key the API never uses and
|
|
81
|
+
// never populating from the real response key. Names that cannot be
|
|
82
|
+
// represented are skipped with a warning instead — the same treatment
|
|
83
|
+
// csharp/java give names with no legal identifier form.
|
|
84
|
+
const GO_TAG_PUNCT = '!#$%&()*+-./:;<=>?@[]^_{|}~ '
|
|
85
|
+
|
|
86
|
+
function goTaggable(name: string): boolean {
|
|
87
|
+
const s = String(name)
|
|
88
|
+
if ('' === s) {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
91
|
+
for (const c of s) {
|
|
92
|
+
if (GO_TAG_PUNCT.includes(c)) continue
|
|
93
|
+
if (/[\p{L}\p{Nd}]/u.test(c)) continue
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
function goTag(name: string, omitempty: boolean): string {
|
|
101
|
+
const jsonName = String(name) + (omitempty ? ',omitempty' : '')
|
|
102
|
+
return '`json:"' + jsonName + '"`'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
65
106
|
// One Go struct field line. `optional` -> pointer + ,omitempty (Go's closest
|
|
66
|
-
// analog to an optional/absent field).
|
|
67
|
-
|
|
107
|
+
// analog to an optional/absent field). `ident` overrides the derived field
|
|
108
|
+
// identifier when goField() would collide with a sibling (see uniqueGoFields).
|
|
109
|
+
function fieldLine(name: string, sentinel: any, optional: boolean, ident?: string): string {
|
|
68
110
|
const gt = canonToType(sentinel, LANG)
|
|
69
111
|
const typ = optional ? ('*' + gt) : gt
|
|
70
|
-
|
|
71
|
-
return `\t${goField(name)} ${typ} ${tag}\n`
|
|
112
|
+
return `\t${ident || goField(name)} ${typ} ${goTag(name, optional)}\n`
|
|
72
113
|
}
|
|
73
114
|
|
|
74
115
|
|
|
116
|
+
// Collision-free Go field identifiers for one struct's members.
|
|
117
|
+
//
|
|
118
|
+
// goField() is lossy — it strips every non-alphanumeric character — so
|
|
119
|
+
// `some_field`, `some-field` and `someField` all map to `SomeField`. Emitting
|
|
120
|
+
// them into the same struct is a "field redeclared" compile error, and Go is
|
|
121
|
+
// the only target exposed to it (ts/py/… keep the raw key). Later duplicates
|
|
122
|
+
// get a numeric suffix; the FIRST occurrence keeps the natural name, and the
|
|
123
|
+
// json tag always keeps the original wire name, so behaviour is unchanged.
|
|
124
|
+
// Deterministic: members arrive in sorted-key order from opRequestShape/each.
|
|
125
|
+
function uniqueGoFields(members: { name: string }[]): string[] {
|
|
126
|
+
const taken: Record<string, boolean> = {}
|
|
127
|
+
return members.map((m) => {
|
|
128
|
+
const base = goField(m.name)
|
|
129
|
+
let ident = base
|
|
130
|
+
let n = 1
|
|
131
|
+
while (taken[ident]) {
|
|
132
|
+
n++
|
|
133
|
+
ident = base + n
|
|
134
|
+
}
|
|
135
|
+
taken[ident] = true
|
|
136
|
+
return ident
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
// Keep a member only when its name survives into a Go json tag; warn once per
|
|
142
|
+
// dropped member so the omission is visible rather than a silent contract change.
|
|
143
|
+
function skipUntaggable(member: any, typeName: string, log: any): boolean {
|
|
144
|
+
if (null == member || null == member.name) {
|
|
145
|
+
return false
|
|
146
|
+
}
|
|
147
|
+
if (goTaggable(member.name)) {
|
|
148
|
+
return true
|
|
149
|
+
}
|
|
150
|
+
if (log && log.warn) {
|
|
151
|
+
log.warn({
|
|
152
|
+
point: 'entity-types-skip-field', typeName, field: member.name,
|
|
153
|
+
note: `go: field "${member.name}" of ${typeName} cannot be carried in a ` +
|
|
154
|
+
`Go json struct tag (encoding/json rejects the name, and Go would ` +
|
|
155
|
+
`silently marshal under the field name instead); omitted from the ` +
|
|
156
|
+
`typed model (still reachable via the runtime map)`,
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
return false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
75
164
|
const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
76
165
|
const { target } = props
|
|
77
166
|
const { model, log } = props.ctx$
|
|
@@ -84,14 +173,11 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
84
173
|
// Emit for every entity that gets an entity file. Main_go.ts / Entity_go.ts
|
|
85
174
|
// iterate entities WITHOUT an `active` filter and reference the typed data
|
|
86
175
|
// type `<Name>` in every *_entity.go, so a struct is required for each or the
|
|
87
|
-
// package won't compile.
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
// the struct set is deterministic and matches the *_entity.go set.
|
|
93
|
-
const entityList = each(entity).filter((e: any) => e && null != e.name)
|
|
94
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
176
|
+
// package won't compile. deriveEntityNames() selects on `name` (always
|
|
177
|
+
// present) and derives the lazily-set PascalCase `Name` up front, so the
|
|
178
|
+
// struct set is deterministic and matches the *_entity.go set regardless of
|
|
179
|
+
// which component runs first.
|
|
180
|
+
const entityList = deriveEntityNames(entity)
|
|
95
181
|
|
|
96
182
|
// Surface duplicate generated type names (two entities with the same
|
|
97
183
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -123,8 +209,11 @@ import "encoding/json"
|
|
|
123
209
|
Content(`// ${Name} is the typed data model for the ${ent.name} entity.
|
|
124
210
|
type ${Name} struct {
|
|
125
211
|
`)
|
|
126
|
-
fields.
|
|
127
|
-
|
|
212
|
+
const taggable = fields.filter(
|
|
213
|
+
(f: any) => skipUntaggable(f, Name, log))
|
|
214
|
+
const fieldIdents = uniqueGoFields(taggable)
|
|
215
|
+
taggable.forEach((f: any, i: number) => {
|
|
216
|
+
Content(fieldLine(f.name, f.type, false === f.req, fieldIdents[i]))
|
|
128
217
|
})
|
|
129
218
|
Content(`}
|
|
130
219
|
|
|
@@ -146,8 +235,11 @@ type ${Name} struct {
|
|
|
146
235
|
Content(`// ${typeName} is the typed request payload for ${Name}.${cap(opname)}Typed.
|
|
147
236
|
type ${typeName} struct {
|
|
148
237
|
`)
|
|
149
|
-
items.
|
|
150
|
-
|
|
238
|
+
const taggableItems = items.filter(
|
|
239
|
+
(it: any) => skipUntaggable(it, typeName, log))
|
|
240
|
+
const itemIdents = uniqueGoFields(taggableItems)
|
|
241
|
+
taggableItems.forEach((it: any, i: number) => {
|
|
242
|
+
Content(fieldLine(it.name, it.type, it.optional, itemIdents[i]))
|
|
151
243
|
})
|
|
152
244
|
Content(`}
|
|
153
245
|
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, each, camelify, names,
|
|
6
6
|
File, Content, Folder, Fragment, Line, FeatureHook, Slot,
|
|
7
|
-
entityClassName,
|
|
7
|
+
entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -26,7 +26,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
26
26
|
// Collision-free entity CLASS name (see entityClassName): normally
|
|
27
27
|
// `<Name>Entity`, but disambiguated (e.g. `<Name>EntityClient`) when it would
|
|
28
28
|
// clash with another entity's data-type name. The DATA type stays `<Name>`.
|
|
29
|
-
const entityColl =
|
|
29
|
+
const entityColl = entityCollection(model)
|
|
30
30
|
const cls = entityClassName(entity, entityColl)
|
|
31
31
|
|
|
32
32
|
const entrep = {
|
|
@@ -42,7 +42,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
42
42
|
|
|
43
43
|
File({ name: entity.name + '_entity.' + target.ext }, () => {
|
|
44
44
|
|
|
45
|
-
const opnames = Object.keys(entity.op)
|
|
45
|
+
const opnames = Object.keys(entity.op || {})
|
|
46
46
|
|
|
47
47
|
// For each CRUD op: if the spec defines it, splice in the real
|
|
48
48
|
// implementation. Otherwise emit a stub that satisfies the static
|
|
@@ -4,7 +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
|
-
entityClassName,
|
|
7
|
+
entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from '@voxgig/apidef'
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
import { goFeatureName } from './utility_go'
|
|
22
23
|
import { Package } from './Package_go'
|
|
23
24
|
import { Config } from './Config_go'
|
|
24
25
|
import { Gitignore } from './Gitignore_go'
|
|
@@ -82,7 +83,7 @@ const Main = cmp(async function Main(props: any) {
|
|
|
82
83
|
|
|
83
84
|
'#BuildFeatures': ({ indent }: any) => {
|
|
84
85
|
each(feature, (feat: any) => {
|
|
85
|
-
const fname =
|
|
86
|
+
const fname = goFeatureName(feat)
|
|
86
87
|
Content({ indent }, `u.FeatureAdd(s.rootctx, New${fname}FeatureFunc())
|
|
87
88
|
`)
|
|
88
89
|
})
|
|
@@ -119,7 +120,7 @@ var NewBaseFeatureFunc func() Feature
|
|
|
119
120
|
// Feature constructor function vars (non-base)
|
|
120
121
|
each(feature, (feat: any) => {
|
|
121
122
|
if (feat.name !== 'base') {
|
|
122
|
-
const fname =
|
|
123
|
+
const fname = goFeatureName(feat)
|
|
123
124
|
Content(`var New${fname}FeatureFunc func() Feature
|
|
124
125
|
|
|
125
126
|
`)
|
|
@@ -177,7 +178,7 @@ func init() {
|
|
|
177
178
|
// Register non-base feature constructors
|
|
178
179
|
each(feature, (feat: any) => {
|
|
179
180
|
if (feat.name !== 'base') {
|
|
180
|
-
const fname =
|
|
181
|
+
const fname = goFeatureName(feat)
|
|
181
182
|
Content(` core.New${fname}FeatureFunc = func() core.Feature {
|
|
182
183
|
return feature.New${fname}Feature()
|
|
183
184
|
}
|
|
@@ -188,7 +189,7 @@ func init() {
|
|
|
188
189
|
// Register entity constructors
|
|
189
190
|
each(entity, (ent: any) => {
|
|
190
191
|
Content(` core.New${ent.Name}EntityFunc = func(client *core.${model.const.Name}SDK, entopts map[string]any) core.${model.const.Name}Entity {
|
|
191
|
-
return entity.New${entityClassName(ent,
|
|
192
|
+
return entity.New${entityClassName(ent, entityCollection(model))}(client, entopts)
|
|
192
193
|
}
|
|
193
194
|
`)
|
|
194
195
|
})
|
|
@@ -219,7 +220,7 @@ func Test() *${model.const.Name}SDK { return TestSDK(nil, nil) }
|
|
|
219
220
|
|
|
220
221
|
each(feature, (feat: any) => {
|
|
221
222
|
if (feat.name !== 'base') {
|
|
222
|
-
const fname =
|
|
223
|
+
const fname = goFeatureName(feat)
|
|
223
224
|
Content(`var New${fname}Feature = feature.New${fname}Feature
|
|
224
225
|
`)
|
|
225
226
|
}
|
|
@@ -31,7 +31,7 @@ go 1.20
|
|
|
31
31
|
|
|
32
32
|
const deps: Record<string, string> = {}
|
|
33
33
|
const replaceDirs: Record<string, string> = {}
|
|
34
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
34
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
35
35
|
// Target-level deps default to 'v0.0.0' when version is absent;
|
|
36
36
|
// feature deps require an explicit version.
|
|
37
37
|
deps[d.name] = d.source === 'target' ? (d.version || 'v0.0.0') : d.version
|
|
@@ -75,7 +75,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
75
75
|
? `\n\t\t\t"apikey": env["${PROJECTNAME}_APIKEY"],`
|
|
76
76
|
: ''
|
|
77
77
|
|
|
78
|
-
const opnames = Object.keys(entity.op)
|
|
78
|
+
const opnames = Object.keys(entity.op || {})
|
|
79
79
|
const hasLoad = opnames.includes('load')
|
|
80
80
|
const hasList = opnames.includes('list')
|
|
81
81
|
|
|
@@ -83,8 +83,8 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
83
83
|
return
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
const loadOp = entity.op
|
|
87
|
-
const listOp = entity.op
|
|
86
|
+
const loadOp = entity.op?.load
|
|
87
|
+
const listOp = entity.op?.list
|
|
88
88
|
|
|
89
89
|
// Get load point info
|
|
90
90
|
const loadPoint = loadOp?.points?.[0]
|