@voxgig/sdkgen 1.2.1 → 1.3.2
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 +3 -1
- package/dist/action/action.js +26 -10
- package/dist/action/action.js.map +1 -1
- package/dist/action/feature.js +9 -8
- package/dist/action/feature.js.map +1 -1
- package/dist/action/target.d.ts +7 -1
- package/dist/action/target.js +22 -13
- 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 +225 -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 +12 -2
- package/dist/sdkgen.js +60 -20
- 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.d.ts +2 -1
- package/dist/utility.js +39 -11
- package/dist/utility.js.map +1 -1
- package/model/sdkgen.aontu +137 -0
- package/package.json +11 -5
- package/project/.sdk/model/feature/feature-index.aontu +5 -0
- package/project/.sdk/model/target/go-cli.aontu +47 -0
- package/project/.sdk/model/target/go-mcp.aontu +41 -0
- package/project/.sdk/model/target/go.aontu +28 -0
- package/project/.sdk/model/target/{js.jsonic → js.aontu} +13 -0
- package/project/.sdk/model/target/{lua.jsonic → lua.aontu} +13 -0
- package/project/.sdk/model/target/{php.jsonic → php.aontu} +13 -0
- package/project/.sdk/model/target/{py.jsonic → py.aontu} +13 -0
- package/project/.sdk/model/target/{rb.jsonic → rb.aontu} +13 -0
- package/project/.sdk/model/target/{ts.jsonic → ts.aontu} +13 -0
- package/project/.sdk/src/cmp/go/Config_go.ts +3 -2
- 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 +48 -10
- package/project/.sdk/src/cmp/go/ReadmeExamplesTest_go.ts +688 -0
- package/project/.sdk/src/cmp/go/ReadmeExplanation_go.ts +1 -1
- package/project/.sdk/src/cmp/go/ReadmeHowto_go.ts +52 -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 +67 -17
- package/project/.sdk/src/cmp/go/ReadmeOptions_go.ts +4 -3
- package/project/.sdk/src/cmp/go/ReadmeQuick_go.ts +146 -116
- package/project/.sdk/src/cmp/go/ReadmeRef_go.ts +87 -21
- package/project/.sdk/src/cmp/go/ReadmeTopHowto_go.ts +4 -0
- package/project/.sdk/src/cmp/go/ReadmeTopQuick_go.ts +75 -16
- 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/utility_go.ts +70 -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/Config_js.ts +3 -6
- 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 +33 -10
- 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 +70 -20
- package/project/.sdk/src/cmp/js/ReadmeRef_js.ts +50 -16
- package/project/.sdk/src/cmp/js/ReadmeTopHowto_js.ts +3 -0
- package/project/.sdk/src/cmp/js/ReadmeTopQuick_js.ts +45 -19
- package/project/.sdk/src/cmp/js/ReadmeTopTest_js.ts +35 -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/Config_lua.ts +3 -2
- 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 +50 -13
- 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 +156 -21
- package/project/.sdk/src/cmp/lua/ReadmeRef_lua.ts +71 -23
- package/project/.sdk/src/cmp/lua/ReadmeTopQuick_lua.ts +46 -9
- package/project/.sdk/src/cmp/lua/ReadmeTopTest_lua.ts +43 -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/Config_php.ts +3 -2
- 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 +46 -14
- 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 +159 -25
- package/project/.sdk/src/cmp/php/ReadmeRef_php.ts +90 -45
- package/project/.sdk/src/cmp/php/ReadmeTopHowto_php.ts +1 -1
- package/project/.sdk/src/cmp/php/ReadmeTopQuick_php.ts +43 -11
- package/project/.sdk/src/cmp/php/ReadmeTopTest_php.ts +52 -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/Config_py.ts +3 -2
- 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 +48 -14
- 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 +150 -27
- package/project/.sdk/src/cmp/py/ReadmeRef_py.ts +86 -40
- package/project/.sdk/src/cmp/py/ReadmeTopHowto_py.ts +1 -1
- package/project/.sdk/src/cmp/py/ReadmeTopQuick_py.ts +45 -11
- package/project/.sdk/src/cmp/py/ReadmeTopTest_py.ts +43 -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/Config_rb.ts +3 -2
- 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 +47 -13
- 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 +163 -25
- package/project/.sdk/src/cmp/rb/ReadmeRef_rb.ts +85 -40
- package/project/.sdk/src/cmp/rb/ReadmeTopHowto_rb.ts +1 -1
- package/project/.sdk/src/cmp/rb/ReadmeTopQuick_rb.ts +45 -11
- package/project/.sdk/src/cmp/rb/ReadmeTopTest_rb.ts +54 -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/Config_ts.ts +3 -6
- 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 +32 -10
- 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 +141 -48
- package/project/.sdk/src/cmp/ts/ReadmeRef_ts.ts +50 -16
- package/project/.sdk/src/cmp/ts/ReadmeTopHowto_ts.ts +3 -0
- package/project/.sdk/src/cmp/ts/ReadmeTopQuick_ts.ts +58 -19
- package/project/.sdk/src/cmp/ts/ReadmeTopTest_ts.ts +35 -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/test/test_struct_utility.py +1 -1
- 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 +36 -2
- 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 +30 -11
- package/src/action/feature.ts +12 -14
- package/src/action/target.ts +28 -17
- 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 +274 -0
- package/src/helpers/packageMeta.ts +236 -0
- package/src/sdkgen.ts +91 -23
- package/src/tsconfig.json +1 -0
- package/src/types.ts +85 -2
- package/src/utility.ts +45 -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/model/feature/feature-index.jsonic +0 -5
- package/project/.sdk/model/target/go.jsonic +0 -22
- package/project/.sdk/tm/go/utility/struct/go.mod +0 -3
- /package/project/.sdk/model/feature/{log.jsonic → log.aontu} +0 -0
- /package/project/.sdk/model/feature/{test.jsonic → test.aontu} +0 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
|
|
2
|
+
import { cmp, File, Content } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
} from '@voxgig/apidef'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// Emits test/ReadmeExamplesTest.php — a PHPUnit COMPLETENESS GATE that
|
|
11
|
+
// guarantees every fenced php code example in the package docs is unit-tested.
|
|
12
|
+
// It reads ALL THREE docs — the root (multi-language) ../../README.md, the
|
|
13
|
+
// PHP-specific ../README.md, and ../REFERENCE.md — extracts every fenced php
|
|
14
|
+
// block (tagged by source doc + index) and enforces four properties:
|
|
15
|
+
//
|
|
16
|
+
// 1. SYNTAX — `php -l` on every block (a leading <?php is prepended when the
|
|
17
|
+
// snippet omits one). Every documented example must parse.
|
|
18
|
+
// 2. RUN — every RUNNABLE block (one that constructs the SDK, drives
|
|
19
|
+
// $client->, or performs an entity op) is EXECUTED offline in seeded test
|
|
20
|
+
// mode against the real SDK. The captured stdout+stderr is scanned for
|
|
21
|
+
// FATAL programming-error markers REGARDLESS of exit code, so a bug that a
|
|
22
|
+
// documented try/catch swallows and echoes via getMessage() is still
|
|
23
|
+
// caught. Only a not-found / domain error is tolerated.
|
|
24
|
+
// 3. COMPLETENESS — every block is partitioned into exactly one of
|
|
25
|
+
// {executed, syntaxchecked-nonrunnable, illustration} and the counts must
|
|
26
|
+
// sum to the total. "illustration" is a NARROW explicit class (a
|
|
27
|
+
// signature / method-table block that names the SDK class or a documented
|
|
28
|
+
// method but never uses a live client) — never a catch-all. A
|
|
29
|
+
// runnable-looking block that was NOT executed lands in neither bucket and
|
|
30
|
+
// FAILS the gate: no runnable example can be silently skipped.
|
|
31
|
+
// 4. A per-doc summary (total / executed / syntaxchecked / illustration) is
|
|
32
|
+
// printed to STDERR.
|
|
33
|
+
//
|
|
34
|
+
// A runnable block is rewritten so its client is a test-mode client
|
|
35
|
+
// (<Sdk>SDK::test) seeded with an in-memory fixture for every entity it
|
|
36
|
+
// references; any real constructor is rewritten and the doc's own require of
|
|
37
|
+
// the SDK file is stripped (we require it by absolute path). A block that only
|
|
38
|
+
// *uses* $client (constructed in an earlier fenced block) gets a test client
|
|
39
|
+
// prepended.
|
|
40
|
+
//
|
|
41
|
+
// The emitted PHP builds the ``` fence via chr(96) so this generator string
|
|
42
|
+
// contains no backticks of its own.
|
|
43
|
+
const ReadmeExamplesTest = cmp(function ReadmeExamplesTest(props: any) {
|
|
44
|
+
const { target } = props
|
|
45
|
+
const { model } = props.ctx$
|
|
46
|
+
|
|
47
|
+
const sdkbase = model.const.Name.toLowerCase() + '_sdk'
|
|
48
|
+
const sdkfile = sdkbase + '.php'
|
|
49
|
+
|
|
50
|
+
// Entity accessor ($client->Name()) => fixture storage key (lowercase name),
|
|
51
|
+
// derived from the model so fixtures seed under the key the mock expects.
|
|
52
|
+
const entity = getModelPath(model, `main.${KIT}.entity`) || {}
|
|
53
|
+
const entityLines = Object.values(entity)
|
|
54
|
+
.filter((e: any) => e && e.active !== false)
|
|
55
|
+
.map((e: any) => ` ${JSON.stringify(e.Name)} => ${JSON.stringify(e.name)},`)
|
|
56
|
+
.join('\n')
|
|
57
|
+
|
|
58
|
+
File({ name: 'ReadmeExamplesTest.' + target.ext }, () => {
|
|
59
|
+
Content(`<?php
|
|
60
|
+
declare(strict_types=1);
|
|
61
|
+
|
|
62
|
+
// ${model.const.Name} SDK — documentation example COMPLETENESS GATE.
|
|
63
|
+
//
|
|
64
|
+
// Guarantees every fenced php code example across ALL THREE package docs is
|
|
65
|
+
// unit-tested. Reads the root ../../README.md, the PHP ../README.md, and
|
|
66
|
+
// ../REFERENCE.md, extracts every fenced php block (tagged by source doc +
|
|
67
|
+
// index) and enforces:
|
|
68
|
+
//
|
|
69
|
+
// 1. SYNTAX — 'php -l' on every block (a leading <?php is prepended when the
|
|
70
|
+
// snippet omits one). Every documented php example must parse.
|
|
71
|
+
// 2. RUN — every RUNNABLE block (one that constructs the SDK, drives
|
|
72
|
+
// \\$client->, or performs an entity op load/list/create/update/remove) is
|
|
73
|
+
// EXECUTED offline in seeded test mode (${model.const.Name}SDK::test)
|
|
74
|
+
// against the real SDK. The captured output is scanned for a real
|
|
75
|
+
// PHP-level error (undefined method, wrong-arg-count, TypeError, ...)
|
|
76
|
+
// REGARDLESS of exit code, so a bug a documented try/catch swallows and
|
|
77
|
+
// echoes cannot slip through. Expected not-found domain errors are
|
|
78
|
+
// tolerated.
|
|
79
|
+
// 3. COMPLETENESS — every block is partitioned into exactly one of
|
|
80
|
+
// {executed, syntaxchecked-nonrunnable, illustration}; the counts must sum
|
|
81
|
+
// to the total. A runnable-looking block that was not executed belongs to
|
|
82
|
+
// no bucket and FAILS the gate.
|
|
83
|
+
//
|
|
84
|
+
// PHP is dynamically typed, so syntax + actually running every example is the
|
|
85
|
+
// strongest check available without a live server.
|
|
86
|
+
|
|
87
|
+
require_once __DIR__ . '/../${sdkfile}';
|
|
88
|
+
|
|
89
|
+
use PHPUnit\\Framework\\TestCase;
|
|
90
|
+
|
|
91
|
+
class ReadmeExamplesTest extends TestCase
|
|
92
|
+
{
|
|
93
|
+
private const SDK_CLASS = '${model.const.Name}SDK';
|
|
94
|
+
|
|
95
|
+
// SDK file basename (no extension) — used to strip the doc's own require of
|
|
96
|
+
// the SDK file from a runnable block (we require it by absolute path).
|
|
97
|
+
private const SDK_BASE = '${sdkbase}';
|
|
98
|
+
|
|
99
|
+
// Entity accessor (\\$client->Name()) => fixture storage key (lowercase name).
|
|
100
|
+
private const ENTITIES = [
|
|
101
|
+
${entityLines}
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
// Documented SDK method names — used only to recognise the NARROW
|
|
105
|
+
// signature/method-table "illustration" class.
|
|
106
|
+
private const METHODS = [
|
|
107
|
+
'options_map', 'get_utility', 'prepare', 'direct',
|
|
108
|
+
'data_get', 'data_set', 'match_get', 'match_set', 'make', 'get_name',
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
// PHP-level errors that indicate a real bug in a documented example (as
|
|
112
|
+
// opposed to an expected not-found / domain error, which is tolerated).
|
|
113
|
+
private const FATAL = '/(Call to undefined method|Call to undefined function|Call to a member function|ArgumentCountError|Too few arguments|Undefined constant|Uncaught TypeError)/';
|
|
114
|
+
|
|
115
|
+
// The three documentation sources this gate covers.
|
|
116
|
+
private function docs(): array
|
|
117
|
+
{
|
|
118
|
+
return [
|
|
119
|
+
'root README' => __DIR__ . '/../../README.md',
|
|
120
|
+
'php README' => __DIR__ . '/../README.md',
|
|
121
|
+
'php REFERENCE' => __DIR__ . '/../REFERENCE.md',
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Extract every fenced php block from all three docs, each tagged with its
|
|
127
|
+
* source doc label and its index within that doc.
|
|
128
|
+
*/
|
|
129
|
+
private function phpBlocks(): array
|
|
130
|
+
{
|
|
131
|
+
$fence = str_repeat(chr(96), 3);
|
|
132
|
+
$pattern = '/' . $fence . 'php\\r?\\n(.*?)' . $fence . '/s';
|
|
133
|
+
$blocks = [];
|
|
134
|
+
foreach ($this->docs() as $label => $path) {
|
|
135
|
+
$this->assertFileExists($path, 'missing documentation source: ' . $label);
|
|
136
|
+
preg_match_all($pattern, file_get_contents($path), $m);
|
|
137
|
+
foreach ($m[1] as $i => $b) {
|
|
138
|
+
$blocks[] = ['doc' => $label, 'n' => $i, 'code' => $b];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return $blocks;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// --- classification -----------------------------------------------------
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A block is RUNNABLE when it constructs the SDK, drives \\$client->, or
|
|
148
|
+
* performs an entity operation. Every runnable block MUST be executed.
|
|
149
|
+
*/
|
|
150
|
+
private function isRunnable(string $b): bool
|
|
151
|
+
{
|
|
152
|
+
$cls = preg_quote(self::SDK_CLASS, '/');
|
|
153
|
+
return preg_match('/new\\s+' . $cls . '\\b/', $b) === 1
|
|
154
|
+
|| preg_match('/' . $cls . '::test\\b/', $b) === 1
|
|
155
|
+
|| preg_match('/\\$client\\s*->/', $b) === 1
|
|
156
|
+
|| preg_match('/->\\s*(?:load|list|create|update|remove)\\s*\\(/', $b) === 1;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A block "mentions the SDK" when it references the client variable, the SDK
|
|
161
|
+
* class, an entity accessor, or an entity operation. A non-runnable block
|
|
162
|
+
* that mentions the SDK but is not a signature illustration is an uncovered
|
|
163
|
+
* runnable-looking block and must fail the completeness gate.
|
|
164
|
+
*/
|
|
165
|
+
private function looksSdk(string $b): bool
|
|
166
|
+
{
|
|
167
|
+
if (preg_match('/\\$client\\b/', $b) === 1) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
if (preg_match('/\\b' . preg_quote(self::SDK_CLASS, '/') . '\\b/', $b) === 1) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
if (preg_match('/->\\s*(?:load|list|create|update|remove)\\b/', $b) === 1) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
foreach (array_keys(self::ENTITIES) as $name) {
|
|
177
|
+
if (preg_match('/->\\s*' . preg_quote($name, '/') . '\\s*\\(/', $b) === 1) {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* NARROW illustration class: a non-runnable block that references the SDK
|
|
186
|
+
* class or a documented method NAME as a signature / method-table, and never
|
|
187
|
+
* uses a live client variable. This is an explicit, restricted class — not a
|
|
188
|
+
* catch-all — so an unexecuted block that uses \\$client cannot hide here.
|
|
189
|
+
*/
|
|
190
|
+
private function isIllustration(string $b): bool
|
|
191
|
+
{
|
|
192
|
+
if ($this->isRunnable($b)) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
if (preg_match('/\\$client\\b/', $b) === 1) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (preg_match('/\\b' . preg_quote(self::SDK_CLASS, '/') . '\\b/', $b) === 1) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
foreach (self::METHODS as $meth) {
|
|
202
|
+
if (preg_match('/\\b' . preg_quote($meth, '/') . '\\s*\\(/', $b) === 1) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Partition label for a block: exactly one of the four. */
|
|
210
|
+
private function classify(string $b): string
|
|
211
|
+
{
|
|
212
|
+
if ($this->isRunnable($b)) {
|
|
213
|
+
return 'executed';
|
|
214
|
+
}
|
|
215
|
+
if ($this->isIllustration($b)) {
|
|
216
|
+
return 'illustration';
|
|
217
|
+
}
|
|
218
|
+
if (!$this->looksSdk($b)) {
|
|
219
|
+
return 'syntaxchecked_nonrunnable';
|
|
220
|
+
}
|
|
221
|
+
return 'unclassified';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// --- tests --------------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
public function test_docs_have_php_examples(): void
|
|
227
|
+
{
|
|
228
|
+
$this->assertNotEmpty($this->phpBlocks(), 'docs should contain php examples');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Every php block across all three docs must parse (php -l). */
|
|
232
|
+
public function test_php_snippets_have_valid_syntax(): void
|
|
233
|
+
{
|
|
234
|
+
$failures = [];
|
|
235
|
+
foreach ($this->phpBlocks() as $blk) {
|
|
236
|
+
$block = $blk['code'];
|
|
237
|
+
$code = preg_match('/^\\s*<\\?php/', $block) ? $block : "<?php\\n" . $block;
|
|
238
|
+
$tmp = tempnam(sys_get_temp_dir(), 'readme_php_') . '.php';
|
|
239
|
+
file_put_contents($tmp, $code);
|
|
240
|
+
$out = [];
|
|
241
|
+
$rc = 0;
|
|
242
|
+
exec('php -l ' . escapeshellarg($tmp) . ' 2>&1', $out, $rc);
|
|
243
|
+
@unlink($tmp);
|
|
244
|
+
if ($rc !== 0) {
|
|
245
|
+
$failures[] = $blk['doc'] . ' #' . $blk['n'] . ":\\n" . implode("\\n", $out) . "\\n" . $block;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
$this->assertSame([], $failures, "docs php blocks with syntax errors:\\n" . implode("\\n\\n", $failures));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Build the SDK 'entity' fixture option for the entities a block references,
|
|
253
|
+
* falling back to seeding all entities when none are named.
|
|
254
|
+
*/
|
|
255
|
+
private function fixturesFor(string $block): array
|
|
256
|
+
{
|
|
257
|
+
$refs = [];
|
|
258
|
+
foreach (self::ENTITIES as $name => $storage) {
|
|
259
|
+
if (preg_match('/\\$client->' . preg_quote($name, '/') . '\\b/', $block)) {
|
|
260
|
+
$refs[$storage] = ["test01" => ["id" => "test01"]];
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (empty($refs)) {
|
|
264
|
+
foreach (self::ENTITIES as $storage) {
|
|
265
|
+
$refs[$storage] = ["test01" => ["id" => "test01"]];
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return ["entity" => $refs];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Rewrite a runnable block into an executable offline test-mode program: the
|
|
273
|
+
* doc's own require of the SDK file is stripped (we require it by absolute
|
|
274
|
+
* path); any real client constructor (new <Sdk>SDK / <Sdk>SDK::test) becomes
|
|
275
|
+
* <Sdk>SDK::test(<fixtures>); a block that only uses \\$client gets such a
|
|
276
|
+
* constructor prepended. (The constructor arg-list match is deliberately
|
|
277
|
+
* shallow — it does not span nested parens — because runnable op blocks
|
|
278
|
+
* never build a client inline with a closure argument.)
|
|
279
|
+
*/
|
|
280
|
+
private function toRunner(string $block, string $sdk): string
|
|
281
|
+
{
|
|
282
|
+
$cls = self::SDK_CLASS;
|
|
283
|
+
$fixtures = var_export($this->fixturesFor($block), true);
|
|
284
|
+
$body = preg_replace('/^\\s*<\\?php\\s*/', '', $block);
|
|
285
|
+
// Drop the doc's own require of the SDK file; we require it by absolute path.
|
|
286
|
+
$body = preg_replace(
|
|
287
|
+
'/^[ \\t]*require(?:_once)?[^\\n]*' . preg_quote(self::SDK_BASE, '/') . '[^\\n]*\\r?\\n?/mi',
|
|
288
|
+
'',
|
|
289
|
+
$body
|
|
290
|
+
);
|
|
291
|
+
$ctorRe = '/(?:new\\s+' . preg_quote($cls, '/') . '|' . preg_quote($cls, '/') . '::test)(?:\\([^()]*\\))?/';
|
|
292
|
+
if (preg_match($ctorRe, $body)) {
|
|
293
|
+
$body = preg_replace_callback($ctorRe, function () use ($cls, $fixtures) {
|
|
294
|
+
return $cls . '::test(' . $fixtures . ')';
|
|
295
|
+
}, $body);
|
|
296
|
+
} else {
|
|
297
|
+
$body = '$client = ' . $cls . '::test(' . $fixtures . ");\\n" . $body;
|
|
298
|
+
}
|
|
299
|
+
return "<?php\\nrequire_once " . var_export($sdk, true) . ";\\n" . $body;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Every RUNNABLE block is executed offline in test mode and must not raise a
|
|
304
|
+
* real PHP-level error — even one an error-handling example swallows in a
|
|
305
|
+
* catch (Throwable) and echoes via getMessage(): the captured output is
|
|
306
|
+
* scanned for FATAL either way, so a programming error in a documented
|
|
307
|
+
* try/catch cannot slip through. Expected domain errors (e.g. "404: Not
|
|
308
|
+
* found") never match FATAL, so caught not-found cases stay tolerated.
|
|
309
|
+
*/
|
|
310
|
+
public function test_php_examples_run_offline(): void
|
|
311
|
+
{
|
|
312
|
+
$ran = 0;
|
|
313
|
+
$failures = [];
|
|
314
|
+
$sdk = __DIR__ . '/../${sdkfile}';
|
|
315
|
+
foreach ($this->phpBlocks() as $blk) {
|
|
316
|
+
if (!$this->isRunnable($blk['code'])) {
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
$ran++;
|
|
320
|
+
$runner = $this->toRunner($blk['code'], $sdk);
|
|
321
|
+
$tmp = tempnam(sys_get_temp_dir(), 'readme_run_') . '.php';
|
|
322
|
+
file_put_contents($tmp, $runner);
|
|
323
|
+
$out = [];
|
|
324
|
+
$rc = 0;
|
|
325
|
+
exec('php ' . escapeshellarg($tmp) . ' 2>&1', $out, $rc);
|
|
326
|
+
@unlink($tmp);
|
|
327
|
+
$text = implode("\\n", $out);
|
|
328
|
+
if (preg_match(self::FATAL, $text) === 1) {
|
|
329
|
+
$failures[] = $blk['doc'] . ' #' . $blk['n'] . ' (exit ' . $rc . "):\\n" . $text . "\\n" . $blk['code'];
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
$this->assertGreaterThan(0, $ran, 'expected at least one runnable example to execute');
|
|
333
|
+
$this->assertSame([], $failures, "docs php examples raised a real error when run offline:\\n" . implode("\\n\\n", $failures));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* COMPLETENESS GATE: every fenced php block is partitioned into exactly one
|
|
338
|
+
* of {executed, syntaxchecked-nonrunnable, illustration}. The three counts
|
|
339
|
+
* must sum to the total. A block that references the SDK but is neither
|
|
340
|
+
* runnable (so not executed) nor a narrow signature illustration is
|
|
341
|
+
* "unclassified" — a runnable-looking example that would be silently skipped
|
|
342
|
+
* — and fails the gate.
|
|
343
|
+
*/
|
|
344
|
+
public function test_php_examples_are_completely_classified(): void
|
|
345
|
+
{
|
|
346
|
+
$blocks = $this->phpBlocks();
|
|
347
|
+
$buckets = [
|
|
348
|
+
'executed' => [],
|
|
349
|
+
'syntaxchecked_nonrunnable' => [],
|
|
350
|
+
'illustration' => [],
|
|
351
|
+
'unclassified' => [],
|
|
352
|
+
];
|
|
353
|
+
$perDoc = [];
|
|
354
|
+
foreach ($blocks as $blk) {
|
|
355
|
+
$cls = $this->classify($blk['code']);
|
|
356
|
+
$buckets[$cls][] = $blk;
|
|
357
|
+
$doc = $blk['doc'];
|
|
358
|
+
if (!isset($perDoc[$doc])) {
|
|
359
|
+
$perDoc[$doc] = ['total' => 0, 'executed' => 0, 'syntaxchecked_nonrunnable' => 0, 'illustration' => 0, 'unclassified' => 0];
|
|
360
|
+
}
|
|
361
|
+
$perDoc[$doc]['total']++;
|
|
362
|
+
$perDoc[$doc][$cls]++;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
$summary = "ReadmeExamplesTest — php example coverage:\\n";
|
|
366
|
+
foreach ($perDoc as $doc => $c) {
|
|
367
|
+
$summary .= sprintf(
|
|
368
|
+
" %-14s total=%d executed=%d syntaxchecked=%d illustration=%d%s\\n",
|
|
369
|
+
$doc, $c['total'], $c['executed'], $c['syntaxchecked_nonrunnable'], $c['illustration'],
|
|
370
|
+
$c['unclassified'] > 0 ? ' UNCLASSIFIED=' . $c['unclassified'] : ''
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
fwrite(STDERR, "\\n" . $summary);
|
|
374
|
+
|
|
375
|
+
$unclassified = array_map(
|
|
376
|
+
function ($b) { return $b['doc'] . ' #' . $b['n'] . ":\\n" . $b['code']; },
|
|
377
|
+
$buckets['unclassified']
|
|
378
|
+
);
|
|
379
|
+
$this->assertSame([], $unclassified,
|
|
380
|
+
"runnable-looking php blocks that were neither executed nor a signature illustration:\\n"
|
|
381
|
+
. implode("\\n\\n", $unclassified));
|
|
382
|
+
|
|
383
|
+
$total = count($blocks);
|
|
384
|
+
$sum = count($buckets['executed'])
|
|
385
|
+
+ count($buckets['syntaxchecked_nonrunnable'])
|
|
386
|
+
+ count($buckets['illustration']);
|
|
387
|
+
$this->assertSame($total, $sum,
|
|
388
|
+
"every php block must be executed, syntaxchecked-nonrunnable, or illustration.\\n" . $summary);
|
|
389
|
+
|
|
390
|
+
$this->assertGreaterThan(0, count($buckets['executed']),
|
|
391
|
+
'expected at least one executed php example');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
`)
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
export {
|
|
400
|
+
ReadmeExamplesTest
|
|
401
|
+
}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content, isAuthActive } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, isAuthActive, envName, canonKey, entityIdField, entityPrimaryOp, opRequestShape } from '@voxgig/sdkgen'
|
|
3
|
+
|
|
4
|
+
import { KIT, getModelPath, nom } from '@voxgig/apidef'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// A type-correct PHP literal for a field's canonical type.
|
|
8
|
+
function phpLit(type: any): string {
|
|
9
|
+
const k = canonKey(type)
|
|
10
|
+
if ('INTEGER' === k || 'NUMBER' === k) return '1'
|
|
11
|
+
if ('BOOLEAN' === k) return 'true'
|
|
12
|
+
if ('ARRAY' === k || 'OBJECT' === k) return '[]'
|
|
13
|
+
return '"example"'
|
|
14
|
+
}
|
|
3
15
|
|
|
4
16
|
|
|
5
17
|
const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
|
|
6
18
|
const { target, ctx$: { model } } = props
|
|
7
19
|
|
|
20
|
+
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
21
|
+
const exampleEntity = Object.values(entity || {}).find((e: any) => e && e.active !== false) as any
|
|
22
|
+
const eName = exampleEntity ? nom(exampleEntity, 'Name') : 'Entity'
|
|
23
|
+
// Model-driven id key: null when the entity has no id-like field.
|
|
24
|
+
const idF = exampleEntity ? entityIdField(exampleEntity) : null
|
|
25
|
+
// Drive the test-mode example off the entity's PRIMARY op — never a hardcoded
|
|
26
|
+
// `load` a create-only entity lacks.
|
|
27
|
+
const primaryOp = exampleEntity ? (entityPrimaryOp(exampleEntity) || 'load') : 'load'
|
|
28
|
+
const isMatchOp = 'load' === primaryOp || 'remove' === primaryOp
|
|
29
|
+
const seedSentence = idF
|
|
30
|
+
? '. Seed fixture\ndata via the `entity` option so offline calls resolve without a live server'
|
|
31
|
+
: ''
|
|
32
|
+
const testCtor = idF
|
|
33
|
+
? `${model.const.Name}SDK::test([\n "entity" => ["${eName.toLowerCase()}" => ["test01" => ["${idF}" => "test01"]]],\n])`
|
|
34
|
+
: `${model.const.Name}SDK::test()`
|
|
35
|
+
let testCallArg = ''
|
|
36
|
+
if (exampleEntity && isMatchOp) {
|
|
37
|
+
testCallArg = idF ? `["${idF}" => "test01"]` : ''
|
|
38
|
+
} else if (exampleEntity && ('create' === primaryOp || 'update' === primaryOp)) {
|
|
39
|
+
const items = opRequestShape(exampleEntity, primaryOp).items
|
|
40
|
+
.filter((it: any) => it.name !== idF && it.name !== 'id')
|
|
41
|
+
const required = items.filter((it: any) => !it.optional)
|
|
42
|
+
const chosen = required.length ? required : items.slice(0, 3)
|
|
43
|
+
testCallArg = `[${chosen.map((it: any) => `"${it.name}" => ${phpLit(it.type)}`).join(', ')}]`
|
|
44
|
+
}
|
|
45
|
+
|
|
8
46
|
const apikeyEnvLine = isAuthActive(model)
|
|
9
|
-
? `\n${model
|
|
47
|
+
? `\n${envName(model)}_APIKEY=<your-key>`
|
|
10
48
|
: ''
|
|
11
49
|
|
|
12
50
|
Content(`### Make a direct HTTP request
|
|
@@ -14,28 +52,34 @@ const ReadmeHowto = cmp(function ReadmeHowto(props: any) {
|
|
|
14
52
|
For endpoints not covered by entity methods:
|
|
15
53
|
|
|
16
54
|
\`\`\`php
|
|
17
|
-
|
|
55
|
+
// direct() is the raw-HTTP escape hatch: it returns a result array
|
|
56
|
+
// (it does not throw). Branch on $result["ok"].
|
|
57
|
+
$result = $client->direct([
|
|
18
58
|
"path" => "/api/resource/{id}",
|
|
19
59
|
"method" => "GET",
|
|
20
60
|
"params" => ["id" => "example"],
|
|
21
61
|
]);
|
|
22
|
-
if ($err) { throw new \\Exception($err); }
|
|
23
62
|
|
|
24
63
|
if ($result["ok"]) {
|
|
25
64
|
echo $result["status"]; // 200
|
|
26
65
|
print_r($result["data"]); // response body
|
|
66
|
+
} else {
|
|
67
|
+
// On an HTTP error status there is no err (only a transport failure sets
|
|
68
|
+
// it), so fall back to the status code.
|
|
69
|
+
$err = $result["err"] ?? null;
|
|
70
|
+
echo "Error: " . ($err ? $err->getMessage() : "HTTP " . $result["status"]);
|
|
27
71
|
}
|
|
28
72
|
\`\`\`
|
|
29
73
|
|
|
30
74
|
### Prepare a request without sending it
|
|
31
75
|
|
|
32
76
|
\`\`\`php
|
|
33
|
-
|
|
77
|
+
// prepare() throws on error and returns the fetch definition.
|
|
78
|
+
$fetchdef = $client->prepare([
|
|
34
79
|
"path" => "/api/resource/{id}",
|
|
35
80
|
"method" => "DELETE",
|
|
36
81
|
"params" => ["id" => "example"],
|
|
37
82
|
]);
|
|
38
|
-
if ($err) { throw new \\Exception($err); }
|
|
39
83
|
|
|
40
84
|
echo $fetchdef["url"];
|
|
41
85
|
echo $fetchdef["method"];
|
|
@@ -44,15 +88,14 @@ print_r($fetchdef["headers"]);
|
|
|
44
88
|
|
|
45
89
|
### Use test mode
|
|
46
90
|
|
|
47
|
-
Create a mock client for unit testing — no server required:
|
|
91
|
+
Create a mock client for unit testing — no server required${seedSentence}:
|
|
48
92
|
|
|
49
93
|
\`\`\`php
|
|
50
|
-
$client = ${
|
|
94
|
+
$client = ${testCtor};
|
|
51
95
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
);
|
|
55
|
-
// $result contains mock response data
|
|
96
|
+
// Entity ops return the bare mock record (throws on error).
|
|
97
|
+
$${eName.toLowerCase()} = $client->${eName}()->${primaryOp}(${testCallArg});
|
|
98
|
+
print_r($${eName.toLowerCase()});
|
|
56
99
|
\`\`\`
|
|
57
100
|
|
|
58
101
|
### Use a custom fetch function
|
|
@@ -85,7 +128,7 @@ $client = new ${model.const.Name}SDK([
|
|
|
85
128
|
Create a \`.env.local\` file at the project root:
|
|
86
129
|
|
|
87
130
|
\`\`\`
|
|
88
|
-
${model
|
|
131
|
+
${envName(model)}_TEST_LIVE=TRUE${apikeyEnvLine}
|
|
89
132
|
\`\`\`
|
|
90
133
|
|
|
91
134
|
Then run:
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
|
|
2
|
-
import { cmp, Content } from '@voxgig/sdkgen'
|
|
2
|
+
import { cmp, Content, installCommand, isPublished, repoInfo } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const ReadmeInstall = cmp(function ReadmeInstall(props: any) {
|
|
6
6
|
const { target, ctx$ } = props
|
|
7
7
|
const { model } = ctx$
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (isPublished(model, target.name)) {
|
|
10
|
+
Content(`\`\`\`bash
|
|
11
|
+
${installCommand(model, target.name)}
|
|
11
12
|
\`\`\`
|
|
12
13
|
|
|
14
|
+
`)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Publish pending: not yet on Packagist. Install from the git release tag.
|
|
19
|
+
const { releasesUrl } = repoInfo(model)
|
|
20
|
+
Content(`This package is not yet published to Packagist. Install it from the
|
|
21
|
+
GitHub release tag (\`${target.name}/vX.Y.Z\`):
|
|
22
|
+
|
|
23
|
+
- Releases: [${releasesUrl}](${releasesUrl})
|
|
24
|
+
|
|
13
25
|
`)
|
|
14
26
|
})
|
|
15
27
|
|
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
|
|
2
2
|
import { cmp, Content } from '@voxgig/sdkgen'
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
KIT,
|
|
6
|
+
getModelPath,
|
|
7
|
+
nom,
|
|
8
|
+
} from '@voxgig/apidef'
|
|
9
|
+
|
|
4
10
|
|
|
5
11
|
const ReadmeIntro = cmp(function ReadmeIntro(props: any) {
|
|
6
12
|
const { target, ctx$: { model } } = props
|
|
13
|
+
const info = (model.main && model.main.kit && model.main.kit.info) || {}
|
|
14
|
+
const tagline = info.tagline || ''
|
|
15
|
+
|
|
16
|
+
// Derive a representative entity (and its operations) from the model so the
|
|
17
|
+
// semantic-entity pitch names something real rather than a placeholder.
|
|
18
|
+
const entity = getModelPath(model, `main.${KIT}.entity`) || {}
|
|
19
|
+
const exampleEntity = Object.values(entity).find((e: any) => e && e.active !== false) as any
|
|
20
|
+
const eName = exampleEntity ? nom(exampleEntity, 'Name') : null
|
|
21
|
+
// Model-driven op list — union of the operations the active entities
|
|
22
|
+
// actually expose (a read-only entity has just list+load), in canonical
|
|
23
|
+
// order; never claim create/update/remove exist when no entity has them.
|
|
24
|
+
const CANON_OPS = ['list', 'load', 'create', 'update', 'remove']
|
|
25
|
+
const opSet = new Set<string>()
|
|
26
|
+
Object.values(entity || {}).forEach((e: any) => {
|
|
27
|
+
if (!e || e.active === false) return
|
|
28
|
+
Object.keys(e.op || {}).forEach((o: string) => {
|
|
29
|
+
if (e.op[o] && e.op[o].active !== false) opSet.add(o)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
const opnames = CANON_OPS.filter((o) => opSet.has(o))
|
|
33
|
+
.concat([...opSet].filter((o) => !CANON_OPS.includes(o)))
|
|
34
|
+
const opList = (opnames.length > 0 ? opnames : ['list', 'load']).join('`/`')
|
|
35
|
+
|
|
36
|
+
const semantic = eName
|
|
37
|
+
? `The SDK exposes the API as capitalised, semantic **Entities** — for example \`$client->${eName}()\` — with named operations (\`${opList}\`) instead of raw URL paths and query strings. Working with resources and verbs keeps call sites self-describing and reduces cognitive load.
|
|
38
|
+
|
|
39
|
+
`
|
|
40
|
+
: ''
|
|
7
41
|
|
|
8
42
|
Content(`# ${model.Name} ${target.title} SDK
|
|
9
43
|
|
|
10
|
-
|
|
44
|
+
${tagline}
|
|
45
|
+
|
|
46
|
+
The ${target.title} SDK for the ${model.Name} API — an entity-oriented client using PHP conventions.
|
|
47
|
+
|
|
48
|
+
${semantic}> Other languages, the CLI, and MCP server live alongside this one — see
|
|
49
|
+
> the [top-level README](../README.md).
|
|
11
50
|
|
|
12
51
|
`)
|
|
13
52
|
})
|
|
@@ -13,6 +13,23 @@ const ReadmeModel = cmp(function ReadmeModel(props: any) {
|
|
|
13
13
|
const entity = getModelPath(model, `main.${KIT}.entity`)
|
|
14
14
|
const entityList = each(entity).filter((e: any) => e.active !== false)
|
|
15
15
|
|
|
16
|
+
// Model-driven op rows for the shared entity interface: emit a
|
|
17
|
+
// load/list/create/update/remove row only for operations at least one active
|
|
18
|
+
// entity actually exposes (a read-only entity has just list+load) — never
|
|
19
|
+
// document an operation no entity has.
|
|
20
|
+
const opUnion = new Set<string>()
|
|
21
|
+
entityList.forEach((e: any) => Object.keys(e.op || {})
|
|
22
|
+
.forEach((o: string) => { if (e.op[o] && e.op[o].active !== false) opUnion.add(o) }))
|
|
23
|
+
const opRowDefs: Record<string, string> = {
|
|
24
|
+
load: '| `load` | `($reqmatch, $ctrl): array` | Load a single entity by match criteria. |',
|
|
25
|
+
list: '| `list` | `(?array $reqmatch = null, $ctrl): array` | List entities matching the criteria (call with no argument to list all). |',
|
|
26
|
+
create: '| `create` | `($reqdata, $ctrl): array` | Create a new entity. |',
|
|
27
|
+
update: '| `update` | `($reqdata, $ctrl): array` | Update an existing entity. |',
|
|
28
|
+
remove: '| `remove` | `($reqmatch, $ctrl): array` | Remove an entity. |',
|
|
29
|
+
}
|
|
30
|
+
const opRows = ['load', 'list', 'create', 'update', 'remove']
|
|
31
|
+
.filter((o) => opUnion.has(o)).map((o) => opRowDefs[o]).join('\n')
|
|
32
|
+
|
|
16
33
|
const apikeyOptionRow = isAuthActive(model)
|
|
17
34
|
? '| `apikey` | `string` | API key for authentication. |\n'
|
|
18
35
|
: ''
|
|
@@ -54,7 +71,8 @@ Creates a test-mode client with mock transport. Both arguments may be \`null\`.
|
|
|
54
71
|
`)
|
|
55
72
|
|
|
56
73
|
each(entityList, (ent: any) => {
|
|
57
|
-
|
|
74
|
+
const article = /^[aeiou]/i.test(ent.Name) ? 'an' : 'a'
|
|
75
|
+
Content(`| \`${ent.Name}\` | \`($data): ${ent.Name}Entity\` | Create ${article} ${ent.Name} entity instance. |
|
|
58
76
|
`)
|
|
59
77
|
})
|
|
60
78
|
|
|
@@ -65,11 +83,7 @@ All entities share the same interface.
|
|
|
65
83
|
|
|
66
84
|
| Method | Signature | Description |
|
|
67
85
|
| --- | --- | --- |
|
|
68
|
-
|
|
69
|
-
| \`list\` | \`($reqmatch, $ctrl): array\` | List entities matching the criteria. |
|
|
70
|
-
| \`create\` | \`($reqdata, $ctrl): array\` | Create a new entity. |
|
|
71
|
-
| \`update\` | \`($reqdata, $ctrl): array\` | Update an existing entity. |
|
|
72
|
-
| \`remove\` | \`($reqmatch, $ctrl): array\` | Remove an entity. |
|
|
86
|
+
${opRows}
|
|
73
87
|
| \`data_get\` | \`(): array\` | Get entity data. |
|
|
74
88
|
| \`data_set\` | \`($data): void\` | Set entity data. |
|
|
75
89
|
| \`match_get\` | \`(): array\` | Get entity match criteria. |
|
|
@@ -79,8 +93,12 @@ All entities share the same interface.
|
|
|
79
93
|
|
|
80
94
|
### Result shape
|
|
81
95
|
|
|
82
|
-
Entity operations return
|
|
83
|
-
\`
|
|
96
|
+
Entity operations return the bare result data (an \`array\` for single-entity
|
|
97
|
+
ops, a \`list\` for \`list\`) and throw on error. Wrap calls in
|
|
98
|
+
\`try\`/\`catch\` to handle failures.
|
|
99
|
+
|
|
100
|
+
The \`direct()\` escape hatch never throws — it returns a result \`array\`
|
|
101
|
+
you branch on via \`$result["ok"]\`:
|
|
84
102
|
|
|
85
103
|
| Key | Type | Description |
|
|
86
104
|
| --- | --- | --- |
|