@voxgig/sdkgen 1.2.0 → 1.3.1
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 +2 -2
- package/dist/action/action.d.ts +2 -1
- package/dist/action/action.js +15 -9
- package/dist/action/action.js.map +1 -1
- package/dist/action/feature.js +6 -3
- package/dist/action/feature.js.map +1 -1
- package/dist/action/target.d.ts +7 -1
- package/dist/action/target.js +13 -6
- package/dist/action/target.js.map +1 -1
- package/dist/cmp/Changelog.d.ts +2 -0
- package/dist/cmp/Changelog.js +30 -0
- package/dist/cmp/Changelog.js.map +1 -0
- package/dist/cmp/Deploy.d.ts +2 -0
- package/dist/cmp/Deploy.js +227 -0
- package/dist/cmp/Deploy.js.map +1 -0
- package/dist/cmp/FeatureHook.js +5 -6
- package/dist/cmp/FeatureHook.js.map +1 -1
- package/dist/cmp/License.d.ts +2 -0
- package/dist/cmp/License.js +44 -0
- package/dist/cmp/License.js.map +1 -0
- package/dist/cmp/Readme.js +2 -0
- package/dist/cmp/Readme.js.map +1 -1
- package/dist/cmp/ReadmeErrors.d.ts +2 -0
- package/dist/cmp/ReadmeErrors.js +210 -0
- package/dist/cmp/ReadmeErrors.js.map +1 -0
- package/dist/cmp/ReadmeExplanation.js +213 -223
- package/dist/cmp/ReadmeExplanation.js.map +1 -1
- package/dist/cmp/ReadmeModel.js +6 -1
- package/dist/cmp/ReadmeModel.js.map +1 -1
- package/dist/cmp/ReadmeTop.js +389 -82
- package/dist/cmp/ReadmeTop.js.map +1 -1
- package/dist/cmp/Security.d.ts +2 -0
- package/dist/cmp/Security.js +36 -0
- package/dist/cmp/Security.js.map +1 -0
- package/dist/helpers/canonType.d.ts +7 -0
- package/dist/helpers/canonType.js +74 -0
- package/dist/helpers/canonType.js.map +1 -0
- package/dist/helpers/collectDeps.d.ts +3 -2
- package/dist/helpers/collectDeps.js.map +1 -1
- package/dist/helpers/naming.d.ts +3 -0
- package/dist/helpers/naming.js +51 -0
- package/dist/helpers/naming.js.map +1 -0
- package/dist/helpers/opExample.d.ts +13 -0
- package/dist/helpers/opExample.js +149 -0
- package/dist/helpers/opExample.js.map +1 -0
- package/dist/helpers/opShape.d.ts +18 -0
- package/dist/helpers/opShape.js +193 -0
- package/dist/helpers/opShape.js.map +1 -0
- package/dist/helpers/packageMeta.d.ts +27 -0
- package/dist/helpers/packageMeta.js +224 -0
- package/dist/helpers/packageMeta.js.map +1 -0
- package/dist/sdkgen.d.ts +11 -1
- package/dist/sdkgen.js +57 -18
- package/dist/sdkgen.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +65 -2
- package/dist/types.js.map +1 -1
- package/dist/utility.js +20 -11
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aontu +137 -0
- package/package.json +13 -6
- package/project/.sdk/model/target/go-cli.jsonic +47 -0
- package/project/.sdk/model/target/go-mcp.jsonic +41 -0
- package/project/.sdk/model/target/go.jsonic +9 -3
- package/project/.sdk/model/target/js.jsonic +13 -0
- package/project/.sdk/model/target/lua.jsonic +13 -0
- package/project/.sdk/model/target/php.jsonic +13 -0
- package/project/.sdk/model/target/py.jsonic +13 -0
- package/project/.sdk/model/target/rb.jsonic +13 -0
- package/project/.sdk/model/target/ts.jsonic +13 -0
- package/project/.sdk/src/cmp/go/EntityOperation_go.ts +1 -0
- package/project/.sdk/src/cmp/go/EntityTypes_go.ts +197 -0
- package/project/.sdk/src/cmp/go/Entity_go.ts +2 -1
- package/project/.sdk/src/cmp/go/MainEntity_go.ts +6 -0
- package/project/.sdk/src/cmp/go/Main_go.ts +23 -3
- package/project/.sdk/src/cmp/go/Package_go.ts +1 -1
- package/project/.sdk/src/cmp/go/ReadmeEntity_go.ts +18 -6
- package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +684 -0
- package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +48 -8
- package/project/.sdk/src/cmp/go/ReadmeInstall_go.ts +11 -6
- package/project/.sdk/src/cmp/go/ReadmeIntro_go.ts +40 -1
- package/project/.sdk/src/cmp/go/ReadmeModel_go.ts +63 -17
- package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +4 -3
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +124 -115
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +28 -15
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +33 -9
- package/project/.sdk/src/cmp/go/ReadmeTopTest_go.ts +35 -5
- package/project/.sdk/src/cmp/go/TestEntity_go.ts +1 -1
- package/project/.sdk/src/cmp/go/Test_go.ts +5 -1
- package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +21 -0
- package/project/.sdk/src/cmp/go/fragment/EntityCreateOp.fragment.go +11 -0
- package/project/.sdk/src/cmp/go/fragment/EntityListOp.fragment.go +11 -0
- package/project/.sdk/src/cmp/go/fragment/EntityLoadOp.fragment.go +11 -0
- package/project/.sdk/src/cmp/go/fragment/EntityRemoveOp.fragment.go +11 -0
- package/project/.sdk/src/cmp/go/fragment/EntityUpdateOp.fragment.go +11 -0
- package/project/.sdk/src/cmp/go-cli/Main_go-cli.ts +195 -0
- package/project/.sdk/src/cmp/go-cli/fragment/main.fragment.go +106 -0
- package/project/.sdk/src/cmp/go-cli/fragment/words.fragment.go +132 -0
- package/project/.sdk/src/cmp/go-mcp/Main_go-mcp.ts +184 -0
- package/project/.sdk/src/cmp/go-mcp/fragment/main.fragment.go +68 -0
- package/project/.sdk/src/cmp/go-mcp/fragment/tools.fragment.go +114 -0
- package/project/.sdk/src/cmp/js/EntityTypes_js.ts +111 -0
- package/project/.sdk/src/cmp/js/MainEntity_js.ts +1 -0
- package/project/.sdk/src/cmp/js/Main_js.ts +3 -0
- package/project/.sdk/src/cmp/js/Package_js.ts +16 -7
- package/project/.sdk/src/cmp/js/ReadmeEntity_js.ts +13 -7
- package/project/.sdk/src/cmp/js/ReadmeExplanation_js.ts +2 -2
- package/project/.sdk/src/cmp/js/ReadmeHowto_js.ts +52 -11
- package/project/.sdk/src/cmp/js/ReadmeIntro_js.ts +39 -1
- package/project/.sdk/src/cmp/js/ReadmeModel_js.ts +50 -18
- package/project/.sdk/src/cmp/js/ReadmeOptions_js.ts +4 -3
- package/project/.sdk/src/cmp/js/ReadmeQuick_js.ts +45 -19
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +24 -13
- package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +3 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +28 -12
- package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +23 -3
- package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +5 -0
- package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +5 -0
- package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +5 -0
- package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +5 -0
- package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +5 -0
- package/project/.sdk/src/cmp/js/utility_js.ts +57 -0
- package/project/.sdk/src/cmp/lua/EntityTypes_lua.ts +113 -0
- package/project/.sdk/src/cmp/lua/MainEntity_lua.ts +8 -0
- package/project/.sdk/src/cmp/lua/Main_lua.ts +4 -0
- package/project/.sdk/src/cmp/lua/Package_lua.ts +23 -4
- package/project/.sdk/src/cmp/lua/ReadmeEntity_lua.ts +12 -10
- package/project/.sdk/src/cmp/lua/ReadmeExamplesTest_lua.ts +293 -0
- package/project/.sdk/src/cmp/lua/ReadmeHowto_lua.ts +46 -8
- package/project/.sdk/src/cmp/lua/ReadmeInstall_lua.ts +19 -3
- package/project/.sdk/src/cmp/lua/ReadmeIntro_lua.ts +38 -1
- package/project/.sdk/src/cmp/lua/ReadmeModel_lua.ts +51 -16
- package/project/.sdk/src/cmp/lua/ReadmeOptions_lua.ts +4 -3
- package/project/.sdk/src/cmp/lua/ReadmeQuick_lua.ts +79 -18
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +25 -20
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +17 -9
- package/project/.sdk/src/cmp/lua/ReadmeTopTest_lua.ts +32 -5
- package/project/.sdk/src/cmp/lua/Test_lua.ts +4 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityCreateOp.fragment.lua +4 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityListOp.fragment.lua +4 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityLoadOp.fragment.lua +4 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityRemoveOp.fragment.lua +4 -0
- package/project/.sdk/src/cmp/lua/fragment/EntityUpdateOp.fragment.lua +4 -0
- package/project/.sdk/src/cmp/php/EntityTypes_php.ts +142 -0
- package/project/.sdk/src/cmp/php/MainEntity_php.ts +18 -1
- package/project/.sdk/src/cmp/php/Main_php.ts +4 -0
- package/project/.sdk/src/cmp/php/Package_php.ts +18 -7
- package/project/.sdk/src/cmp/php/ReadmeEntity_php.ts +15 -11
- package/project/.sdk/src/cmp/php/ReadmeExamplesTest_php.ts +401 -0
- package/project/.sdk/src/cmp/php/ReadmeHowto_php.ts +56 -13
- package/project/.sdk/src/cmp/php/ReadmeInstall_php.ts +15 -3
- package/project/.sdk/src/cmp/php/ReadmeIntro_php.ts +40 -1
- package/project/.sdk/src/cmp/php/ReadmeModel_php.ts +26 -8
- package/project/.sdk/src/cmp/php/ReadmeOptions_php.ts +4 -3
- package/project/.sdk/src/cmp/php/ReadmeQuick_php.ts +80 -22
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +51 -42
- package/project/.sdk/src/cmp/php/ReadmeTopHowto_php.ts +1 -1
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +19 -11
- package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +41 -11
- package/project/.sdk/src/cmp/php/TestDirect_php.ts +9 -9
- package/project/.sdk/src/cmp/php/TestEntity_php.ts +6 -12
- package/project/.sdk/src/cmp/php/Test_php.ts +4 -0
- package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +13 -1
- package/project/.sdk/src/cmp/php/fragment/EntityCreateOp.fragment.php +10 -1
- package/project/.sdk/src/cmp/php/fragment/EntityListOp.fragment.php +10 -1
- package/project/.sdk/src/cmp/php/fragment/EntityLoadOp.fragment.php +10 -1
- package/project/.sdk/src/cmp/php/fragment/EntityRemoveOp.fragment.php +10 -1
- package/project/.sdk/src/cmp/php/fragment/EntityUpdateOp.fragment.php +10 -1
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +22 -14
- package/project/.sdk/src/cmp/py/EntityTypes_py.ts +184 -0
- package/project/.sdk/src/cmp/py/Entity_py.ts +27 -0
- package/project/.sdk/src/cmp/py/MainEntity_py.ts +2 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +35 -0
- package/project/.sdk/src/cmp/py/Package_py.ts +24 -3
- package/project/.sdk/src/cmp/py/ReadmeEntity_py.ts +27 -11
- package/project/.sdk/src/cmp/py/ReadmeExamplesTest_py.ts +626 -0
- package/project/.sdk/src/cmp/py/ReadmeHowto_py.ts +53 -14
- package/project/.sdk/src/cmp/py/ReadmeInstall_py.ts +19 -3
- package/project/.sdk/src/cmp/py/ReadmeIntro_py.ts +48 -1
- package/project/.sdk/src/cmp/py/ReadmeModel_py.ts +28 -10
- package/project/.sdk/src/cmp/py/ReadmeOptions_py.ts +4 -3
- package/project/.sdk/src/cmp/py/ReadmeQuick_py.ts +73 -24
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +57 -37
- package/project/.sdk/src/cmp/py/ReadmeTopHowto_py.ts +1 -1
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +19 -11
- package/project/.sdk/src/cmp/py/ReadmeTopTest_py.ts +30 -5
- package/project/.sdk/src/cmp/py/TestDirect_py.ts +7 -9
- package/project/.sdk/src/cmp/py/TestEntity_py.ts +6 -14
- package/project/.sdk/src/cmp/py/Test_py.ts +4 -0
- package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +5 -2
- package/project/.sdk/src/cmp/py/fragment/EntityCreateOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/EntityListOp.fragment.py +5 -1
- package/project/.sdk/src/cmp/py/fragment/EntityLoadOp.fragment.py +6 -1
- package/project/.sdk/src/cmp/py/fragment/EntityRemoveOp.fragment.py +6 -1
- package/project/.sdk/src/cmp/py/fragment/EntityUpdateOp.fragment.py +1 -1
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +17 -10
- package/project/.sdk/src/cmp/rb/EntityTypes_rb.ts +136 -0
- package/project/.sdk/src/cmp/rb/MainEntity_rb.ts +1 -0
- package/project/.sdk/src/cmp/rb/Main_rb.ts +4 -0
- package/project/.sdk/src/cmp/rb/Package_rb.ts +34 -7
- package/project/.sdk/src/cmp/rb/ReadmeEntity_rb.ts +26 -10
- package/project/.sdk/src/cmp/rb/ReadmeExamplesTest_rb.ts +289 -0
- package/project/.sdk/src/cmp/rb/ReadmeHowto_rb.ts +72 -21
- package/project/.sdk/src/cmp/rb/ReadmeInstall_rb.ts +16 -4
- package/project/.sdk/src/cmp/rb/ReadmeIntro_rb.ts +40 -1
- package/project/.sdk/src/cmp/rb/ReadmeModel_rb.ts +29 -12
- package/project/.sdk/src/cmp/rb/ReadmeOptions_rb.ts +4 -3
- package/project/.sdk/src/cmp/rb/ReadmeQuick_rb.ts +85 -22
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +56 -37
- package/project/.sdk/src/cmp/rb/ReadmeTopHowto_rb.ts +1 -1
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +19 -11
- package/project/.sdk/src/cmp/rb/ReadmeTopTest_rb.ts +43 -11
- package/project/.sdk/src/cmp/rb/TestDirect_rb.ts +9 -9
- package/project/.sdk/src/cmp/rb/TestEntity_rb.ts +6 -12
- package/project/.sdk/src/cmp/rb/Test_rb.ts +4 -0
- package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +2 -0
- package/project/.sdk/src/cmp/rb/fragment/EntityCreateOp.fragment.rb +5 -0
- package/project/.sdk/src/cmp/rb/fragment/EntityListOp.fragment.rb +20 -2
- package/project/.sdk/src/cmp/rb/fragment/EntityLoadOp.fragment.rb +8 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityRemoveOp.fragment.rb +6 -1
- package/project/.sdk/src/cmp/rb/fragment/EntityUpdateOp.fragment.rb +5 -0
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +24 -8
- package/project/.sdk/src/cmp/ts/EntityTypes_ts.ts +105 -0
- package/project/.sdk/src/cmp/ts/Entity_ts.ts +17 -1
- package/project/.sdk/src/cmp/ts/MainEntity_ts.ts +1 -0
- package/project/.sdk/src/cmp/ts/Main_ts.ts +6 -0
- package/project/.sdk/src/cmp/ts/Package_ts.ts +14 -7
- package/project/.sdk/src/cmp/ts/ReadmeEntity_ts.ts +13 -7
- package/project/.sdk/src/cmp/ts/ReadmeExampleTest_ts.ts +81 -0
- package/project/.sdk/src/cmp/ts/ReadmeExamplesTest_ts.ts +446 -0
- package/project/.sdk/src/cmp/ts/ReadmeExplanation_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/ReadmeHowto_ts.ts +57 -11
- package/project/.sdk/src/cmp/ts/ReadmeInstall_ts.ts +19 -6
- package/project/.sdk/src/cmp/ts/ReadmeIntro_ts.ts +39 -1
- package/project/.sdk/src/cmp/ts/ReadmeModel_ts.ts +50 -18
- package/project/.sdk/src/cmp/ts/ReadmeOptions_ts.ts +4 -3
- package/project/.sdk/src/cmp/ts/ReadmeQuick_ts.ts +95 -40
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +24 -13
- package/project/.sdk/src/cmp/ts/ReadmeTopHowto_ts.ts +3 -0
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +44 -12
- package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +23 -3
- package/project/.sdk/src/cmp/ts/TestEntity_ts.ts +2 -2
- package/project/.sdk/src/cmp/ts/Test_ts.ts +5 -0
- package/project/.sdk/src/cmp/ts/fragment/Entity.fragment.ts +3 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +10 -5
- package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +4 -2
- package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +4 -2
- package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +4 -2
- package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +4 -2
- package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +4 -2
- package/project/.sdk/src/cmp/ts/utility_ts.ts +59 -0
- package/project/.sdk/tm/go/LICENSE +1 -1
- package/project/.sdk/tm/go/Makefile +36 -1
- package/project/.sdk/tm/go/VERSION +1 -0
- package/project/.sdk/tm/go/core/context.go +12 -7
- package/project/.sdk/tm/go-cli/src/feature/README.md +6 -0
- package/project/.sdk/tm/go-cli/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/go-cli/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/go-cli/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/go-mcp/src/feature/README.md +6 -0
- package/project/.sdk/tm/go-mcp/src/feature/base/.gitkeep +0 -0
- package/project/.sdk/tm/go-mcp/src/feature/log/.gitkeep +0 -0
- package/project/.sdk/tm/go-mcp/src/feature/test/.gitkeep +0 -0
- package/project/.sdk/tm/js/LICENSE +1 -1
- package/project/.sdk/tm/js/Makefile +41 -0
- package/project/.sdk/tm/lua/LICENSE +1 -1
- package/project/.sdk/tm/lua/Makefile +40 -1
- package/project/.sdk/tm/lua/core/context.lua +13 -8
- package/project/.sdk/tm/php/LICENSE +1 -1
- package/project/.sdk/tm/php/Makefile +31 -1
- package/project/.sdk/tm/php/VERSION +1 -0
- package/project/.sdk/tm/php/core/Context.php +12 -6
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +13 -4
- package/project/.sdk/tm/php/utility/Done.php +2 -2
- package/project/.sdk/tm/php/utility/MakeError.php +3 -3
- package/project/.sdk/tm/py/LICENSE +1 -1
- package/project/.sdk/tm/py/Makefile +34 -1
- package/project/.sdk/tm/py/core/context.py +12 -7
- package/project/.sdk/tm/py/test/test_primary_utility.py +15 -4
- package/project/.sdk/tm/py/utility/done.py +3 -1
- package/project/.sdk/tm/py/utility/make_error.py +2 -2
- package/project/.sdk/tm/rb/LICENSE +1 -1
- package/project/.sdk/tm/rb/Makefile +33 -1
- package/project/.sdk/tm/rb/core/context.rb +8 -3
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +2 -2
- package/project/.sdk/tm/rb/utility/done.rb +3 -1
- package/project/.sdk/tm/rb/utility/make_error.rb +5 -2
- package/project/.sdk/tm/ts/LICENSE +1 -1
- package/project/.sdk/tm/ts/Makefile +42 -0
- package/project/.sdk/tm/ts/src/Context.ts +8 -3
- package/src/action/action.ts +17 -10
- package/src/action/feature.ts +8 -6
- package/src/action/target.ts +17 -8
- package/src/cmp/Changelog.ts +34 -0
- package/src/cmp/Deploy.ts +258 -0
- package/src/cmp/FeatureHook.ts +6 -8
- package/src/cmp/License.ts +49 -0
- package/src/cmp/Readme.ts +2 -0
- package/src/cmp/ReadmeErrors.ts +257 -0
- package/src/cmp/ReadmeExplanation.ts +250 -230
- package/src/cmp/ReadmeModel.ts +7 -2
- package/src/cmp/ReadmeTop.ts +411 -95
- package/src/cmp/Security.ts +41 -0
- package/src/helpers/canonType.ts +89 -0
- package/src/helpers/collectDeps.ts +5 -3
- package/src/helpers/naming.ts +59 -0
- package/src/helpers/opExample.ts +170 -0
- package/src/helpers/opShape.ts +236 -0
- package/src/helpers/packageMeta.ts +236 -0
- package/src/sdkgen.ts +87 -20
- package/src/tsconfig.json +1 -0
- package/src/types.ts +85 -2
- package/src/utility.ts +22 -11
- package/README.md +0 -2
- package/dist/action/lang.d.ts +0 -2
- package/dist/action/lang.js +0 -68
- package/dist/action/lang.js.map +0 -1
- package/dist/cmp/Hook.d.ts +0 -2
- package/dist/cmp/Hook.js +0 -10
- package/dist/cmp/Hook.js.map +0 -1
- package/dist/cmp/Top.d.ts +0 -2
- package/dist/cmp/Top.js +0 -23
- package/dist/cmp/Top.js.map +0 -1
- package/dist/prepare-openapi.d.ts +0 -2
- package/dist/prepare-openapi.js +0 -37
- package/dist/prepare-openapi.js.map +0 -1
- package/model/sdkgen.jsonic +0 -74
- package/project/.sdk/tm/go/utility/struct/go.mod +0 -3
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Canonical type-sentinel -> language primitive type mapper.
|
|
2
|
+
//
|
|
3
|
+
// SOURCE OF TRUTH for the sentinel set: @voxgig/apidef
|
|
4
|
+
// ~/Projects/voxgig/apidef ts/src/utility.ts -> `const VALID_CANON`
|
|
5
|
+
// (around line 908). VALID_CANON maps an OpenAPI type NAME -> a `$SENTINEL`
|
|
6
|
+
// string (e.g. 'string' -> `$STRING`). The model stores those sentinels on
|
|
7
|
+
// every `fields[].type` and op `points[].args.params[].type`.
|
|
8
|
+
//
|
|
9
|
+
// This table maps the SENTINEL the other way -> a concrete primitive type in
|
|
10
|
+
// each target language, so the typed-model generators (EntityTypes_<lang>.ts)
|
|
11
|
+
// can turn the model's field/param sentinels into real language types.
|
|
12
|
+
//
|
|
13
|
+
// Kept as a small duplicate here (rather than importing VALID_CANON) because
|
|
14
|
+
// VALID_CANON is name->sentinel, is not exported from @voxgig/apidef, and would
|
|
15
|
+
// need inverting; a sentinel->type table is what every language generator
|
|
16
|
+
// actually needs. If VALID_CANON gains a new sentinel, add a row below (all
|
|
17
|
+
// languages) and keep the two in sync.
|
|
18
|
+
//
|
|
19
|
+
// KNOWN GAPS (papered over sanely, documented for the port):
|
|
20
|
+
// - Unknown / missing sentinel -> the language's "any" (never throws).
|
|
21
|
+
// - Array element typing is not in the model: $ARRAY maps to an untyped
|
|
22
|
+
// list/array. `list` ops return T[] via op-kind inference in the op
|
|
23
|
+
// fragment, NOT via a field sentinel.
|
|
24
|
+
// - Object/nested field schemas are not in the corpus: $OBJECT maps to the
|
|
25
|
+
// language's open record/map type.
|
|
26
|
+
// - No enum/format/nullability beyond the `req` flag.
|
|
27
|
+
|
|
28
|
+
// Target languages sdkgen supports (go-cli / go-mcp reuse 'go').
|
|
29
|
+
type CanonLang = 'ts' | 'js' | 'py' | 'php' | 'rb' | 'lua' | 'go'
|
|
30
|
+
|
|
31
|
+
// Bare sentinel key (backticks + leading `$` stripped, upper-cased)
|
|
32
|
+
// -> per-language primitive type name.
|
|
33
|
+
//
|
|
34
|
+
// ONLY the `ts` column is exercised + tested today (the reference target).
|
|
35
|
+
// The other columns are a starting scaffold for the per-language port; verify
|
|
36
|
+
// each against that language's idioms before wiring its EntityTypes_<lang>.ts.
|
|
37
|
+
const CANON_TYPE: Record<string, Record<CanonLang, string>> = {
|
|
38
|
+
STRING: { ts: 'string', js: 'string', py: 'str', php: 'string', rb: 'String', lua: 'string', go: 'string' },
|
|
39
|
+
INTEGER: { ts: 'number', js: 'number', py: 'int', php: 'int', rb: 'Integer', lua: 'number', go: 'int' },
|
|
40
|
+
NUMBER: { ts: 'number', js: 'number', py: 'float', php: 'float', rb: 'Float', lua: 'number', go: 'float64' },
|
|
41
|
+
BOOLEAN: { ts: 'boolean', js: 'boolean', py: 'bool', php: 'bool', rb: 'Boolean', lua: 'boolean', go: 'bool' },
|
|
42
|
+
NULL: { ts: 'null', js: 'null', py: 'None', php: 'null', rb: 'NilClass', lua: 'nil', go: 'any' },
|
|
43
|
+
ARRAY: { ts: 'any[]', js: 'Array', py: 'list', php: 'array', rb: 'Array', lua: 'table', go: '[]any' },
|
|
44
|
+
OBJECT: { ts: 'Record<string, any>', js: 'Object', py: 'dict', php: 'array', rb: 'Hash', lua: 'table', go: 'map[string]any' },
|
|
45
|
+
ANY: { ts: 'any', js: '*', py: 'Any', php: 'mixed', rb: 'Object', lua: 'any', go: 'any' },
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Per-language fallback for unknown / missing sentinels.
|
|
49
|
+
// js uses JSDoc's `*` (any type); lua uses `any` (LuaLS).
|
|
50
|
+
const CANON_ANY: Record<CanonLang, string> = {
|
|
51
|
+
ts: 'any', js: '*', py: 'Any', php: 'mixed', rb: 'Object', lua: 'any', go: 'any',
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
// Normalize a raw sentinel value to its bare upper-case key:
|
|
56
|
+
// '`$STRING`' / '$STRING' / 'string' -> 'STRING'.
|
|
57
|
+
function canonKey(sentinel: unknown): string {
|
|
58
|
+
if (null == sentinel) {
|
|
59
|
+
return ''
|
|
60
|
+
}
|
|
61
|
+
return String(sentinel).replace(/[`$]/g, '').trim().toUpperCase()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// Map a field/param type sentinel to a target-language primitive type.
|
|
66
|
+
// Unknown or missing sentinel -> that language's "any" (never throws).
|
|
67
|
+
function canonToType(sentinel: unknown, lang: string): string {
|
|
68
|
+
const l = lang as CanonLang
|
|
69
|
+
const fallback = CANON_ANY[l] ?? 'any'
|
|
70
|
+
|
|
71
|
+
const row = CANON_TYPE[canonKey(sentinel)]
|
|
72
|
+
if (null == row) {
|
|
73
|
+
return fallback
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return row[l] ?? fallback
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
canonToType,
|
|
82
|
+
canonKey,
|
|
83
|
+
CANON_TYPE,
|
|
84
|
+
CANON_ANY,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type {
|
|
88
|
+
CanonLang,
|
|
89
|
+
}
|
|
@@ -14,17 +14,19 @@
|
|
|
14
14
|
import { each } from 'jostraca'
|
|
15
15
|
import { KIT, getModelPath } from '@voxgig/apidef'
|
|
16
16
|
|
|
17
|
+
import type { SdkModel, ModelDep } from '../types'
|
|
18
|
+
|
|
17
19
|
type DepEntry = {
|
|
18
20
|
name: string
|
|
19
21
|
version: string
|
|
20
22
|
source: 'feature' | 'target'
|
|
21
|
-
raw:
|
|
23
|
+
raw: ModelDep
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
function collectDeps(
|
|
25
|
-
model:
|
|
27
|
+
model: SdkModel,
|
|
26
28
|
targetName: string,
|
|
27
|
-
targetDeps:
|
|
29
|
+
targetDeps: Record<string, ModelDep> | undefined,
|
|
28
30
|
): DepEntry[] {
|
|
29
31
|
const out: DepEntry[] = []
|
|
30
32
|
const feature = getModelPath(model, `main.${KIT}.feature`)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Reserved-word sanitiser for generated doc-example variable names.
|
|
2
|
+
//
|
|
3
|
+
// A doc example binds a variable named after the lowercased entity name
|
|
4
|
+
// (e.g. `const delete = await client.Delete().load()`). When that name is a
|
|
5
|
+
// reserved word in the target language the snippet does not compile
|
|
6
|
+
// (TS1109/TS1389 for `delete`). `safeVarName` appends `_` to any reserved
|
|
7
|
+
// name so the example still reads clearly and compiles.
|
|
8
|
+
//
|
|
9
|
+
// Only languages whose build/vet actually rejects the name are listed. JS and
|
|
10
|
+
// TS share the ECMAScript reserved set (plus the strict-mode / contextual
|
|
11
|
+
// words a `const` binding trips on). Go lists its 25 keywords — a var named
|
|
12
|
+
// `type`/`func`/`range` fails `go build`; Go builtins like `delete`/`len` are
|
|
13
|
+
// NOT keywords and are legal identifiers, so they are intentionally omitted.
|
|
14
|
+
// py/php/rb/lua rarely collide on a lowercased entity name and are not treated
|
|
15
|
+
// here (add a set if a real collision surfaces).
|
|
16
|
+
|
|
17
|
+
const JS_RESERVED = new Set<string>([
|
|
18
|
+
'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
|
19
|
+
'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'false',
|
|
20
|
+
'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new',
|
|
21
|
+
'null', 'return', 'super', 'switch', 'this', 'throw', 'true', 'try',
|
|
22
|
+
'typeof', 'var', 'void', 'while', 'with', 'yield',
|
|
23
|
+
// strict-mode / contextual words that are invalid as a `const`/`let` binding
|
|
24
|
+
'await', 'implements', 'interface', 'let', 'package', 'private',
|
|
25
|
+
'protected', 'public', 'static',
|
|
26
|
+
])
|
|
27
|
+
|
|
28
|
+
const GO_RESERVED = new Set<string>([
|
|
29
|
+
'break', 'case', 'chan', 'const', 'continue', 'default', 'defer', 'else',
|
|
30
|
+
'fallthrough', 'for', 'func', 'go', 'goto', 'if', 'import', 'interface',
|
|
31
|
+
'map', 'package', 'range', 'return', 'select', 'struct', 'switch', 'type',
|
|
32
|
+
'var',
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
const RESERVED: Record<string, Set<string>> = {
|
|
36
|
+
ts: JS_RESERVED,
|
|
37
|
+
js: JS_RESERVED,
|
|
38
|
+
go: GO_RESERVED,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
// Is `name` a reserved word (an illegal identifier) in the target language?
|
|
43
|
+
function isReservedName(name: string, lang: string): boolean {
|
|
44
|
+
const set = RESERVED[lang]
|
|
45
|
+
return !!set && set.has(name)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
// A collision-free variable name for the target language: the name unchanged
|
|
50
|
+
// unless it is reserved, in which case a trailing `_` is appended.
|
|
51
|
+
function safeVarName(name: string, lang: string): string {
|
|
52
|
+
return isReservedName(name, lang) ? name + '_' : name
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
isReservedName,
|
|
58
|
+
safeVarName,
|
|
59
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// Renders a single, type-correct entity-op CALL for the neutral doc
|
|
2
|
+
// components (ReadmeErrors, ReadmeExplanation) that illustrate a convention
|
|
3
|
+
// (throw-on-error, stateful entities) with one representative operation.
|
|
4
|
+
//
|
|
5
|
+
// Two model traps this centralises:
|
|
6
|
+
// 1. OP-AWARENESS — the illustrated op must be one the entity actually
|
|
7
|
+
// exposes. A create-only entity has no `load` method, so these components
|
|
8
|
+
// pick the entity's PRIMARY op (entityPrimaryOp) rather than hardcoding
|
|
9
|
+
// `load`, and this module renders whatever op that is.
|
|
10
|
+
// 2. TYPE-CORRECT MATCH ID — an entity can carry its id ONLY in the
|
|
11
|
+
// load-match params (no `id` data field). The example id literal is
|
|
12
|
+
// therefore derived from the OP's param type (opRequestShape), not the
|
|
13
|
+
// entity fields, so a numeric match id renders `1` and not `"example_id"`
|
|
14
|
+
// (which would be a TS2322 against a `number` match).
|
|
15
|
+
//
|
|
16
|
+
// Output is the invocation EXPRESSION and its result binding; the surrounding
|
|
17
|
+
// prose / try-catch scaffolding stays in each component's per-language table.
|
|
18
|
+
|
|
19
|
+
import { each } from 'jostraca'
|
|
20
|
+
import { canonKey } from './canonType'
|
|
21
|
+
import { opRequestShape, entityIdField } from './opShape'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
type ExampleLang = 'ts' | 'js' | 'py' | 'php' | 'rb' | 'lua' | 'go'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
function cap(s: string): string {
|
|
28
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// A type-correct literal for a canonical type sentinel, in the target language.
|
|
33
|
+
function litFor(lang: ExampleLang, type: any): string {
|
|
34
|
+
const k = canonKey(type)
|
|
35
|
+
if ('INTEGER' === k || 'NUMBER' === k) return '1'
|
|
36
|
+
if ('BOOLEAN' === k) return 'py' === lang ? 'True' : ('rb' === lang ? 'true' : 'true')
|
|
37
|
+
if ('ARRAY' === k) return ('lua' === lang) ? '{}' : ('go' === lang ? '[]any{}' : '[]')
|
|
38
|
+
if ('OBJECT' === k) return ('go' === lang) ? 'map[string]any{}' : '{}'
|
|
39
|
+
return '"example"'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// The example id literal for an op's match key, typed from the op's declared
|
|
44
|
+
// param (falling back to the entity field) so a numeric id is never quoted.
|
|
45
|
+
function idLiteral(ent: any, op: string, idF: string | null): string {
|
|
46
|
+
if (null == idF) return '"example_id"'
|
|
47
|
+
const item = opRequestShape(ent, op).items.find((it: any) => it.name === idF)
|
|
48
|
+
const k = canonKey(item && item.type)
|
|
49
|
+
return ('INTEGER' === k || 'NUMBER' === k) ? '1' : '"example_id"'
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
// Render a match object `{ idF: idLit }` (or empty when the entity has no id
|
|
54
|
+
// key) in the target language's object syntax.
|
|
55
|
+
function matchArg(lang: ExampleLang, idF: string | null, idLit: string): string {
|
|
56
|
+
if (null == idF) return 'go' === lang ? 'nil' : ''
|
|
57
|
+
switch (lang) {
|
|
58
|
+
case 'py': return `{"${idF}": ${idLit}}`
|
|
59
|
+
case 'php': return `["${idF}" => ${idLit}]`
|
|
60
|
+
case 'rb': return `{ "${idF}" => ${idLit} }`
|
|
61
|
+
case 'lua': return `{ ${idF} = ${idLit} }`
|
|
62
|
+
case 'go': return `map[string]any{"${idF}": ${idLit}}`
|
|
63
|
+
default: return `{ ${idF}: ${idLit} }`
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// The entity's required writable fields for a create/update body, rendered as
|
|
69
|
+
// `key: value` pairs (capped) in the target language's object syntax. Ensures
|
|
70
|
+
// the body satisfies a typed CreateData/UpdateData (required fields present).
|
|
71
|
+
function dataArg(lang: ExampleLang, ent: any, op: string, idF: string | null): string {
|
|
72
|
+
const items = opRequestShape(ent, op).items
|
|
73
|
+
.filter((it: any) => it.name !== idF && it.name !== 'id')
|
|
74
|
+
const required = items.filter((it: any) => !it.optional)
|
|
75
|
+
// ALL required fields must appear (a typed CreateData rejects a partial); cap
|
|
76
|
+
// only the optional fallback used when the op declares no required field.
|
|
77
|
+
const chosen = required.length ? required : items.slice(0, 3)
|
|
78
|
+
const pairs = chosen.map((it: any) => {
|
|
79
|
+
const v = litFor(lang, it.type)
|
|
80
|
+
switch (lang) {
|
|
81
|
+
case 'py': return `"${it.name}": ${v}`
|
|
82
|
+
case 'php': return `"${it.name}" => ${v}`
|
|
83
|
+
case 'rb': return `"${it.name}" => ${v}`
|
|
84
|
+
case 'lua': return `${it.name} = ${v}`
|
|
85
|
+
case 'go': return `"${it.name}": ${v}`
|
|
86
|
+
default: return `${it.name}: ${v}`
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
switch (lang) {
|
|
90
|
+
case 'php': return `[${pairs.join(', ')}]`
|
|
91
|
+
case 'lua': return `{ ${pairs.join(', ')} }`
|
|
92
|
+
case 'go': return `map[string]any{${pairs.join(', ')}}`
|
|
93
|
+
default: return `{ ${pairs.join(', ')} }`
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
type PrimaryCall = {
|
|
99
|
+
// The full invocation expression, e.g. `client.Advice().load({ id: 1 })`
|
|
100
|
+
// (ts) or `client.Generate(nil).Create(map[string]any{...}, nil)` (go).
|
|
101
|
+
expr: string
|
|
102
|
+
// The natural result-variable name (`advice`, `advices`, `generate`).
|
|
103
|
+
resultVar: string
|
|
104
|
+
// True when the op returns no value (remove) — callers that print the
|
|
105
|
+
// result should skip it.
|
|
106
|
+
isVoid: boolean
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// Render the entity's PRIMARY-op invocation in `lang`. `eName` is the
|
|
111
|
+
// Capitalised entity name, `eLower` the variable-safe lowercase name, `op` the
|
|
112
|
+
// primary op name. Method spelling / factory syntax follow each language's
|
|
113
|
+
// idiom (Go PascalCase + ctrl arg, Lua `:` calls, Ruby paren-less factory).
|
|
114
|
+
function primaryOpCall(
|
|
115
|
+
lang: ExampleLang,
|
|
116
|
+
eName: string,
|
|
117
|
+
eLower: string,
|
|
118
|
+
op: string,
|
|
119
|
+
idF: string | null,
|
|
120
|
+
ent: any,
|
|
121
|
+
): PrimaryCall {
|
|
122
|
+
const isMatch = 'load' === op || 'remove' === op
|
|
123
|
+
const isList = 'list' === op
|
|
124
|
+
const isData = 'create' === op || 'update' === op
|
|
125
|
+
const idLit = idLiteral(ent, op, idF)
|
|
126
|
+
|
|
127
|
+
// Factory + method spelling per language.
|
|
128
|
+
const method = 'go' === lang ? cap(op) : op
|
|
129
|
+
let factory: string
|
|
130
|
+
let sep: string
|
|
131
|
+
if ('go' === lang) { factory = `client.${eName}(nil)`; sep = '.' }
|
|
132
|
+
else if ('lua' === lang) { factory = `client:${eName}()`; sep = ':' }
|
|
133
|
+
else if ('rb' === lang) { factory = `client.${eName}`; sep = '.' }
|
|
134
|
+
else if ('php' === lang) { factory = `$client->${eName}()`; sep = '->' }
|
|
135
|
+
else { factory = `client.${eName}()`; sep = '.' }
|
|
136
|
+
|
|
137
|
+
// Argument string per op + language.
|
|
138
|
+
let arg: string
|
|
139
|
+
if (isList) {
|
|
140
|
+
arg = 'go' === lang ? 'nil' : ''
|
|
141
|
+
} else if (isMatch) {
|
|
142
|
+
arg = matchArg(lang, idF, idLit)
|
|
143
|
+
} else if (isData) {
|
|
144
|
+
arg = dataArg(lang, ent, op, idF)
|
|
145
|
+
} else {
|
|
146
|
+
arg = 'go' === lang ? 'nil' : ''
|
|
147
|
+
}
|
|
148
|
+
// Go passes a trailing ctrl arg on every entity method.
|
|
149
|
+
if ('go' === lang) {
|
|
150
|
+
arg = arg + ', nil'
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const expr = `${factory}${sep}${method}(${arg})`
|
|
154
|
+
const resultVar = isList ? eLower + 's' : eLower
|
|
155
|
+
return { expr, resultVar, isVoid: 'remove' === op }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
export {
|
|
160
|
+
primaryOpCall,
|
|
161
|
+
idLiteral,
|
|
162
|
+
matchArg,
|
|
163
|
+
dataArg,
|
|
164
|
+
litFor,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export type {
|
|
168
|
+
ExampleLang,
|
|
169
|
+
PrimaryCall,
|
|
170
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// Per-op request-payload shape + partiality policy for the typed-model
|
|
2
|
+
// generators (EntityTypes_<lang>.ts).
|
|
3
|
+
//
|
|
4
|
+
// SINGLE SOURCE OF TRUTH for two things every language generator needs:
|
|
5
|
+
// 1. The type-name scheme: <Name>{Load,List,Remove}Match /
|
|
6
|
+
// <Name>{Create,Update}Data (OP_SUFFIX + opTypeName).
|
|
7
|
+
// 2. Which fields make up an op's request payload, and whether each is
|
|
8
|
+
// required or optional (opRequestShape) — i.e. the partiality policy.
|
|
9
|
+
//
|
|
10
|
+
// PARTIALITY POLICY
|
|
11
|
+
// Op-declared params win: if the op declares params
|
|
12
|
+
// (op.<name>.points[].args.params[]), the payload is built from them and a
|
|
13
|
+
// param is optional iff `reqd === false` (this is how path/query params such
|
|
14
|
+
// as {id} become required). `fromParams` is true in that case.
|
|
15
|
+
//
|
|
16
|
+
// Otherwise the payload mirrors the entity's fields, filtered to those active
|
|
17
|
+
// for the op (field.op[opname].active !== false; absent -> participates), and
|
|
18
|
+
// optionality is decided per-op:
|
|
19
|
+
// create -> required iff `field.req` (server-shaped required fields);
|
|
20
|
+
// update -> all optional (patch);
|
|
21
|
+
// load / remove -> a field named `id` is required, the rest optional
|
|
22
|
+
// (best-effort key convention; degrades to all-optional if no `id`);
|
|
23
|
+
// list -> all optional (filter).
|
|
24
|
+
//
|
|
25
|
+
// The generators consume `items` (each already carrying its final `optional`
|
|
26
|
+
// flag) and render them in the target language's struct/interface/TypedDict
|
|
27
|
+
// syntax; the policy itself is language-neutral and tested in isolation.
|
|
28
|
+
|
|
29
|
+
import { each } from 'jostraca'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// The five ops, and whether their request payload is a `Match` (query/id) or
|
|
33
|
+
// `Data` (body) — this fixes the generated type-name suffix per op.
|
|
34
|
+
const OP_SUFFIX: Record<string, 'Match' | 'Data'> = {
|
|
35
|
+
load: 'Match',
|
|
36
|
+
list: 'Match',
|
|
37
|
+
remove: 'Match',
|
|
38
|
+
create: 'Data',
|
|
39
|
+
update: 'Data',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
function cap(s: string): string {
|
|
44
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// The generated type name for an op's request payload, e.g. AdviceLoadMatch.
|
|
49
|
+
function opTypeName(Name: string, opname: string): string {
|
|
50
|
+
return Name + cap(opname) + (OP_SUFFIX[opname] || 'Match')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// One request-payload member: a model field or op param, with the final
|
|
55
|
+
// required/optional decision already applied per the partiality policy.
|
|
56
|
+
type OpShapeItem = {
|
|
57
|
+
name: string
|
|
58
|
+
type: any // canonical type sentinel (e.g. `$STRING`); render via canonToType
|
|
59
|
+
optional: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
// Collect an op's params, deduped by name across all of its points.
|
|
64
|
+
function opParams(op: any): any[] {
|
|
65
|
+
const points = op && op.points ? each(op.points) : []
|
|
66
|
+
const seen: Record<string, boolean> = {}
|
|
67
|
+
const out: any[] = []
|
|
68
|
+
points.forEach((pt: any) => {
|
|
69
|
+
const params = pt && pt.args && pt.args.params ? each(pt.args.params) : []
|
|
70
|
+
params.forEach((p: any) => {
|
|
71
|
+
if (p && null != p.name && !seen[p.name]) {
|
|
72
|
+
seen[p.name] = true
|
|
73
|
+
out.push(p)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
return out
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
// Does a field participate in an op? Absent op-entry -> participates; only an
|
|
82
|
+
// explicit `active: false` excludes it.
|
|
83
|
+
function fieldInOp(field: any, opname: string): boolean {
|
|
84
|
+
const fop = field && field.op && field.op[opname]
|
|
85
|
+
return null == fop || fop.active !== false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
// Decide optionality for a field in a no-params request payload, per op.
|
|
90
|
+
function fieldOptional(field: any, opname: string): boolean {
|
|
91
|
+
switch (opname) {
|
|
92
|
+
case 'create':
|
|
93
|
+
// Respect the model's required flag: required unless req === false.
|
|
94
|
+
return false === field.req
|
|
95
|
+
case 'update':
|
|
96
|
+
// Patch semantics — every field optional.
|
|
97
|
+
return true
|
|
98
|
+
case 'load':
|
|
99
|
+
case 'remove':
|
|
100
|
+
// Best-effort key convention: the `id` field is required, rest optional.
|
|
101
|
+
return 'id' !== field.name
|
|
102
|
+
case 'list':
|
|
103
|
+
default:
|
|
104
|
+
// Filter — every field optional.
|
|
105
|
+
return true
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
// The ordered request-payload members for an entity op, with each member's
|
|
111
|
+
// required/optional decision baked in. `fromParams` records whether the op's
|
|
112
|
+
// declared params were used (true) or the entity-field fallback (false).
|
|
113
|
+
function opRequestShape(ent: any, opname: string):
|
|
114
|
+
{ items: OpShapeItem[], fromParams: boolean } {
|
|
115
|
+
|
|
116
|
+
const op = ent && ent.op ? ent.op[opname] : null
|
|
117
|
+
if (null == op) {
|
|
118
|
+
return { items: [], fromParams: false }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const params = opParams(op)
|
|
122
|
+
if (0 < params.length) {
|
|
123
|
+
const items = params.map((p: any) => ({
|
|
124
|
+
name: p.name,
|
|
125
|
+
type: p.type,
|
|
126
|
+
optional: false === p.reqd,
|
|
127
|
+
}))
|
|
128
|
+
return { items, fromParams: true }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const fields = (ent.fields ? each(ent.fields) : [])
|
|
132
|
+
.filter((f: any) => f.active !== false)
|
|
133
|
+
.filter((f: any) => fieldInOp(f, opname))
|
|
134
|
+
|
|
135
|
+
const items = fields.map((f: any) => ({
|
|
136
|
+
name: f.name,
|
|
137
|
+
type: f.type,
|
|
138
|
+
optional: fieldOptional(f, opname),
|
|
139
|
+
}))
|
|
140
|
+
|
|
141
|
+
return { items, fromParams: false }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
// The entity's id-like key field, or null when it has none. Used by the doc
|
|
146
|
+
// generators to decide whether an example may key a load/remove on `{ id: ... }`
|
|
147
|
+
// and access `.id` on a returned entity, OR must degrade to `load()` with no
|
|
148
|
+
// argument (some APIs model an entity whose load match carries no id — e.g. a
|
|
149
|
+
// response-wrapped spec, where AqiLoadMatch is { code, data, msg }). Prefers the
|
|
150
|
+
// model's declared id field name, then a literal `id`, checking the load-match
|
|
151
|
+
// shape first and the entity's own fields as a fallback.
|
|
152
|
+
function entityIdField(ent: any): string | null {
|
|
153
|
+
if (null == ent) {
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
156
|
+
const idName = (ent.id && ent.id.field) || 'id'
|
|
157
|
+
const loadItems = opRequestShape(ent, 'load').items
|
|
158
|
+
if (loadItems.some((it: OpShapeItem) => it.name === idName)) {
|
|
159
|
+
return idName
|
|
160
|
+
}
|
|
161
|
+
if (loadItems.some((it: OpShapeItem) => it.name === 'id')) {
|
|
162
|
+
return 'id'
|
|
163
|
+
}
|
|
164
|
+
// NO fallback to entity.fields: this is the load-MATCH key. An entity whose
|
|
165
|
+
// DATA type has an `id` field but whose load match does NOT (a query-param
|
|
166
|
+
// load, e.g. playstation-store's StoreLoadMatch { age, country, ... }) must
|
|
167
|
+
// degrade to a no-arg load(); `.id` access is decided by entityDataIdField.
|
|
168
|
+
return null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
// The entity's ACTIVE op names, in canonical CRUD order (list, load, create,
|
|
173
|
+
// update, remove), with any non-canonical ops appended in sorted order. Doc
|
|
174
|
+
// generators must gate an op example on this (an op present in the model but
|
|
175
|
+
// `active: false` generates no method, so an example calling it would not
|
|
176
|
+
// compile) — NOT on the raw `Object.keys(ent.op)`, which includes inactive ops.
|
|
177
|
+
const CANON_OP_ORDER = ['list', 'load', 'create', 'update', 'remove']
|
|
178
|
+
|
|
179
|
+
function entityOps(ent: any): string[] {
|
|
180
|
+
const ops = (ent && ent.op) || {}
|
|
181
|
+
const active = Object.keys(ops).filter((o: string) => ops[o] && ops[o].active !== false)
|
|
182
|
+
return CANON_OP_ORDER.filter((o) => active.includes(o))
|
|
183
|
+
.concat(active.filter((o) => !CANON_OP_ORDER.includes(o)).sort())
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
// The entity's primary/representative op for a single illustrative call —
|
|
188
|
+
// prefer a read op (list, then load) so the snippet needs no fabricated match,
|
|
189
|
+
// then fall back to create/update/remove. null when the entity exposes no op.
|
|
190
|
+
// Doc generators MUST pick their "primary" op through this rather than
|
|
191
|
+
// hardcoding `load`: a create-only entity has no `load` method.
|
|
192
|
+
function entityPrimaryOp(ent: any): string | null {
|
|
193
|
+
const ops = entityOps(ent)
|
|
194
|
+
for (const o of CANON_OP_ORDER) {
|
|
195
|
+
if (ops.includes(o)) {
|
|
196
|
+
return o
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return ops[0] || null
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
// The id field on the entity's DATA type (its fields[]), or null. DISTINCT from
|
|
204
|
+
// entityIdField (the load-MATCH key): an API can model a load match that carries
|
|
205
|
+
// an `id` param while the response entity itself has no `id` field, so `.id`
|
|
206
|
+
// access on a RETURNED record must be guarded on this, not on the match key.
|
|
207
|
+
function entityDataIdField(ent: any): string | null {
|
|
208
|
+
if (null == ent) {
|
|
209
|
+
return null
|
|
210
|
+
}
|
|
211
|
+
const idName = (ent.id && ent.id.field) || 'id'
|
|
212
|
+
const fields = ent.fields ? each(ent.fields) : []
|
|
213
|
+
if (fields.some((f: any) => f && f.name === idName)) {
|
|
214
|
+
return idName
|
|
215
|
+
}
|
|
216
|
+
if (fields.some((f: any) => f && f.name === 'id')) {
|
|
217
|
+
return 'id'
|
|
218
|
+
}
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
export {
|
|
224
|
+
OP_SUFFIX,
|
|
225
|
+
opTypeName,
|
|
226
|
+
opParams,
|
|
227
|
+
opRequestShape,
|
|
228
|
+
entityIdField,
|
|
229
|
+
entityDataIdField,
|
|
230
|
+
entityOps,
|
|
231
|
+
entityPrimaryOp,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type {
|
|
235
|
+
OpShapeItem,
|
|
236
|
+
}
|