@voxgig/sdkgen 1.3.17 → 1.3.19
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/Deploy.js +16 -16
- package/dist/cmp/Deploy.js.map +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/cmp/ReadmeTop.js +13 -11
- package/dist/cmp/ReadmeTop.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 +5 -1
- package/dist/helpers/naming.js +118 -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/helpers/serverVars.d.ts +10 -0
- package/dist/helpers/serverVars.js +87 -0
- package/dist/helpers/serverVars.js.map +1 -0
- package/dist/sdkgen.d.ts +4 -3
- package/dist/sdkgen.js +11 -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/csharp/TestEntity_csharp.ts +22 -15
- 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 +14 -2
- 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 +62 -35
- package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +7 -7
- package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +21 -18
- 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/Config_js.ts +11 -0
- 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/js/fragment/Config.fragment.js +2 -2
- package/project/.sdk/src/cmp/js/fragment/Direct.test.fragment.js +4 -0
- 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/Config_lua.ts +10 -1
- 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/Config_php.ts +13 -2
- 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/Config_py.ts +10 -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/Config_rb.ts +12 -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/rust/TestEntity_rust.ts +25 -18
- 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 +12 -6
- 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/Config_ts.ts +11 -0
- 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/ts/fragment/Config.fragment.ts +2 -2
- package/project/.sdk/src/cmp/ts/fragment/Direct.test.fragment.ts +4 -0
- 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/Makefile +6 -6
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +10 -28
- package/project/.sdk/tm/dart/Makefile +3 -3
- package/project/.sdk/tm/dart/test/primary_test.dart +7 -0
- package/project/.sdk/tm/go/Makefile +6 -6
- package/project/.sdk/tm/go/feature/test_feature.go +33 -1
- package/project/.sdk/tm/go/test/primary_utility_test.go +46 -42
- package/project/.sdk/tm/go/test/runner_test.go +30 -1
- package/project/.sdk/tm/go/utility/make_options.go +48 -0
- package/project/.sdk/tm/java/Makefile +6 -6
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +7 -24
- package/project/.sdk/tm/js/Makefile +6 -6
- package/project/.sdk/tm/js/src/feature/test/TestFeature.js +18 -1
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -1
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +13 -0
- package/project/.sdk/tm/kotlin/Makefile +6 -6
- 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/Makefile +7 -7
- package/project/.sdk/tm/lua/feature/test_feature.lua +29 -1
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +14 -8
- package/project/.sdk/tm/lua/utility/make_options.lua +39 -0
- package/project/.sdk/tm/perl/Makefile +6 -6
- package/project/.sdk/tm/perl/t/primary_utility.t +8 -17
- package/project/.sdk/tm/php/Makefile +6 -6
- package/project/.sdk/tm/php/feature/TestFeature.php +30 -2
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +14 -7
- package/project/.sdk/tm/php/utility/MakeOptions.php +44 -0
- package/project/.sdk/tm/py/Makefile +6 -6
- package/project/.sdk/tm/py/feature/test_feature.py +28 -1
- package/project/.sdk/tm/py/test/test_primary_utility.py +18 -18
- package/project/.sdk/tm/py/utility/make_options.py +42 -0
- package/project/.sdk/tm/rb/Makefile +6 -6
- package/project/.sdk/tm/rb/feature/test_feature.rb +24 -1
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +11 -8
- package/project/.sdk/tm/rb/utility/make_options.rb +37 -0
- package/project/.sdk/tm/rust/Makefile +6 -6
- 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/Makefile +6 -6
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +7 -8
- package/project/.sdk/tm/ts/Makefile +6 -6
- package/project/.sdk/tm/ts/src/feature/test/TestFeature.ts +18 -1
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +39 -1
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +69 -21
- package/src/cmp/Deploy.ts +16 -16
- package/src/cmp/Entity.ts +5 -1
- package/src/cmp/Feature.ts +2 -1
- package/src/cmp/ReadmeTop.ts +13 -11
- package/src/helpers/canonType.ts +8 -3
- package/src/helpers/collectDeps.ts +39 -12
- package/src/helpers/naming.ts +130 -0
- package/src/helpers/opShape.ts +99 -12
- package/src/helpers/serverVars.ts +105 -0
- package/src/sdkgen.ts +12 -3
|
@@ -70,7 +70,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
70
70
|
? `\n "apikey" => env["${PROJECTNAME}_APIKEY"],`
|
|
71
71
|
: ''
|
|
72
72
|
|
|
73
|
-
const opnames = Object.keys(entity.op)
|
|
73
|
+
const opnames = Object.keys(entity.op || {})
|
|
74
74
|
const hasLoad = opnames.includes('load')
|
|
75
75
|
const hasList = opnames.includes('list')
|
|
76
76
|
|
|
@@ -78,8 +78,8 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
78
78
|
return
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const loadOp = entity.op
|
|
82
|
-
const listOp = entity.op
|
|
81
|
+
const loadOp = entity.op?.load
|
|
82
|
+
const listOp = entity.op?.list
|
|
83
83
|
|
|
84
84
|
const loadPoint = loadOp?.points?.[0]
|
|
85
85
|
const loadPath = loadPoint ? normalizePathParams(loadPoint.parts || [], loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
@@ -50,7 +50,7 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
50
50
|
// it only applies to entities that declare a list op. Others (e.g. Batch =
|
|
51
51
|
// create/load) have no list endpoint — make_point errors and the stream
|
|
52
52
|
// yields nothing — so skip the stream test for them.
|
|
53
|
-
const hasList = !!(entity.op && (entity.op as any)
|
|
53
|
+
const hasList = !!(entity.op && (entity.op as any)?.list)
|
|
54
54
|
|
|
55
55
|
const basicflow: ModelEntityFlow | undefined =
|
|
56
56
|
getModelPath(model, `main.${KIT}.flow.Basic${nom(entity, 'Name')}Flow`)
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
Folder,
|
|
6
6
|
cmp,
|
|
7
7
|
each,
|
|
8
|
-
entityClassName,
|
|
8
|
+
entityClassName, entityCollection,
|
|
9
9
|
} from '@voxgig/sdkgen'
|
|
10
10
|
|
|
11
11
|
|
|
@@ -27,7 +27,7 @@ const EntityBase = cmp(async function EntityBase(props: any) {
|
|
|
27
27
|
const { model } = props.ctx$
|
|
28
28
|
|
|
29
29
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
30
|
-
const entityColl =
|
|
30
|
+
const entityColl = entityCollection(model)
|
|
31
31
|
|
|
32
32
|
Folder({ name: 'entity' }, () => {
|
|
33
33
|
File({ name: 'mod.' + target.ext }, () => {
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
// types yet (parity intent, not dead-code churn).
|
|
26
26
|
|
|
27
27
|
import {
|
|
28
|
-
cmp, each,
|
|
28
|
+
cmp, each,
|
|
29
29
|
File, Content, Folder,
|
|
30
30
|
} from '@voxgig/sdkgen'
|
|
31
31
|
|
|
32
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
32
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
33
33
|
|
|
34
34
|
import {
|
|
35
35
|
KIT,
|
|
@@ -85,8 +85,7 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
85
85
|
// Emit for every entity that gets an entity file (filter on `name`, always
|
|
86
86
|
// present; derive `Name` here so the struct set is deterministic — parity
|
|
87
87
|
// with the go emitter's fix).
|
|
88
|
-
const entityList =
|
|
89
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
88
|
+
const entityList = deriveEntityNames(entity)
|
|
90
89
|
|
|
91
90
|
// Surface duplicate generated type names (two entities with the same
|
|
92
91
|
// 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,
|
|
6
6
|
File, Content, 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
|
// Collision-free entity CLASS name (see entityClassName): normally
|
|
24
24
|
// `<Name>Entity`, but disambiguated when it would clash with another
|
|
25
25
|
// entity's data-type name.
|
|
26
|
-
const entityColl =
|
|
26
|
+
const entityColl = entityCollection(model)
|
|
27
27
|
const cls = entityClassName(entity, entityColl)
|
|
28
28
|
|
|
29
29
|
const entrep = {
|
|
@@ -37,7 +37,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
37
37
|
|
|
38
38
|
File({ name: rustVarName(entity.name) + '.' + target.ext }, () => {
|
|
39
39
|
|
|
40
|
-
const opnames = Object.keys(entity.op)
|
|
40
|
+
const opnames = Object.keys(entity.op || {})
|
|
41
41
|
|
|
42
42
|
// For each CRUD op: if the spec defines it, splice in the real
|
|
43
43
|
// implementation. Otherwise emit a stub that satisfies the static
|
|
@@ -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,
|
|
@@ -17,7 +17,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
17
17
|
const { entity } = props
|
|
18
18
|
const { model } = props.ctx$
|
|
19
19
|
|
|
20
|
-
const entityColl =
|
|
20
|
+
const entityColl = entityCollection(model)
|
|
21
21
|
const cls = entityClassName(entity, entityColl)
|
|
22
22
|
const method = rustVarName(entity.name)
|
|
23
23
|
const mod = rustVarName(entity.name)
|
|
@@ -43,7 +43,7 @@ path = "lib.rs"
|
|
|
43
43
|
|
|
44
44
|
const prod: Record<string, string> = {}
|
|
45
45
|
const dev: Record<string, string> = {}
|
|
46
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
46
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
47
47
|
// Target-level deps default to '*' when version is absent; feature
|
|
48
48
|
// deps require an explicit version.
|
|
49
49
|
const version = d.source === 'target' ? (d.version || '*') : d.version
|
|
@@ -33,7 +33,10 @@ use std::fs;
|
|
|
33
33
|
use std::path::PathBuf;
|
|
34
34
|
|
|
35
35
|
// Extract the body of every \`\`\`rust ... \`\`\` fenced block from markdown.
|
|
36
|
-
|
|
36
|
+
// Returns the blocks plus a flag that is true when the scan reached EOF with a
|
|
37
|
+
// fence still open (an unterminated \`\`\`rust block) — the caller fails on it
|
|
38
|
+
// rather than silently dropping the malformed block.
|
|
39
|
+
fn extract_rust_blocks(md: &str) -> (Vec<String>, bool) {
|
|
37
40
|
let mut blocks: Vec<String> = Vec::new();
|
|
38
41
|
let mut in_block = false;
|
|
39
42
|
let mut cur: Vec<&str> = Vec::new();
|
|
@@ -53,14 +56,15 @@ fn extract_rust_blocks(md: &str) -> Vec<String> {
|
|
|
53
56
|
}
|
|
54
57
|
cur.push(line);
|
|
55
58
|
}
|
|
56
|
-
blocks
|
|
59
|
+
(blocks, in_block)
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
// Balanced (), [], {} outside of string literals
|
|
60
|
-
//
|
|
62
|
+
// Balanced (), [], {} outside of string literals, with each closer matching the
|
|
63
|
+
// most-recent opener (so "([)]" is rejected, not just counted). Naive quote
|
|
64
|
+
// toggle: the generated snippets never embed an escaped quote inside a string.
|
|
61
65
|
fn is_balanced(block: &str) -> bool {
|
|
62
66
|
let mut in_str = false;
|
|
63
|
-
let mut
|
|
67
|
+
let mut stack: Vec<char> = Vec::new();
|
|
64
68
|
for c in block.chars() {
|
|
65
69
|
if c == '"' {
|
|
66
70
|
in_str = !in_str;
|
|
@@ -70,17 +74,18 @@ fn is_balanced(block: &str) -> bool {
|
|
|
70
74
|
continue;
|
|
71
75
|
}
|
|
72
76
|
match c {
|
|
73
|
-
'('
|
|
77
|
+
'(' => stack.push(')'),
|
|
78
|
+
'[' => stack.push(']'),
|
|
79
|
+
'{' => stack.push('}'),
|
|
74
80
|
')' | ']' | '}' => {
|
|
75
|
-
|
|
76
|
-
if depth < 0 {
|
|
81
|
+
if stack.pop() != Some(c) {
|
|
77
82
|
return false;
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
_ => {}
|
|
81
86
|
}
|
|
82
87
|
}
|
|
83
|
-
|
|
88
|
+
stack.is_empty() && !in_str
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
#[test]
|
|
@@ -98,7 +103,14 @@ fn readme_rust_snippets_wellformed() {
|
|
|
98
103
|
Ok(s) => s,
|
|
99
104
|
Err(_) => continue, // doc not generated in this run — tolerate
|
|
100
105
|
};
|
|
101
|
-
let blocks = extract_rust_blocks(&src);
|
|
106
|
+
let (blocks, unterminated) = extract_rust_blocks(&src);
|
|
107
|
+
// A fence opened but never closed is a malformed doc — fail rather than
|
|
108
|
+
// silently skipping the unterminated block.
|
|
109
|
+
assert!(
|
|
110
|
+
!unterminated,
|
|
111
|
+
"{}: unterminated \`\`\`rust fence (block never closed)",
|
|
112
|
+
label
|
|
113
|
+
);
|
|
102
114
|
for (i, block) in blocks.iter().enumerate() {
|
|
103
115
|
assert!(
|
|
104
116
|
!block.trim().is_empty(),
|
|
@@ -73,7 +73,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
73
73
|
? `("apikey", getp(&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 as any)
|
|
85
|
-
const listOp = (entity.op as any)
|
|
84
|
+
const loadOp = (entity.op as any)?.load
|
|
85
|
+
const listOp = (entity.op as any)?.list
|
|
86
86
|
|
|
87
87
|
// Load point info.
|
|
88
88
|
const loadPoint = loadOp?.points?.[0]
|
|
@@ -75,8 +75,30 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
75
75
|
|
|
76
76
|
const genCtx: GenCtx = { model, entity, rustcrate, flow: basicflow, PROJUPPER }
|
|
77
77
|
|
|
78
|
-
const
|
|
79
|
-
|
|
78
|
+
const opNames = Array.from(new Set(allSteps.map((s: any) => s.op).filter(Boolean)))
|
|
79
|
+
const opsList = opNames.map(o => `"${o}"`).join(', ')
|
|
80
|
+
|
|
81
|
+
// Same hazard as the csharp target: an entity whose basic flow has no ops
|
|
82
|
+
// would emit `for op in []`, and rustc cannot infer the element type of an
|
|
83
|
+
// empty array literal — E0282, type annotations needed. The loop is dead
|
|
84
|
+
// code in that case, and so is the `mode` binding only it reads (which
|
|
85
|
+
// would then warn as unused). Emit neither.
|
|
86
|
+
const skipBlock = 0 === opNames.length ? '' : ` // Per-op sdk-test-control.json skip — the basic test exercises a flow
|
|
87
|
+
// with multiple ops; skipping any op skips the whole flow.
|
|
88
|
+
let mode = if setup.live { "live" } else { "unit" };
|
|
89
|
+
for op in [${opsList}] {
|
|
90
|
+
let (skip, reason) = is_control_skipped("entityOp", &format!("${entity.name}.{}", op), mode);
|
|
91
|
+
if skip {
|
|
92
|
+
let reason = if reason.is_empty() {
|
|
93
|
+
"skipped via sdk-test-control.json".to_string()
|
|
94
|
+
} else {
|
|
95
|
+
reason
|
|
96
|
+
};
|
|
97
|
+
eprintln!("skip: {}", reason);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
`
|
|
80
102
|
|
|
81
103
|
const method = rustVarName(entity.name)
|
|
82
104
|
const evar = rustVarName(entity.name)
|
|
@@ -158,22 +180,7 @@ fn ${evar}_entity_stream() {
|
|
|
158
180
|
#[test]
|
|
159
181
|
fn ${evar}_entity_basic() {
|
|
160
182
|
let setup = ${evar}_basic_setup(Value::Noval);
|
|
161
|
-
//
|
|
162
|
-
// with multiple ops; skipping any op skips the whole flow.
|
|
163
|
-
let mode = if setup.live { "live" } else { "unit" };
|
|
164
|
-
for op in [${opsList}] {
|
|
165
|
-
let (skip, reason) = is_control_skipped("entityOp", &format!("${entity.name}.{}", op), mode);
|
|
166
|
-
if skip {
|
|
167
|
-
let reason = if reason.is_empty() {
|
|
168
|
-
"skipped via sdk-test-control.json".to_string()
|
|
169
|
-
} else {
|
|
170
|
-
reason
|
|
171
|
-
};
|
|
172
|
-
eprintln!("skip: {}", reason);
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// The basic flow consumes synthetic IDs from the fixture. In live mode
|
|
183
|
+
${skipBlock} // The basic flow consumes synthetic IDs from the fixture. In live mode
|
|
177
184
|
// without an *_ENTID env override, those IDs hit the live API and 4xx.
|
|
178
185
|
if setup.synthetic_only {
|
|
179
186
|
eprintln!("skip: live entity test uses synthetic IDs from fixture — set ${PROJUPPER}_TEST_${ENTUPPER}_ENTID JSON to run live");
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
File, Content,
|
|
39
39
|
} from '@voxgig/sdkgen'
|
|
40
40
|
|
|
41
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
41
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
42
42
|
|
|
43
43
|
import {
|
|
44
44
|
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/java/csharp 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
|
File, Content, 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
|
const scalapackage = scalaPackage(model)
|
|
24
24
|
|
|
25
25
|
// Collision-free entity CLASS name.
|
|
26
|
-
const entityColl =
|
|
26
|
+
const entityColl = entityCollection(model)
|
|
27
27
|
const cls = entityClassName(entity, entityColl)
|
|
28
28
|
|
|
29
29
|
const entrep = {
|
|
@@ -39,7 +39,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
39
39
|
|
|
40
40
|
File({ name: cls + '.' + target.ext }, () => {
|
|
41
41
|
|
|
42
|
-
const opnames = Object.keys(entity.op)
|
|
42
|
+
const opnames = Object.keys(entity.op || {})
|
|
43
43
|
|
|
44
44
|
// For each CRUD op: if the spec defines it, splice in the real
|
|
45
45
|
// implementation. Otherwise emit a stub that satisfies the SdkEntity
|
|
@@ -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,
|
|
@@ -18,7 +18,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
18
18
|
const { model } = props.ctx$
|
|
19
19
|
|
|
20
20
|
const scalapackage = scalaPackage(model)
|
|
21
|
-
const entityColl =
|
|
21
|
+
const entityColl = entityCollection(model)
|
|
22
22
|
const cls = entityClassName(entity, entityColl)
|
|
23
23
|
const accessor = scalaVarName(entity.name)
|
|
24
24
|
|
|
@@ -43,8 +43,11 @@ const ReadmeExamplesTest = cmp(function ReadmeExamplesTest(props: any) {
|
|
|
43
43
|
//
|
|
44
44
|
// Checks, PER DOCUMENT:
|
|
45
45
|
// 1. PRESENCE: the doc exists and holds at least one scala block.
|
|
46
|
-
// 2. STRUCTURE: every
|
|
47
|
-
//
|
|
46
|
+
// 2. STRUCTURE: every fence is closed (an odd number of triple-backtick
|
|
47
|
+
// markers means a fence was opened but never closed — the doc is truncated
|
|
48
|
+
// and split-based extraction would mis-segment the tail), AND every scala
|
|
49
|
+
// block's braces / parens / brackets balance, so a truncated or malformed
|
|
50
|
+
// generated snippet fails loudly.
|
|
48
51
|
//
|
|
49
52
|
// GENERATED by @voxgig/sdkgen — do not edit by hand.
|
|
50
53
|
|
|
@@ -85,6 +88,17 @@ object ReadmeExamplesTest {
|
|
|
85
88
|
private def readDoc(path: Path): String =
|
|
86
89
|
new String(Files.readAllBytes(path), "UTF-8")
|
|
87
90
|
|
|
91
|
+
// True when every triple-backtick fence in the document is paired. split(-1)
|
|
92
|
+
// yields (fenceCount + 1) parts, so an even fence count (all fences closed)
|
|
93
|
+
// gives an odd number of parts. An odd fence count means a fence was opened
|
|
94
|
+
// but never closed: the block-extraction above would then treat everything
|
|
95
|
+
// after it as one big "block", and a truncated snippet that happens to
|
|
96
|
+
// balance would pass silently. Detecting it here lets the gate fail loudly.
|
|
97
|
+
private def fencesClosed(text: String): Boolean = {
|
|
98
|
+
val fence = 96.toChar.toString.repeat(3)
|
|
99
|
+
text.split(java.util.regex.Pattern.quote(fence), -1).length % 2 == 1
|
|
100
|
+
}
|
|
101
|
+
|
|
88
102
|
// True when every open/close delimiter balances (ignores the subtlety of
|
|
89
103
|
// delimiters inside string literals — a generated snippet never nests an
|
|
90
104
|
// unbalanced delimiter in a string, and this catches truncation).
|
|
@@ -135,7 +149,12 @@ object ReadmeExamplesTest {
|
|
|
135
149
|
val label = ds(dj)(0)
|
|
136
150
|
val path = Paths.get(ds(dj)(1))
|
|
137
151
|
if (Files.exists(path)) {
|
|
138
|
-
val
|
|
152
|
+
val text = readDoc(path)
|
|
153
|
+
// A fence opened but never closed leaves an odd number of fence
|
|
154
|
+
// markers; fail loudly rather than trusting the mis-segmented tail.
|
|
155
|
+
if (!fencesClosed(text))
|
|
156
|
+
failures.add(label + " has an unclosed scala code fence")
|
|
157
|
+
val blocks = scalaBlocks(text)
|
|
139
158
|
var balancedCount = 0
|
|
140
159
|
var bi = 0
|
|
141
160
|
while (bi < blocks.size()) {
|
|
@@ -65,7 +65,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
65
65
|
const EntityName = nom(entity, 'Name')
|
|
66
66
|
const ENTLOWER = entity.name
|
|
67
67
|
|
|
68
|
-
const opnames = Object.keys(entity.op)
|
|
68
|
+
const opnames = Object.keys(entity.op || {})
|
|
69
69
|
const hasLoad = opnames.includes('load')
|
|
70
70
|
const hasList = opnames.includes('list')
|
|
71
71
|
|
|
@@ -73,8 +73,8 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
73
73
|
return
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
const loadOp = (entity.op as any)
|
|
77
|
-
const listOp = (entity.op as any)
|
|
76
|
+
const loadOp = (entity.op as any)?.load
|
|
77
|
+
const listOp = (entity.op as any)?.list
|
|
78
78
|
|
|
79
79
|
// Load point info.
|
|
80
80
|
const loadPoint = loadOp?.points?.[0]
|
|
@@ -40,7 +40,7 @@ const Test = cmp(function Test(props: any) {
|
|
|
40
40
|
getModelPath(model, `main.${KIT}.flow.Basic${EntityName}Flow`)
|
|
41
41
|
const hasEntity = null != basicflow && true === basicflow.active
|
|
42
42
|
|
|
43
|
-
const opnames = Object.keys(entity.op)
|
|
43
|
+
const opnames = Object.keys(entity.op || {})
|
|
44
44
|
const hasDirect = opnames.includes('load') || opnames.includes('list')
|
|
45
45
|
|
|
46
46
|
if (hasEntity) {
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
// the runtime's open shape.
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
|
-
cmp, each,
|
|
24
|
+
cmp, each,
|
|
25
25
|
File, Content, Folder,
|
|
26
26
|
} from '@voxgig/sdkgen'
|
|
27
27
|
|
|
28
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
28
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames, swiftSafeTypeName } from '@voxgig/sdkgen'
|
|
29
29
|
|
|
30
30
|
import {
|
|
31
31
|
KIT,
|
|
@@ -81,8 +81,7 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
81
81
|
// Emit for every entity that gets an entity file (filter on `name`, always
|
|
82
82
|
// present; derive `Name` here so the struct set is deterministic — parity
|
|
83
83
|
// with the rust/go emitter's fix).
|
|
84
|
-
const entityList =
|
|
85
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
84
|
+
const entityList = deriveEntityNames(entity)
|
|
86
85
|
|
|
87
86
|
// Surface duplicate generated type names (two entities with the same
|
|
88
87
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -115,9 +114,16 @@ import Foundation
|
|
|
115
114
|
.filter((f: any) => f.active !== false)
|
|
116
115
|
|
|
117
116
|
// Entity data model: one property per field. req:false -> optional.
|
|
117
|
+
//
|
|
118
|
+
// Swift has no intra-module namespacing, so a spec schema named
|
|
119
|
+
// after one of our own runtime types (e.g. `Response`) would be a
|
|
120
|
+
// redeclaration and fail the build. swiftSafeTypeName appends
|
|
121
|
+
// `Type` on collision only — `Response` -> `ResponseType` — so
|
|
122
|
+
// non-colliding SDKs generate byte-identical output to before.
|
|
123
|
+
const TypeName = swiftSafeTypeName(Name)
|
|
118
124
|
emitStruct(
|
|
119
|
-
`/// ${
|
|
120
|
-
|
|
125
|
+
`/// ${TypeName} is the typed data model for the ${ent.name} entity.`,
|
|
126
|
+
TypeName,
|
|
121
127
|
fields.map((f: any) => ({ name: f.name, type: f.type, optional: false === f.req }))
|
|
122
128
|
)
|
|
123
129
|
|
|
@@ -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 {
|
|
@@ -20,7 +20,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
20
20
|
const { target, entity } = props
|
|
21
21
|
|
|
22
22
|
// Collision-free entity CLASS name (see entityClassName).
|
|
23
|
-
const entityColl =
|
|
23
|
+
const entityColl = entityCollection(model)
|
|
24
24
|
const cls = entityClassName(entity, entityColl)
|
|
25
25
|
|
|
26
26
|
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
|
const Name = model.const.Name
|
|
@@ -28,7 +28,7 @@ const Package = cmp(async function Package(props: any) {
|
|
|
28
28
|
const Name = model.const.Name
|
|
29
29
|
|
|
30
30
|
const deps: Record<string, string> = {}
|
|
31
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
31
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
32
32
|
deps[d.name] = d.source === 'target' ? (d.version || '0.0.0') : d.version
|
|
33
33
|
}
|
|
34
34
|
// Vendored, dependency-free by design; declared deps (if any) are ignored
|
|
@@ -43,7 +43,9 @@ const ReadmeExamplesTest = cmp(function ReadmeExamplesTest(props: any) {
|
|
|
43
43
|
// Checks, PER DOCUMENT that exists:
|
|
44
44
|
// 1. PRESENCE: the doc holds at least one swift block.
|
|
45
45
|
// 2. STRUCTURE: every swift block's braces / parens / brackets balance, so a
|
|
46
|
-
// truncated or malformed generated snippet fails loudly.
|
|
46
|
+
// truncated or malformed generated snippet fails loudly. An unclosed fence
|
|
47
|
+
// (odd number of fence markers) also fails, rather than silently absorbing
|
|
48
|
+
// the trailing text as a block.
|
|
47
49
|
//
|
|
48
50
|
// GENERATED by @voxgig/sdkgen — do not edit by hand.
|
|
49
51
|
|
|
@@ -94,6 +96,16 @@ final class ReadmeExamplesTest: XCTestCase {
|
|
|
94
96
|
return blocks
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
// True when the doc has a fence that was opened but never closed. A
|
|
100
|
+
// well-formed doc holds fence markers in open/close pairs, so an ODD number
|
|
101
|
+
// of markers means the final fence dangles — the split-based scan above would
|
|
102
|
+
// otherwise silently treat the truncated tail as a block. This is the
|
|
103
|
+
// structural analogue of an at-EOF "still inside a block" check.
|
|
104
|
+
private func hasUnclosedFence(_ text: String) -> Bool {
|
|
105
|
+
let fenceCount = text.components(separatedBy: fence).count - 1
|
|
106
|
+
return fenceCount % 2 != 0
|
|
107
|
+
}
|
|
108
|
+
|
|
97
109
|
// True when every open/close delimiter balances, ignoring characters inside
|
|
98
110
|
// string literals and line comments (a generated snippet never nests an
|
|
99
111
|
// unbalanced delimiter outside those, and this catches truncation).
|
|
@@ -149,6 +161,11 @@ final class ReadmeExamplesTest: XCTestCase {
|
|
|
149
161
|
var failures: [String] = []
|
|
150
162
|
for doc in docs() {
|
|
151
163
|
guard let text = read(doc.path) else { continue }
|
|
164
|
+
// A fence opened but never closed is a malformed doc — fail loudly rather
|
|
165
|
+
// than silently absorbing the unterminated tail as a block.
|
|
166
|
+
if hasUnclosedFence(text) {
|
|
167
|
+
failures.append(doc.label + " has an unclosed swift code fence")
|
|
168
|
+
}
|
|
152
169
|
let blocks = swiftBlocks(text)
|
|
153
170
|
var balancedCount = 0
|
|
154
171
|
for (i, b) in blocks.enumerated() {
|
|
@@ -24,7 +24,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
24
24
|
|
|
25
25
|
const Name = model.const.Name
|
|
26
26
|
|
|
27
|
-
const opnames = Object.keys(entity.op)
|
|
27
|
+
const opnames = Object.keys(entity.op || {})
|
|
28
28
|
if (!opnames.includes('load') && !opnames.includes('list')) {
|
|
29
29
|
return
|
|
30
30
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
indent,
|
|
13
13
|
isAuthActive,
|
|
14
14
|
resolveAuthPrefix,
|
|
15
|
+
serverVariables,
|
|
15
16
|
} from '@voxgig/sdkgen'
|
|
16
17
|
|
|
17
18
|
|
|
@@ -53,6 +54,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
53
54
|
`
|
|
54
55
|
: ''
|
|
55
56
|
|
|
57
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
58
|
+
// runtime can substitute {name} placeholders in base (see makeOptions).
|
|
59
|
+
const svars = serverVariables(model)
|
|
60
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
61
|
+
'server: {\n' +
|
|
62
|
+
svars.map((v: any) => ` ${JSON.stringify(v.name)}: ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
63
|
+
' },\n\n '
|
|
64
|
+
|
|
56
65
|
File({ name: 'Config.' + target.ext }, () => {
|
|
57
66
|
|
|
58
67
|
Fragment({
|
|
@@ -60,6 +69,8 @@ const Config = cmp(async function Config(props: any) {
|
|
|
60
69
|
|
|
61
70
|
replace: {
|
|
62
71
|
|
|
72
|
+
"'SERVERBLOCK'": serverBlock,
|
|
73
|
+
|
|
63
74
|
"'AUTHBLOCK'": authBlock,
|
|
64
75
|
|
|
65
76
|
"'HEADERS'": indent(JSON.stringify(headers, null, 2), 4).trim(),
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
File, Content,
|
|
22
22
|
} from '@voxgig/sdkgen'
|
|
23
23
|
|
|
24
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
24
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
25
25
|
|
|
26
26
|
import {
|
|
27
27
|
KIT,
|
|
@@ -51,11 +51,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
51
51
|
// filter, so inactive entities still get class files referencing these
|
|
52
52
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
53
53
|
// with the go emitter's fix.
|
|
54
|
-
const entityList =
|
|
54
|
+
const entityList = deriveEntityNames(entity)
|
|
55
55
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
56
56
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
57
57
|
// `Name = undefined` below. Parity with the go emitter's fix.
|
|
58
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
59
58
|
|
|
60
59
|
// Surface duplicate generated type names (two entities with the same
|
|
61
60
|
// 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, each, camelify, names,
|
|
6
6
|
File, Content, Folder, Fragment, Line, FeatureHook, Slot,
|
|
7
|
-
opTypeName, entityClassName,
|
|
7
|
+
opTypeName, entityClassName, entityCollection,
|
|
8
8
|
} from '@voxgig/sdkgen'
|
|
9
9
|
|
|
10
10
|
import {
|
|
@@ -24,7 +24,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
24
24
|
// `<Name>Entity`, disambiguated when it would clash with another entity's
|
|
25
25
|
// data-type name. The DATA type stays `<Name>`. The class file name and the
|
|
26
26
|
// Main import path both use this, so they always agree.
|
|
27
|
-
const entityColl =
|
|
27
|
+
const entityColl = entityCollection(model)
|
|
28
28
|
const cls = entityClassName(entity, entityColl)
|
|
29
29
|
|
|
30
30
|
const entrep = {
|
|
@@ -52,7 +52,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
52
52
|
|
|
53
53
|
File({ name: cls + '.' + target.name }, () => {
|
|
54
54
|
|
|
55
|
-
const opnames = Object.keys(entity.op)
|
|
55
|
+
const opnames = Object.keys(entity.op || {})
|
|
56
56
|
|
|
57
57
|
const opfrags =
|
|
58
58
|
(['load', 'list', 'create', 'update', 'remove']
|