@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
package/src/cmp/Deploy.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
// `publish` sections (see model/sdkgen.aontu):
|
|
11
11
|
//
|
|
12
12
|
// publish.tag — git release tag `<prefix>/vX.Y.Z`; every port has
|
|
13
|
-
// one, pushed with a token from the
|
|
13
|
+
// one, pushed with a token from the boru key vault
|
|
14
14
|
// (--for recipe + alias, default github/github).
|
|
15
15
|
// publish.registry — package registry details (name, url, vault
|
|
16
16
|
// credential recipe or raw env mapping) plus a
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
// Follows the voxgig/struct root Makefile conventions: per-target deploy
|
|
26
26
|
// targets, deliberately no all-targets real deploy (each upload is
|
|
27
27
|
// irreversible), and an everything-at-once DRY run leaning on
|
|
28
|
-
// `
|
|
28
|
+
// `boru vault exec --dry-run` filler-token cooperation in each target's
|
|
29
29
|
// publish recipe.
|
|
30
30
|
const Deploy = cmp(function Deploy(props: any) {
|
|
31
31
|
const { ctx$ } = props
|
|
@@ -76,7 +76,7 @@ function aliasVarName(name: string): string {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
// The
|
|
79
|
+
// The boru vault exec argument string for a target: `--for=<recipe>=<alias>`
|
|
80
80
|
// flags where a preset recipe exists, or a raw `'alias=ENV_VAR,...'`
|
|
81
81
|
// mapping when any credential lacks a preset (e.g. luarocks). The github
|
|
82
82
|
// token for the tag push is always included.
|
|
@@ -142,10 +142,10 @@ function makeDeployMakefile(model: any, targets: any[]): string {
|
|
|
142
142
|
return `
|
|
143
143
|
deploy-${t.name}:
|
|
144
144
|
\t@echo "deploy-${t.name}: tag-only port — publishing the git tag."
|
|
145
|
-
\
|
|
145
|
+
\tboru vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
|
|
146
146
|
|
|
147
147
|
deploy-dry-${t.name}:
|
|
148
|
-
\
|
|
148
|
+
\tboru vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
|
|
149
149
|
${tagPushRecipe(t.name, 'tag-only port')}
|
|
150
150
|
`
|
|
151
151
|
}
|
|
@@ -157,20 +157,20 @@ ${tagPushRecipe(t.name, 'tag-only port')}
|
|
|
157
157
|
return `
|
|
158
158
|
deploy-${t.name}:
|
|
159
159
|
\t@echo "deploy-${t.name}: ${reg.name} publication is pending — publishing the git tag only."
|
|
160
|
-
\
|
|
160
|
+
\tboru vault exec ${ghArgs} -- $(MAKE) tag-push-${t.name}
|
|
161
161
|
|
|
162
162
|
deploy-dry-${t.name}:
|
|
163
|
-
\
|
|
163
|
+
\tboru vault exec --dry-run ${ghArgs} -- $(MAKE) tag-push-${t.name}
|
|
164
164
|
${tagPushRecipe(t.name, reg.name + ' publication pending — tag-only deploy')}
|
|
165
165
|
`
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
return `
|
|
169
169
|
deploy-${t.name}:
|
|
170
|
-
\
|
|
170
|
+
\tboru vault exec ${args} -- $(MAKE) -C ${t.name} publish
|
|
171
171
|
|
|
172
172
|
deploy-dry-${t.name}:
|
|
173
|
-
\
|
|
173
|
+
\tboru vault exec --dry-run ${args} -- $(MAKE) -C ${t.name} publish
|
|
174
174
|
`
|
|
175
175
|
}).join('')
|
|
176
176
|
|
|
@@ -183,7 +183,7 @@ deploy-dry-${t.name}:
|
|
|
183
183
|
#
|
|
184
184
|
# Every port gets a git release tag <target>/vX.Y.Z. Ports with an ACTIVE
|
|
185
185
|
# registry also publish a package there. Credentials are injected at exec
|
|
186
|
-
# time by the
|
|
186
|
+
# time by the boru key vault (https://github.com/boru-lang/boru) — never
|
|
187
187
|
# stored on disk or passed on the command line.
|
|
188
188
|
#
|
|
189
189
|
# Publication state (from the model):
|
|
@@ -194,7 +194,7 @@ ${summary}
|
|
|
194
194
|
# registry upload is irreversible); while a
|
|
195
195
|
# registry is pending this publishes the
|
|
196
196
|
# port's git tag only
|
|
197
|
-
# make deploy-dry rehearse EVERY target:
|
|
197
|
+
# make deploy-dry rehearse EVERY target: boru --dry-run
|
|
198
198
|
# injects a filler token that each publish
|
|
199
199
|
# recipe detects, so build + test run in full
|
|
200
200
|
# but nothing is uploaded and no tag is cut
|
|
@@ -207,7 +207,7 @@ ${varLines}
|
|
|
207
207
|
|
|
208
208
|
# Lockstep SDK version, read from the canonical ts manifest.
|
|
209
209
|
VERSION := $(shell node -p "require('./ts/package.json').version" 2>/dev/null || echo 0.0.0)
|
|
210
|
-
|
|
210
|
+
BORU_DRY_RUN_FILLER := BORU-DRY-RUN-FILLER-NOT-A-REAL-SECRET
|
|
211
211
|
|
|
212
212
|
TARGETS := ${targets.map((t: any) => t.name).join(' ')}
|
|
213
213
|
|
|
@@ -233,7 +233,7 @@ ${deployRules}`
|
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
|
|
236
|
-
// The root-level tag creation + push recipe for a target:
|
|
236
|
+
// The root-level tag creation + push recipe for a target: boru --dry-run
|
|
237
237
|
// filler cooperation, idempotent tag creation, token-authenticated https
|
|
238
238
|
// push (works from an ssh-remote clone without ssh keys).
|
|
239
239
|
function tagPushRecipe(name: string, note: string): string {
|
|
@@ -241,9 +241,9 @@ function tagPushRecipe(name: string, note: string): string {
|
|
|
241
241
|
tag-push-${name}:
|
|
242
242
|
\t@set -e; tag="${name}/v$(VERSION)"; \\
|
|
243
243
|
\ttoken="\$\${GITHUB_TOKEN:-$$GH_TOKEN}"; \\
|
|
244
|
-
\tif [ "$$token" = "$(
|
|
245
|
-
\t echo "[dry-run]
|
|
246
|
-
\tif [ -z "$$token" ]; then echo "tag-push-${name}: no GITHUB_TOKEN in env — run via make deploy-${name} (
|
|
244
|
+
\tif [ "$$token" = "$(BORU_DRY_RUN_FILLER)" ]; then \\
|
|
245
|
+
\t echo "[dry-run] boru filler token detected: would create (if missing) and push tag $$tag; nothing pushed."; exit 0; fi; \\
|
|
246
|
+
\tif [ -z "$$token" ]; then echo "tag-push-${name}: no GITHUB_TOKEN in env — run via make deploy-${name} (boru vault exec)"; exit 1; fi; \\
|
|
247
247
|
\tif git rev-parse -q --verify "refs/tags/$$tag" >/dev/null; then \\
|
|
248
248
|
\t echo "tag $$tag already exists — pushing existing tag"; \\
|
|
249
249
|
\telse git tag -a "$$tag" -m "Release $$tag"; fi; \\
|
package/src/cmp/Entity.ts
CHANGED
|
@@ -21,8 +21,12 @@ const Entity = cmp(function Entity(props: any) {
|
|
|
21
21
|
const Entity_sdk = requirePath(ctx$, `./cmp/${target.name}/Entity_${target.name}`)
|
|
22
22
|
Entity_sdk['Entity']({ target, entity, entitySDK })
|
|
23
23
|
|
|
24
|
+
// Log identifiers, not the model subtrees. `target` and `entity` are large
|
|
25
|
+
// aontu nodes and this fires once per entity per target (thousands of times
|
|
26
|
+
// for a big API x 22 targets), so passing them serialised the whole model
|
|
27
|
+
// fragment each time at default log level.
|
|
24
28
|
log.info({
|
|
25
|
-
point: 'generate-entity', target, entity,
|
|
29
|
+
point: 'generate-entity', target: target.name, entity: entity.name,
|
|
26
30
|
note: 'target:' + target.name + ', ' + 'entity: ' + entity.name
|
|
27
31
|
})
|
|
28
32
|
})
|
package/src/cmp/Feature.ts
CHANGED
|
@@ -19,7 +19,8 @@ const Feature = cmp(function Feature(props: any) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
log.info({
|
|
22
|
-
|
|
22
|
+
// Identifiers only — see the note in Entity.ts.
|
|
23
|
+
point: 'generate-feature', target: target.name, feature: feature.name,
|
|
23
24
|
note: 'target:' + target.name + ', ' + 'feature: ' + feature.name
|
|
24
25
|
})
|
|
25
26
|
|
package/src/cmp/ReadmeTop.ts
CHANGED
|
@@ -549,28 +549,30 @@ Pass custom features via the \`extend\` option at construction time.
|
|
|
549
549
|
`)
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
-
// 13. Upstream API —
|
|
552
|
+
// 13. Upstream API — always disclose the OpenAPI origin and where the
|
|
553
|
+
// spec(s) live; contact/servers links come from the OpenAPI info block.
|
|
553
554
|
const upstreamUrl = (info.contact && info.contact.url)
|
|
554
555
|
|| (info.servers && info.servers[0] && info.servers[0].url)
|
|
555
556
|
|| homepage
|
|
556
|
-
|
|
557
|
-
Content(`## Upstream API
|
|
557
|
+
Content(`## Upstream API
|
|
558
558
|
|
|
559
559
|
This SDK is generated from the upstream OpenAPI specification. It is an
|
|
560
560
|
unofficial client and is not affiliated with the API provider.
|
|
561
561
|
|
|
562
|
+
The OpenAPI spec(s) this SDK was generated from are kept in the
|
|
563
|
+
[\`.sdk/def/\`](.sdk/def/) folder.
|
|
564
|
+
|
|
562
565
|
`)
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
`)
|
|
566
|
-
}
|
|
567
|
-
if (docsUrl && docsUrl !== upstreamUrl) {
|
|
568
|
-
Content(`- Documentation: [${docsUrl}](${docsUrl})
|
|
566
|
+
if (upstreamUrl) {
|
|
567
|
+
Content(`- Upstream API: [${upstreamUrl}](${upstreamUrl})
|
|
569
568
|
`)
|
|
570
|
-
|
|
571
|
-
|
|
569
|
+
}
|
|
570
|
+
if (docsUrl && docsUrl !== upstreamUrl) {
|
|
571
|
+
Content(`- Documentation: [${docsUrl}](${docsUrl})
|
|
572
572
|
`)
|
|
573
573
|
}
|
|
574
|
+
Content(`
|
|
575
|
+
`)
|
|
574
576
|
|
|
575
577
|
// 13b. Security
|
|
576
578
|
Content(`## Security
|
package/src/helpers/canonType.ts
CHANGED
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
// the SINGLE mapping per language: components must not keep local copies.
|
|
15
15
|
//
|
|
16
16
|
// Kept as a small mirror here (rather than importing VALID_CANON at runtime)
|
|
17
|
-
// because apidef is a peer dependency and the table is the INVERSE direction
|
|
18
|
-
//
|
|
19
|
-
//
|
|
17
|
+
// because apidef is a peer dependency and the table is the INVERSE direction.
|
|
18
|
+
//
|
|
19
|
+
// `ts/test/canonsync.test.ts` guards it two ways: the vocabulary and every
|
|
20
|
+
// language column are pinned LOCALLY (that check always runs), and the table
|
|
21
|
+
// is cross-checked against apidef's exported VALID_CANON/CANON_ONE when the
|
|
22
|
+
// installed apidef exports them. Note that the currently published apidef
|
|
23
|
+
// (6.3.1) does NOT export them, so the cross-check skips — do not rely on it
|
|
24
|
+
// alone; add a new sentinel to the local list in the same change.
|
|
20
25
|
//
|
|
21
26
|
// KNOWN GAPS (papered over sanely, documented for the port):
|
|
22
27
|
// - Unknown / missing sentinel -> the language's "any" (never throws).
|
|
@@ -27,21 +27,53 @@ function collectDeps(
|
|
|
27
27
|
model: SdkModel,
|
|
28
28
|
targetName: string,
|
|
29
29
|
targetDeps: Record<string, ModelDep> | undefined,
|
|
30
|
+
log?: any,
|
|
30
31
|
): DepEntry[] {
|
|
31
32
|
const out: DepEntry[] = []
|
|
32
33
|
const feature = getModelPath(model, `main.${KIT}.feature`)
|
|
33
34
|
|
|
35
|
+
// Deduplicate by package name. Two features can require the same package
|
|
36
|
+
// (or a feature and the target itself can), and every Package_<lang>.ts
|
|
37
|
+
// renders one manifest line per entry — a duplicate key is a hard parse
|
|
38
|
+
// error in go.mod and Cargo.toml, and silently last-wins in package.json.
|
|
39
|
+
// FIRST occurrence wins, so the deterministic (sorted-key) feature order
|
|
40
|
+
// decides; a conflicting version is reported rather than silently dropped.
|
|
41
|
+
const seen: Record<string, DepEntry> = {}
|
|
42
|
+
|
|
43
|
+
const add = (dep: any, source: 'feature' | 'target', owner: string) => {
|
|
44
|
+
const name = dep.key$
|
|
45
|
+
if (null == name) return
|
|
46
|
+
|
|
47
|
+
const prev = seen[name]
|
|
48
|
+
if (null != prev) {
|
|
49
|
+
if (log?.warn && prev.version !== dep.version) {
|
|
50
|
+
log.warn({
|
|
51
|
+
point: 'dep-version-conflict', target: targetName, dep: name,
|
|
52
|
+
kept: prev.version, dropped: dep.version, from: owner,
|
|
53
|
+
note: `${targetName}: dependency ${name} declared twice with ` +
|
|
54
|
+
`different versions — keeping ${prev.version} (${prev.source}), ` +
|
|
55
|
+
`ignoring ${dep.version} (${source} ${owner})`,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const entry: DepEntry = {
|
|
62
|
+
name,
|
|
63
|
+
version: dep.version,
|
|
64
|
+
source,
|
|
65
|
+
raw: dep,
|
|
66
|
+
}
|
|
67
|
+
seen[name] = entry
|
|
68
|
+
out.push(entry)
|
|
69
|
+
}
|
|
70
|
+
|
|
34
71
|
each(feature, (f: any) => {
|
|
35
72
|
const langDeps = f?.deps?.[targetName]
|
|
36
73
|
if (!langDeps) return
|
|
37
74
|
each(langDeps, (dep: any) => {
|
|
38
75
|
if (dep?.active) {
|
|
39
|
-
|
|
40
|
-
name: dep.key$,
|
|
41
|
-
version: dep.version,
|
|
42
|
-
source: 'feature',
|
|
43
|
-
raw: dep,
|
|
44
|
-
})
|
|
76
|
+
add(dep, 'feature', f.name)
|
|
45
77
|
}
|
|
46
78
|
})
|
|
47
79
|
})
|
|
@@ -49,12 +81,7 @@ function collectDeps(
|
|
|
49
81
|
if (targetDeps) {
|
|
50
82
|
each(targetDeps, (dep: any) => {
|
|
51
83
|
if (dep?.active !== false) {
|
|
52
|
-
|
|
53
|
-
name: dep.key$,
|
|
54
|
-
version: dep.version,
|
|
55
|
-
source: 'target',
|
|
56
|
-
raw: dep,
|
|
57
|
-
})
|
|
84
|
+
add(dep, 'target', targetName)
|
|
58
85
|
}
|
|
59
86
|
})
|
|
60
87
|
}
|
package/src/helpers/naming.ts
CHANGED
|
@@ -69,6 +69,132 @@ const RESERVED: Record<string, Set<string>> = {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
// Ruby CORE CONSTANTS — a different hazard from the keyword sets above.
|
|
73
|
+
//
|
|
74
|
+
// The keyword sets guard local-variable BINDINGS. This set guards generated
|
|
75
|
+
// top-level CONSTANTS. Ruby constants share one namespace with the core
|
|
76
|
+
// classes, and reassigning one is not an error — it silently replaces it:
|
|
77
|
+
//
|
|
78
|
+
// File = Struct.new(:name) # ::File is now a Struct
|
|
79
|
+
// File.join('a', 'b') # NoMethodError — every later caller breaks
|
|
80
|
+
//
|
|
81
|
+
// The typed model emits `<Name> = Struct.new(...)` per entity, so an API with
|
|
82
|
+
// a `/files` collection (entity `File`) used to clobber Ruby's File class and
|
|
83
|
+
// take the whole SDK down with it — the generated test runner calls
|
|
84
|
+
// `File.join` to locate `.env.local`, so `rb` failed at require time.
|
|
85
|
+
//
|
|
86
|
+
// Only names Ruby itself defines at top level are listed: reassigning any of
|
|
87
|
+
// them breaks working code somewhere. Names that merely LOOK builtin but are
|
|
88
|
+
// not core constants (e.g. `Response`, `Record`) are safe and stay untouched,
|
|
89
|
+
// which keeps the rename off every SDK that does not actually collide.
|
|
90
|
+
const RB_CORE_CONSTANTS = new Set<string>([
|
|
91
|
+
// classes an entity name plausibly lands on
|
|
92
|
+
'Array', 'Binding', 'Class', 'Comparable', 'Complex', 'Data', 'Dir',
|
|
93
|
+
'Encoding', 'Enumerator', 'Exception', 'Fiber', 'File', 'Float', 'Hash',
|
|
94
|
+
'IO', 'Integer', 'Method', 'Module', 'Mutex', 'Numeric', 'Object', 'Proc',
|
|
95
|
+
'Queue', 'Random', 'Range', 'Rational', 'Regexp', 'Set', 'Signal', 'String',
|
|
96
|
+
'Struct', 'Symbol', 'Thread', 'Time', 'UnboundMethod',
|
|
97
|
+
// modules / singletons
|
|
98
|
+
'Enumerable', 'GC', 'Kernel', 'Marshal', 'Math', 'ObjectSpace', 'Process',
|
|
99
|
+
'Warning',
|
|
100
|
+
// the rest of the exception hierarchy an API might name an entity after
|
|
101
|
+
'ArgumentError', 'IndexError', 'IOError', 'KeyError', 'NameError',
|
|
102
|
+
'NotImplementedError', 'RangeError', 'RuntimeError', 'StandardError',
|
|
103
|
+
'StopIteration', 'SystemExit', 'TypeError', 'ZeroDivisionError',
|
|
104
|
+
// literal singletons
|
|
105
|
+
'FalseClass', 'NilClass', 'TrueClass',
|
|
106
|
+
])
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// Is `Name` a constant Ruby already defines at top level?
|
|
110
|
+
function isRbCoreConstant(Name: string): boolean {
|
|
111
|
+
return RB_CORE_CONSTANTS.has(Name)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
// A top-level-safe Ruby constant name for a generated type: the name
|
|
116
|
+
// unchanged, unless Ruby core already owns it, in which case `Type` is
|
|
117
|
+
// appended (`File` -> `FileType`). Applied ONLY to the bare entity data type
|
|
118
|
+
// — the per-op type names always carry a suffix (`FileCreateData`,
|
|
119
|
+
// `FileLoadMatch`), which no core constant matches.
|
|
120
|
+
//
|
|
121
|
+
// The entity ACCESSOR keeps its original name (`client.File(...)`): methods
|
|
122
|
+
// and constants live in separate namespaces in Ruby, so the accessor never
|
|
123
|
+
// collided and the public surface is unchanged.
|
|
124
|
+
function rbSafeTypeName(Name: string): string {
|
|
125
|
+
return isRbCoreConstant(Name) ? Name + 'Type' : Name
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// Swift SDK-OWNED TYPE NAMES — a third hazard, distinct from both sets above.
|
|
130
|
+
//
|
|
131
|
+
// The keyword sets guard local bindings; the Ruby set guards clobbering the
|
|
132
|
+
// LANGUAGE's core. This set guards clobbering OUR OWN runtime, because Swift
|
|
133
|
+
// has no namespacing WITHIN a module: every type the swift templates declare
|
|
134
|
+
// and every generated entity type land in the same module. Two declarations
|
|
135
|
+
// of one name is a hard error, not a silent override:
|
|
136
|
+
//
|
|
137
|
+
// // core/Response.swift (template)
|
|
138
|
+
// public final class Response { ... } // transport wrapper
|
|
139
|
+
// // entity/<Prefix>Types.swift (generated from a spec schema named Response)
|
|
140
|
+
// public struct Response { ... }
|
|
141
|
+
// -> error: invalid redeclaration of 'Response'
|
|
142
|
+
// -> error: 'Response' is ambiguous for type lookup (every core file)
|
|
143
|
+
//
|
|
144
|
+
// Found 2026-08-07: the Hook0 spec has a `Response` schema, which took the
|
|
145
|
+
// whole swift target down. `Response` is merely the first collision to be
|
|
146
|
+
// hit — every name below is equally exposed.
|
|
147
|
+
//
|
|
148
|
+
// Sourced by scanning BOTH `tm/swift/Sources/*/` (templates) and
|
|
149
|
+
// `src/cmp/swift/*.ts` (components) for top-level type declarations —
|
|
150
|
+
// regardless of access level. `internal` is Swift's default and is still
|
|
151
|
+
// module-wide, and `open class BaseFeature` is not `public` either, so an
|
|
152
|
+
// access-level filter under-collects and silently reopens the bug.
|
|
153
|
+
//
|
|
154
|
+
// Nested types (a `typealias Element` inside a struct) and the separate Tests
|
|
155
|
+
// module (`ReadmeExamplesTest`) do NOT share this namespace and are excluded.
|
|
156
|
+
//
|
|
157
|
+
// `swift-sdk-types.test.ts` re-derives this list from the templates and fails
|
|
158
|
+
// on drift, so adding a public type to a swift template cannot silently
|
|
159
|
+
// reopen the bug.
|
|
160
|
+
const SWIFT_SDK_TYPES = new Set<string>([
|
|
161
|
+
// core runtime
|
|
162
|
+
'Context', 'Control', 'Entity', 'Operation', 'Point', 'Response', 'Result',
|
|
163
|
+
'SdkConfig', 'Spec', 'Utility',
|
|
164
|
+
// struct library
|
|
165
|
+
'Injection', 'Injector', 'JSON', 'JSONParseError', 'Modify',
|
|
166
|
+
'OrderedDictionary', 'Sentinel', 'Value', 'VList', 'VMap', 'WalkApply',
|
|
167
|
+
// function/callback aliases
|
|
168
|
+
'FetcherFunc', 'Formatter', 'NativeCall0', 'NativeRef', 'SystemFetch',
|
|
169
|
+
// features
|
|
170
|
+
'AuditFeature', 'BaseFeature', 'CacheFeature', 'ClienttrackFeature',
|
|
171
|
+
'DebugFeature', 'IdempotencyFeature', 'LogFeature', 'MetricsBucket',
|
|
172
|
+
'MetricsFeature', 'NetsimFeature', 'PagingFeature', 'ProxyFeature',
|
|
173
|
+
'RatelimitFeature', 'RbacFeature', 'RetryFeature', 'StreamingFeature',
|
|
174
|
+
'TelemetryFeature', 'TestFeature', 'TimeoutFeature',
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
// Does `Name` collide with a type the swift SDK runtime already declares?
|
|
179
|
+
function isSwiftSdkType(Name: string): boolean {
|
|
180
|
+
return SWIFT_SDK_TYPES.has(Name)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
// A module-safe Swift type name for a generated type: unchanged, unless the
|
|
185
|
+
// swift runtime already declares it, in which case `Type` is appended
|
|
186
|
+
// (`Response` -> `ResponseType`). Mirrors rbSafeTypeName deliberately — same
|
|
187
|
+
// suffix, same "only rename on an actual collision" rule, so SDKs that do not
|
|
188
|
+
// collide are byte-identical to before.
|
|
189
|
+
//
|
|
190
|
+
// Applied ONLY to the bare entity data type. Per-op type names already carry
|
|
191
|
+
// their own suffix (`ResponseCreateData`, `ResponseLoadMatch`) and the entity
|
|
192
|
+
// CLASS is separately suffixed (`ResponseEntity`), so neither ever collided.
|
|
193
|
+
function swiftSafeTypeName(Name: string): string {
|
|
194
|
+
return isSwiftSdkType(Name) ? Name + 'Type' : Name
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
72
198
|
// Is `name` a reserved word (an illegal identifier) in the target language?
|
|
73
199
|
function isReservedName(name: string, lang: string): boolean {
|
|
74
200
|
const set = RESERVED[lang]
|
|
@@ -130,6 +256,10 @@ export {
|
|
|
130
256
|
isReservedName,
|
|
131
257
|
safeVarName,
|
|
132
258
|
exampleVarName,
|
|
259
|
+
isRbCoreConstant,
|
|
260
|
+
rbSafeTypeName,
|
|
261
|
+
isSwiftSdkType,
|
|
262
|
+
swiftSafeTypeName,
|
|
133
263
|
jsProp,
|
|
134
264
|
jsOptProp,
|
|
135
265
|
jsKey,
|
package/src/helpers/opShape.ts
CHANGED
|
@@ -26,7 +26,60 @@
|
|
|
26
26
|
// flag) and render them in the target language's struct/interface/TypedDict
|
|
27
27
|
// syntax; the policy itself is language-neutral and tested in isolation.
|
|
28
28
|
|
|
29
|
-
import { each } from 'jostraca'
|
|
29
|
+
import { each, names } from 'jostraca'
|
|
30
|
+
import { KIT, getModelPath } from '@voxgig/apidef'
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// THE entity collection for a model — resolved once, with a stable identity.
|
|
34
|
+
//
|
|
35
|
+
// Two problems this solves, both caused by every component calling
|
|
36
|
+
// `getModelPath(model, 'main.<KIT>.entity')` for itself:
|
|
37
|
+
//
|
|
38
|
+
// * CORRECTNESS. getModelPath drops `active: false` entries by default, but
|
|
39
|
+
// the consumer scaffold (create-sdkgen Root.ts) generates entity code for
|
|
40
|
+
// EVERY entity and every EntityTypes_<lang> emits data types with
|
|
41
|
+
// `only_active: false`. Class-name assignment done against the filtered
|
|
42
|
+
// view cannot see the inactive entities whose data types it must avoid.
|
|
43
|
+
// This resolver always returns the unfiltered collection.
|
|
44
|
+
//
|
|
45
|
+
// * PERFORMANCE. getModelPath REBUILDS the container object on every call
|
|
46
|
+
// when filtering, so the WeakMap memos below never hit across callers —
|
|
47
|
+
// the O(n·ops) class-name assignment re-ran per entity per target. At 500
|
|
48
|
+
// entities x 22 targets that was ~15s of pure recomputation; caching the
|
|
49
|
+
// resolved collection on the model makes it ~3ms.
|
|
50
|
+
const _entityCollCache = new WeakMap<object, any>()
|
|
51
|
+
|
|
52
|
+
function entityCollection(model: any): any {
|
|
53
|
+
if (null == model || 'object' !== typeof model) {
|
|
54
|
+
return {}
|
|
55
|
+
}
|
|
56
|
+
const cached = _entityCollCache.get(model)
|
|
57
|
+
if (null != cached) {
|
|
58
|
+
return cached
|
|
59
|
+
}
|
|
60
|
+
const coll = getModelPath(model, `main.${KIT}.entity`,
|
|
61
|
+
{ only_active: false, required: false }) || {}
|
|
62
|
+
deriveEntityNames(coll)
|
|
63
|
+
_entityCollCache.set(model, coll)
|
|
64
|
+
return coll
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// Derive the PascalCase `Name` on every entity in a collection.
|
|
69
|
+
//
|
|
70
|
+
// `Name` is injected LAZILY by jostraca's names(), historically by whichever
|
|
71
|
+
// component happened to run first (create-sdkgen Root.ts, or an EntityTypes
|
|
72
|
+
// emitter). Anything reading `e.Name` before that ran saw `undefined` — and
|
|
73
|
+
// because the helpers below MEMOISE, one early read poisoned the result for
|
|
74
|
+
// the whole run (`undefinedEntity` class names; a permanently empty collision
|
|
75
|
+
// list). The helpers therefore derive `Name` themselves, up front, so they
|
|
76
|
+
// never depend on component ordering. Idempotent: names() is only called for
|
|
77
|
+
// an entity that lacks `Name`.
|
|
78
|
+
function deriveEntityNames(entityColl: any): any[] {
|
|
79
|
+
const ents = each(entityColl).filter((e: any) => e && null != e.name)
|
|
80
|
+
ents.forEach((e: any) => { if (null == e.Name) names(e, e.name) })
|
|
81
|
+
return ents
|
|
82
|
+
}
|
|
30
83
|
|
|
31
84
|
|
|
32
85
|
// The five ops, and whether their request payload is a `Match` (query/id) or
|
|
@@ -156,8 +209,21 @@ function opRequestShape(ent: any, opname: string):
|
|
|
156
209
|
return { items: [], fromParams: false }
|
|
157
210
|
}
|
|
158
211
|
|
|
212
|
+
// Ops that carry a BODY are the exception to "op-declared params win":
|
|
213
|
+
// their request payload is BOTH. `PUT /v1/todo/item/{id}` declares the path
|
|
214
|
+
// param `id`, which the SDK resolves out of reqdata (see the param
|
|
215
|
+
// utility's reqmatch -> match -> reqdata search), while the fields the
|
|
216
|
+
// caller wants to change come from the entity. Params alone produced
|
|
217
|
+
// `<Name>UpdateData = { id }` — no way to send anything to update.
|
|
218
|
+
//
|
|
219
|
+
// The param stays in the payload because the path needs it; keeping it out
|
|
220
|
+
// of the request BODY is the model's job, via the op's `transform.req`
|
|
221
|
+
// (@voxgig/apidef restricts the body to a closed request schema's declared
|
|
222
|
+
// properties).
|
|
223
|
+
const isbodyop = 'create' === opname || 'update' === opname || 'patch' === opname
|
|
224
|
+
|
|
159
225
|
const params = opParams(op)
|
|
160
|
-
if (0 < params.length) {
|
|
226
|
+
if (0 < params.length && !isbodyop) {
|
|
161
227
|
const items = params.map((p: any) => ({
|
|
162
228
|
name: p.name,
|
|
163
229
|
type: p.type,
|
|
@@ -166,15 +232,25 @@ function opRequestShape(ent: any, opname: string):
|
|
|
166
232
|
return { items, fromParams: true }
|
|
167
233
|
}
|
|
168
234
|
|
|
235
|
+
const paramItems = isbodyop ? params.map((p: any) => ({
|
|
236
|
+
name: p.name,
|
|
237
|
+
type: p.type,
|
|
238
|
+
optional: false === p.reqd,
|
|
239
|
+
})) : []
|
|
240
|
+
const paramNames = new Set(paramItems.map((p: any) => p.name))
|
|
241
|
+
|
|
169
242
|
const fields = (ent.fields ? each(ent.fields) : [])
|
|
170
243
|
.filter((f: any) => f.active !== false)
|
|
171
244
|
.filter((f: any) => fieldInOp(f, opname))
|
|
172
245
|
|
|
173
|
-
const items =
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
246
|
+
const items = paramItems.concat(
|
|
247
|
+
fields
|
|
248
|
+
.filter((f: any) => !paramNames.has(f.name))
|
|
249
|
+
.map((f: any) => ({
|
|
250
|
+
name: f.name,
|
|
251
|
+
type: f.type,
|
|
252
|
+
optional: fieldOptional(f, opname),
|
|
253
|
+
})))
|
|
178
254
|
|
|
179
255
|
return { items, fromParams: false }
|
|
180
256
|
}
|
|
@@ -250,6 +326,16 @@ function entityPrimaryOp(ent: any): string | null {
|
|
|
250
326
|
// … The DATA type keeps its canonical `<Name>` — only the suffixed class
|
|
251
327
|
// yields. Deterministic (sorted-key iteration) and stable across runs.
|
|
252
328
|
//
|
|
329
|
+
// Covers EVERY entity, active or not: the consumer scaffold (create-sdkgen
|
|
330
|
+
// Root.ts) iterates the RAW entity collection, and every EntityTypes_<lang>
|
|
331
|
+
// emits with `only_active: false`, so an inactive entity still contributes a
|
|
332
|
+
// generated data type AND still needs a class name. Filtering to actives here
|
|
333
|
+
// left inactive entities on the un-deduped `<Name>Entity` fallback and left
|
|
334
|
+
// their data types out of `taken` — so an ACTIVE entity's class could collide
|
|
335
|
+
// with an INACTIVE entity's emitted data type (e.g. active `project` ->
|
|
336
|
+
// class `ProjectEntity` vs inactive `project-entity` -> type `ProjectEntity`,
|
|
337
|
+
// a redeclaration in Go).
|
|
338
|
+
//
|
|
253
339
|
// Memoised per entity-collection object so the O(n) assignment runs once.
|
|
254
340
|
const _classNameCache = new WeakMap<object, Record<string, string>>()
|
|
255
341
|
|
|
@@ -259,7 +345,7 @@ function entityClassNames(entityColl: any): Record<string, string> {
|
|
|
259
345
|
return cached
|
|
260
346
|
}
|
|
261
347
|
|
|
262
|
-
const ents =
|
|
348
|
+
const ents = deriveEntityNames(entityColl)
|
|
263
349
|
|
|
264
350
|
// 1. Every top-level DATA-type name the target emits.
|
|
265
351
|
const taken: Record<string, boolean> = {}
|
|
@@ -314,8 +400,8 @@ function entityClassName(ent: any, entityColl: any): string {
|
|
|
314
400
|
// merging in ts. The names cannot be auto-renamed here — the generated
|
|
315
401
|
// entity classes and op fragments reference them by token — so the guard
|
|
316
402
|
// surfaces the collision loudly instead. Returns the sorted duplicate names
|
|
317
|
-
// (empty when clean).
|
|
318
|
-
//
|
|
403
|
+
// (empty when clean). `Name` is derived here (deriveEntityNames), so the
|
|
404
|
+
// guard cannot be silently disabled by running before an emitter.
|
|
319
405
|
//
|
|
320
406
|
// Memoised per entity-collection object, like entityClassNames.
|
|
321
407
|
const _typeCollisionCache = new WeakMap<object, string[]>()
|
|
@@ -329,8 +415,7 @@ function entityTypeCollisions(entityColl: any): string[] {
|
|
|
329
415
|
const counts: Record<string, number> = {}
|
|
330
416
|
const bump = (n: string) => { counts[n] = (counts[n] || 0) + 1 }
|
|
331
417
|
|
|
332
|
-
|
|
333
|
-
.filter((e: any) => e && null != e.name && null != e.Name)
|
|
418
|
+
deriveEntityNames(entityColl)
|
|
334
419
|
.forEach((e: any) => {
|
|
335
420
|
bump(e.Name)
|
|
336
421
|
for (const op of ['load', 'list', 'create', 'update', 'remove']) {
|
|
@@ -444,6 +529,8 @@ function entityDataIdField(ent: any): string | null {
|
|
|
444
529
|
|
|
445
530
|
export {
|
|
446
531
|
OP_SUFFIX,
|
|
532
|
+
deriveEntityNames,
|
|
533
|
+
entityCollection,
|
|
447
534
|
opTypeName,
|
|
448
535
|
opParams,
|
|
449
536
|
opRequestShape,
|