@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`)
|
|
@@ -45,8 +45,11 @@ let read_file (path : string) : string option =
|
|
|
45
45
|
|
|
46
46
|
let split_lines (s : string) : string list = String.split_on_char '\\n' s
|
|
47
47
|
|
|
48
|
-
(* Extract the body of every \`\`\`ocaml ... \`\`\` fenced block from markdown.
|
|
49
|
-
|
|
48
|
+
(* Extract the body of every \`\`\`ocaml ... \`\`\` fenced block from markdown.
|
|
49
|
+
* Returns (blocks, unclosed) where unclosed is true when a fence was opened
|
|
50
|
+
* but never closed before EOF — a malformed doc that must fail rather than
|
|
51
|
+
* silently drop the unterminated block. *)
|
|
52
|
+
let extract_ocaml_blocks (md : string) : string list * bool =
|
|
50
53
|
let blocks = ref [] in
|
|
51
54
|
let cur = ref [] in
|
|
52
55
|
let in_block = ref false in
|
|
@@ -61,23 +64,31 @@ let extract_ocaml_blocks (md : string) : string list =
|
|
|
61
64
|
end
|
|
62
65
|
else cur := line :: !cur)
|
|
63
66
|
(split_lines md);
|
|
64
|
-
List.rev !blocks
|
|
67
|
+
(List.rev !blocks, !in_block)
|
|
65
68
|
|
|
66
|
-
(* Balanced (), [], {} outside of string literals
|
|
67
|
-
*
|
|
69
|
+
(* Balanced (), [], {} outside of string literals, with each closer matching
|
|
70
|
+
* the most-recent opener (so "([)]" is rejected, not just counted). Naive
|
|
71
|
+
* quote toggle: the generated snippets never embed an escaped quote inside a
|
|
72
|
+
* string. *)
|
|
68
73
|
let is_balanced (block : string) : bool =
|
|
69
74
|
let in_str = ref false in
|
|
70
|
-
let
|
|
75
|
+
let stack = ref [] in
|
|
71
76
|
let ok = ref true in
|
|
72
77
|
String.iter (fun c ->
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
if !ok then
|
|
79
|
+
if c = '"' then in_str := not !in_str
|
|
80
|
+
else if not !in_str then
|
|
81
|
+
match c with
|
|
82
|
+
| '(' -> stack := ')' :: !stack
|
|
83
|
+
| '[' -> stack := ']' :: !stack
|
|
84
|
+
| '{' -> stack := '}' :: !stack
|
|
85
|
+
| ')' | ']' | '}' ->
|
|
86
|
+
(match !stack with
|
|
87
|
+
| top :: rest when top = c -> stack := rest
|
|
88
|
+
| _ -> ok := false)
|
|
89
|
+
| _ -> ())
|
|
79
90
|
block;
|
|
80
|
-
!ok && !
|
|
91
|
+
!ok && !stack = [] && not !in_str
|
|
81
92
|
|
|
82
93
|
let docs = [
|
|
83
94
|
("root README", "../README.md");
|
|
@@ -92,13 +103,17 @@ let () =
|
|
|
92
103
|
match read_file path with
|
|
93
104
|
| None -> () (* doc not generated in this run — tolerate *)
|
|
94
105
|
| Some src ->
|
|
106
|
+
let (blocks, unclosed) = extract_ocaml_blocks src in
|
|
107
|
+
(* A fence opened but never closed is a malformed doc — fail
|
|
108
|
+
* rather than silently skipping the unterminated block. *)
|
|
109
|
+
check (label ^ " ocaml fence closed") (not unclosed);
|
|
95
110
|
List.iteri (fun i block ->
|
|
96
111
|
check (label ^ " block " ^ string_of_int (i + 1) ^ " non-empty")
|
|
97
112
|
(trim block <> "");
|
|
98
113
|
check (label ^ " block " ^ string_of_int (i + 1) ^ " balanced delimiters")
|
|
99
114
|
(is_balanced block);
|
|
100
115
|
incr total)
|
|
101
|
-
|
|
116
|
+
blocks)
|
|
102
117
|
docs;
|
|
103
118
|
check "at least one ocaml code block across the docs" (!total > 0))
|
|
104
119
|
`)
|
|
@@ -4,7 +4,7 @@ import * as Path from 'node:path'
|
|
|
4
4
|
import {
|
|
5
5
|
cmp, camelify, names,
|
|
6
6
|
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`, disambiguated when it would clash with another entity's
|
|
24
24
|
// data-type name. The snake-cased source-file name is unaffected.
|
|
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: entity.name + '_entity.pm' }, () => {
|
|
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,
|
|
@@ -14,7 +14,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
14
14
|
|
|
15
15
|
// Return the collision-free class (entityClassName); the accessor METHOD
|
|
16
16
|
// name (entity.Name) is unchanged so callers still write $client->{Name}.
|
|
17
|
-
const cls = entityClassName(entity,
|
|
17
|
+
const cls = entityClassName(entity, entityCollection(model))
|
|
18
18
|
|
|
19
19
|
Content(`
|
|
20
20
|
# Canonical facade: $client->${entity.Name}->list / ->load({ 'id' => ... })
|
|
@@ -27,7 +27,7 @@ const Package = cmp(async function Package(props: any) {
|
|
|
27
27
|
// (e.g. "Voxgig::SDK::Solar" -> dist voxgig-sdk-solar).
|
|
28
28
|
const Name = model.const.Name
|
|
29
29
|
|
|
30
|
-
const deps = collectDeps(model, target.name, target.deps)
|
|
30
|
+
const deps = collectDeps(model, target.name, target.deps, ctx$.log)
|
|
31
31
|
const prereq = deps
|
|
32
32
|
.map((d: any) => ` '${d.name}' => '${d.version || '0'}',`)
|
|
33
33
|
.join('\n')
|
|
@@ -80,7 +80,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
80
80
|
? `\n 'apikey' => $env->{'${PROJECTNAME}_APIKEY'},`
|
|
81
81
|
: ''
|
|
82
82
|
|
|
83
|
-
const opnames = Object.keys(entity.op)
|
|
83
|
+
const opnames = Object.keys(entity.op || {})
|
|
84
84
|
const hasLoad = opnames.includes('load')
|
|
85
85
|
const hasList = opnames.includes('list')
|
|
86
86
|
|
|
@@ -88,8 +88,8 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
88
88
|
return
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
const loadOp = entity.op
|
|
92
|
-
const listOp = entity.op
|
|
91
|
+
const loadOp = entity.op?.load
|
|
92
|
+
const listOp = entity.op?.list
|
|
93
93
|
|
|
94
94
|
const loadPoint = loadOp?.points?.[0]
|
|
95
95
|
const loadPath = loadPoint ? normalizePathParams(loadPoint.parts || [], loadPoint?.args?.params || [], loadPoint?.rename?.param) : ''
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,16 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see MakeOptions).
|
|
52
|
+
// `$` is escaped so a default can never open a PHP interpolation.
|
|
53
|
+
const svars = serverVariables(model)
|
|
54
|
+
const phps = (s: string) => JSON.stringify(s).replace(/\$/g, '\\$')
|
|
55
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
56
|
+
' "server" => [\n' +
|
|
57
|
+
svars.map((v: any) => ` ${phps(v.name)} => ${phps(v.dflt)},\n`).join('') +
|
|
58
|
+
' ],\n'
|
|
59
|
+
|
|
49
60
|
const authBlock = authActive
|
|
50
61
|
? ` "auth" => [
|
|
51
62
|
"prefix" => "${authPrefix}",
|
|
@@ -84,7 +95,7 @@ class ${model.const.Name}Config
|
|
|
84
95
|
Content(` ],
|
|
85
96
|
"options" => [
|
|
86
97
|
"base" => "${baseUrl}",
|
|
87
|
-
${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
98
|
+
${serverBlock}${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
88
99
|
"entity" => (object)[],
|
|
89
100
|
],
|
|
90
101
|
"entity" => (object)[],
|
|
@@ -94,7 +105,7 @@ ${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
|
94
105
|
Content(` ],
|
|
95
106
|
"options" => [
|
|
96
107
|
"base" => "${baseUrl}",
|
|
97
|
-
${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
108
|
+
${serverBlock}${authBlock} "headers" => ${formatPhpArray(headers, 4)},
|
|
98
109
|
"entity" => [
|
|
99
110
|
`)
|
|
100
111
|
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
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,
|
|
@@ -79,11 +79,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
79
79
|
// filter, so inactive entities still get class files referencing these
|
|
80
80
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
81
81
|
// with the go emitter's fix.
|
|
82
|
-
const entityList =
|
|
82
|
+
const entityList = deriveEntityNames(entity)
|
|
83
83
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
84
84
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
85
85
|
// `Name = undefined` below. Parity with the go emitter's fix.
|
|
86
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
87
86
|
|
|
88
87
|
// Surface duplicate generated type names (two entities with the same
|
|
89
88
|
// 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
|
-
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`, disambiguated when it would clash with another entity's
|
|
24
24
|
// data-type name. The snake-cased source-file name is unaffected.
|
|
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: entity.name + '_entity.' + 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,
|
|
@@ -20,7 +20,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
20
20
|
|
|
21
21
|
// Collision-free entity CLASS name (entityClassName); the accessor METHOD name
|
|
22
22
|
// (below) is unchanged so callers still write $client->${entity.Name}().
|
|
23
|
-
const cls = entityClassName(entity,
|
|
23
|
+
const cls = entityClassName(entity, entityCollection(model))
|
|
24
24
|
|
|
25
25
|
// Canonical facade method name is the PascalCase entity Name
|
|
26
26
|
// (`$client->${entity.Name}()`). PHP method names are case-insensitive, so
|
|
@@ -49,7 +49,7 @@ const Package = cmp(async function Package(props: any) {
|
|
|
49
49
|
"require": {
|
|
50
50
|
"php": ">=8.2"`)
|
|
51
51
|
|
|
52
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
52
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
53
53
|
const v = d.source === 'target' ? (d.version || '0.0') : d.version
|
|
54
54
|
Content(`,
|
|
55
55
|
"${d.name}": "^${v}"`)
|
|
@@ -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) : ''
|
|
@@ -53,7 +53,7 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
53
53
|
// it only applies to entities that declare a list op. Others (e.g. Batch =
|
|
54
54
|
// create/load) have no list endpoint — make_point errors and the stream
|
|
55
55
|
// yields nothing — so skip the stream test for them.
|
|
56
|
-
const hasList = !!(entity.op && (entity.op as any)
|
|
56
|
+
const hasList = !!(entity.op && (entity.op as any)?.list)
|
|
57
57
|
|
|
58
58
|
const basicflow: ModelEntityFlow | undefined =
|
|
59
59
|
getModelPath(model, `main.${KIT}.flow.Basic${nom(entity, 'Name')}Flow`)
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,14 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see make_options).
|
|
52
|
+
const svars = serverVariables(model)
|
|
53
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
54
|
+
' "server": {\n' +
|
|
55
|
+
svars.map((v: any) => ` ${JSON.stringify(v.name)}: ${JSON.stringify(v.dflt)},\n`).join('') +
|
|
56
|
+
' },\n'
|
|
57
|
+
|
|
49
58
|
const authBlock = authActive
|
|
50
59
|
? ` "auth": {
|
|
51
60
|
"prefix": "${authPrefix}",
|
|
@@ -74,7 +83,7 @@ def make_config():
|
|
|
74
83
|
Content(` },
|
|
75
84
|
"options": {
|
|
76
85
|
"base": "${baseUrl}",
|
|
77
|
-
${authBlock} "headers": ${formatPyDict(headers, 3)},
|
|
86
|
+
${serverBlock}${authBlock} "headers": ${formatPyDict(headers, 3)},
|
|
78
87
|
"entity": {
|
|
79
88
|
`)
|
|
80
89
|
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
File, Content,
|
|
37
37
|
} from '@voxgig/sdkgen'
|
|
38
38
|
|
|
39
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
39
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames } from '@voxgig/sdkgen'
|
|
40
40
|
|
|
41
41
|
import {
|
|
42
42
|
KIT,
|
|
@@ -142,11 +142,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
142
142
|
// filter, so inactive entities still get class files referencing these
|
|
143
143
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
144
144
|
// with the go emitter's fix.
|
|
145
|
-
const entityList =
|
|
145
|
+
const entityList = deriveEntityNames(entity)
|
|
146
146
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
147
147
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
148
148
|
// `Name = undefined` below. Parity with the go emitter's fix.
|
|
149
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
150
149
|
|
|
151
150
|
// Surface duplicate generated type names (two entities with the same
|
|
152
151
|
// 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
|
-
entityClassName, opTypeName,
|
|
7
|
+
entityClassName, entityCollection, opTypeName,
|
|
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 DATA type stays `<Name>`. The snake-cased source-file
|
|
25
25
|
// name is unaffected; only the class identifier changes.
|
|
26
|
-
const entityColl =
|
|
26
|
+
const entityColl = entityCollection(model)
|
|
27
27
|
const cls = entityClassName(entity, entityColl)
|
|
28
28
|
|
|
29
29
|
const entrep = {
|
|
@@ -53,7 +53,7 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
53
53
|
|
|
54
54
|
File({ name: entity.name + '_entity.' + target.ext }, () => {
|
|
55
55
|
|
|
56
|
-
const opnames = Object.keys(entity.op)
|
|
56
|
+
const opnames = Object.keys(entity.op || {})
|
|
57
57
|
|
|
58
58
|
const opfrags =
|
|
59
59
|
(['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 (entityClassName); the accessor METHOD name
|
|
16
16
|
// (entity.Name) is unchanged so callers still write client.<Name>(). The
|
|
17
17
|
// source module is snake-cased, so only the imported class identifier changes.
|
|
18
|
-
const cls = entityClassName(entity,
|
|
18
|
+
const cls = entityClassName(entity, entityCollection(model))
|
|
19
19
|
|
|
20
20
|
Content(`
|
|
21
21
|
def ${entity.Name}(self, data=None) -> "${cls}":
|
|
@@ -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
|
|
|
@@ -94,7 +94,7 @@ from typing import TYPE_CHECKING
|
|
|
94
94
|
if TYPE_CHECKING:
|
|
95
95
|
`)
|
|
96
96
|
each(entity, (ent: any) => {
|
|
97
|
-
Content(` from entity.${ent.name}_entity import ${entityClassName(ent,
|
|
97
|
+
Content(` from entity.${ent.name}_entity import ${entityClassName(ent, entityCollection(model))}
|
|
98
98
|
`)
|
|
99
99
|
})
|
|
100
100
|
}
|
|
@@ -47,7 +47,7 @@ dependencies = [
|
|
|
47
47
|
`)
|
|
48
48
|
|
|
49
49
|
const seen = new Set<string>()
|
|
50
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
50
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
51
51
|
if (seen.has(d.name)) continue
|
|
52
52
|
seen.add(d.name)
|
|
53
53
|
const v = d.source === 'target' ? (d.version || '0.0') : d.version
|
|
@@ -70,7 +70,7 @@ const TestDirect = cmp(function TestDirect(props: any) {
|
|
|
70
70
|
? `\n "apikey": env.get("${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) : ''
|
|
@@ -82,7 +82,7 @@ const TestEntity = cmp(function TestEntity(props: any) {
|
|
|
82
82
|
// it only applies to entities that actually declare a `list` op. Others
|
|
83
83
|
// (e.g. Batch = create/load) have no list endpoint — make_point would error
|
|
84
84
|
// and the stream would yield nothing — so skip the test for them.
|
|
85
|
-
const hasList = !!(entity.op && (entity.op as any)
|
|
85
|
+
const hasList = !!(entity.op && (entity.op as any)?.list)
|
|
86
86
|
|
|
87
87
|
File({ name: 'test_' + entity.name + '_entity.' + target.ext }, () => {
|
|
88
88
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
each,
|
|
12
12
|
isAuthActive,
|
|
13
13
|
resolveAuthPrefix,
|
|
14
|
+
serverVariables,
|
|
14
15
|
} from '@voxgig/sdkgen'
|
|
15
16
|
|
|
16
17
|
|
|
@@ -46,6 +47,16 @@ const Config = cmp(async function Config(props: any) {
|
|
|
46
47
|
let baseUrl = ''
|
|
47
48
|
try { baseUrl = getModelPath(model, `main.${KIT}.info.servers.0.url`) } catch (_e) { }
|
|
48
49
|
|
|
50
|
+
// Templated server URL: emit the spec's server-variable defaults so the
|
|
51
|
+
// runtime can substitute {name} placeholders in base (see make_options).
|
|
52
|
+
// `#` is escaped so a default can never open a Ruby interpolation.
|
|
53
|
+
const svars = serverVariables(model)
|
|
54
|
+
const rbs = (s: string) => JSON.stringify(s).replace(/#/g, '\\#')
|
|
55
|
+
const serverBlock = 0 === svars.length ? '' :
|
|
56
|
+
' "server" => {\n' +
|
|
57
|
+
svars.map((v: any) => ` ${rbs(v.name)} => ${rbs(v.dflt)},\n`).join('') +
|
|
58
|
+
' },\n'
|
|
59
|
+
|
|
49
60
|
const authBlock = authActive
|
|
50
61
|
? ` "auth" => {
|
|
51
62
|
"prefix" => "${authPrefix}",
|
|
@@ -74,7 +85,7 @@ module ${model.const.Name}Config
|
|
|
74
85
|
Content(` },
|
|
75
86
|
"options" => {
|
|
76
87
|
"base" => "${baseUrl}",
|
|
77
|
-
${authBlock} "headers" => ${formatRubyHash(headers, 4)},
|
|
88
|
+
${serverBlock}${authBlock} "headers" => ${formatRubyHash(headers, 4)},
|
|
78
89
|
"entity" => {
|
|
79
90
|
`)
|
|
80
91
|
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
// $STRING -> String, $INTEGER -> Integer, $NUMBER -> Float, $BOOLEAN -> Boolean,
|
|
13
13
|
// $OBJECT -> Hash, $ARRAY -> Array, unknown -> Object.
|
|
14
14
|
//
|
|
15
|
-
// Type-name scheme (
|
|
15
|
+
// Type-name scheme (as TS, with one Ruby-only guard): data type = <Name>,
|
|
16
|
+
// except where Ruby core already owns that constant — `File`, `Time`, `Data`,
|
|
17
|
+
// … — which would be silently REPLACED by the assignment; those become
|
|
18
|
+
// <Name>Type (see rbSafeTypeName). Per-op request
|
|
16
19
|
// <Name>LoadMatch / <Name>ListMatch / <Name>RemoveMatch (query/id ops),
|
|
17
20
|
// <Name>CreateData / <Name>UpdateData (body ops). An op WITH params -> a Struct of
|
|
18
21
|
// those params (reqd:false -> annotated `[Type, nil]`). An op WITHOUT params -> a
|
|
@@ -27,7 +30,7 @@ import {
|
|
|
27
30
|
File, Content,
|
|
28
31
|
} from '@voxgig/sdkgen'
|
|
29
32
|
|
|
30
|
-
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions } from '@voxgig/sdkgen'
|
|
33
|
+
import { canonToType, opTypeName, opRequestShape, warnEntityTypeCollisions , deriveEntityNames, rbSafeTypeName } from '@voxgig/sdkgen'
|
|
31
34
|
|
|
32
35
|
import {
|
|
33
36
|
KIT,
|
|
@@ -89,11 +92,10 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
89
92
|
// filter, so inactive entities still get class files referencing these
|
|
90
93
|
// typed names. Filter on `name` (always present), NOT `active` — parity
|
|
91
94
|
// with the go emitter's fix.
|
|
92
|
-
const entityList =
|
|
95
|
+
const entityList = deriveEntityNames(entity)
|
|
93
96
|
// Derive the PascalCase Name up-front — it is set LAZILY by names(), so an
|
|
94
97
|
// entity not yet named (e.g. a fieldless placeholder) would otherwise read
|
|
95
98
|
// `Name = undefined` below. Parity with the go emitter's fix.
|
|
96
|
-
entityList.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
97
99
|
|
|
98
100
|
// Surface duplicate generated type names (two entities with the same
|
|
99
101
|
// PascalCase Name) — they would redeclare a type in statically-typed
|
|
@@ -116,12 +118,20 @@ const EntityTypes = cmp(function EntityTypes(props: any) {
|
|
|
116
118
|
|
|
117
119
|
entityList.forEach((ent: any) => {
|
|
118
120
|
const Name = ent.Name
|
|
121
|
+
// Ruby constants share ONE namespace with the core classes, and
|
|
122
|
+
// assigning one silently replaces it — an entity named `File` emitting
|
|
123
|
+
// `File = Struct.new(...)` clobbers ::File and every later `File.join`
|
|
124
|
+
// raises NoMethodError. Only the bare data-type constant needs the
|
|
125
|
+
// guard; the per-op names below always carry a suffix that no core
|
|
126
|
+
// constant matches. The `client.File(...)` accessor is a METHOD, a
|
|
127
|
+
// separate namespace, so the public surface is unchanged.
|
|
128
|
+
const TypeName = rbSafeTypeName(Name)
|
|
119
129
|
const fields = (ent.fields ? each(ent.fields) : [])
|
|
120
130
|
.filter((f: any) => f.active !== false)
|
|
121
131
|
|
|
122
132
|
// Entity data model: one member per field (`req:false` -> nilable).
|
|
123
133
|
emitStruct(
|
|
124
|
-
|
|
134
|
+
TypeName,
|
|
125
135
|
`${Name} entity data model.`,
|
|
126
136
|
fields.map((f: any) => ({ name: f.name, type: f.type, optional: false === f.req })),
|
|
127
137
|
)
|
|
@@ -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 {
|
|
@@ -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`, disambiguated when it would clash with another entity's
|
|
24
24
|
// data-type name. The snake-cased source-file name is unaffected.
|
|
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: entity.name + '_entity.' + 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,
|
|
@@ -14,7 +14,7 @@ const MainEntity = cmp(async function MainEntity(props: any) {
|
|
|
14
14
|
|
|
15
15
|
// Return the collision-free class (entityClassName); the accessor METHOD name
|
|
16
16
|
// (entity.Name) is unchanged so callers still write client.<Name>.
|
|
17
|
-
const cls = entityClassName(entity,
|
|
17
|
+
const cls = entityClassName(entity, entityCollection(model))
|
|
18
18
|
|
|
19
19
|
Content(`
|
|
20
20
|
# Canonical facade: client.${entity.Name}.list / client.${entity.Name}.load({ "id" => ... })
|
|
@@ -39,7 +39,7 @@ gemspec
|
|
|
39
39
|
|
|
40
40
|
`)
|
|
41
41
|
|
|
42
|
-
for (const d of collectDeps(model, target.name, target.deps)) {
|
|
42
|
+
for (const d of collectDeps(model, target.name, target.deps, ctx$.log)) {
|
|
43
43
|
Content(`gem "${d.name}", "~> ${versionOf(d)}"
|
|
44
44
|
`)
|
|
45
45
|
}
|
|
@@ -51,7 +51,7 @@ gemspec
|
|
|
51
51
|
// twice (Gem::InvalidSpecificationException at `gem build`), so the
|
|
52
52
|
// unconstrained json fallback is only emitted when the model's own
|
|
53
53
|
// dependency list doesn't already declare json.
|
|
54
|
-
const deps = collectDeps(model, target.name, target.deps)
|
|
54
|
+
const deps = collectDeps(model, target.name, target.deps, ctx$.log)
|
|
55
55
|
const hasJson = deps.some((d: any) => 'json' === d.name)
|
|
56
56
|
|
|
57
57
|
Content(`Gem::Specification.new do |spec|
|