@rainbow-robotics/muscat-plugin-kit 0.1.2-dev.9 → 0.10.1-dev.0
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/README.ko.md +1186 -0
- package/README.md +1137 -57
- package/cli/README.md +239 -7
- package/cli/bin/create-muscat-plugin.mjs +1 -1
- package/cli/bin/muscat-pk.mjs +123 -27
- package/cli/bundle-templates.mjs +31 -0
- package/cli/docker/Dockerfile.cpp +28 -0
- package/cli/docker/Dockerfile.dev +17 -0
- package/cli/docker/Dockerfile.python +21 -0
- package/cli/prepack.mjs +10 -0
- package/cli/src/__pycache__/host_agent.cpython-37.pyc +0 -0
- package/cli/src/ai-rules.mjs +107 -0
- package/cli/src/build.mjs +333 -93
- package/cli/src/check-package.mjs +8 -23
- package/cli/src/completion.mjs +168 -0
- package/cli/src/cpp.mjs +78 -0
- package/cli/src/cppIde.mjs +76 -0
- package/cli/src/dev.mjs +195 -6
- package/cli/src/devBack.mjs +671 -60
- package/cli/src/devId.mjs +54 -0
- package/cli/src/devSession.mjs +67 -0
- package/cli/src/devUi.mjs +214 -25
- package/cli/src/esbuild.mjs +27 -10
- package/cli/src/host_agent.py +223 -0
- package/cli/src/manifest.mjs +288 -0
- package/cli/src/mcp.mjs +1153 -0
- package/cli/src/mcpProxy.mjs +110 -0
- package/cli/src/muscatLocal.mjs +292 -0
- package/cli/src/new.mjs +205 -68
- package/cli/src/pluginDevServer.mjs +111 -0
- package/cli/src/ports.mjs +193 -0
- package/cli/src/projectCheck.mjs +102 -0
- package/cli/src/python.mjs +112 -0
- package/cli/src/ros2.mjs +62 -18
- package/cli/src/sdk.mjs +74 -24
- package/cli/src/sim.mjs +177 -0
- package/cli/src/storybook.mjs +150 -0
- package/cli/src/templates-embedded.mjs +4 -0
- package/cli/src/type.mjs +93 -34
- package/cli/src/uninstall.mjs +81 -0
- package/cli/src/update.mjs +364 -35
- package/cli/src/util.mjs +341 -11
- package/cli/src/zenohDev.mjs +83 -0
- package/cli/src/zip.mjs +121 -0
- package/cli/storybook-dist/_design-tokens.css +4957 -0
- package/cli/storybook-dist/_stories-src/NxAvatar.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/NxPagination.stories.tsx +28 -0
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordion.stories.tsx +46 -0
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordionGroup.stories.tsx +73 -0
- package/cli/storybook-dist/_stories-src/RBBadge/RBBadge.stories.tsx +93 -0
- package/cli/storybook-dist/_stories-src/RBBattery/RBBattery.stories.tsx +74 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckIconButton.stories.tsx +28 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckLabelButton.stories.tsx +84 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBIconButton.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBInlineLabelButton.stories.tsx +41 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBLabelButton.stories.tsx +60 -0
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBDateInput.stories.tsx +44 -0
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +56 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBAlert.stories.tsx +51 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBConfirm.stories.tsx +55 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBPrompt.stories.tsx +52 -0
- package/cli/storybook-dist/_stories-src/RBDivider/RBDivider.stories.tsx +93 -0
- package/cli/storybook-dist/_stories-src/RBEmptyView/RBEmptyView.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBIcons/RBColorIcons.stories.tsx +108 -0
- package/cli/storybook-dist/_stories-src/RBIcons/RBIcons.stories.tsx +106 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBCheckBox.stories.tsx +89 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBMultiRangeInput.stories.tsx +64 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioBox.stories.tsx +65 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioButton.stories.tsx +68 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +216 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBSideNumberInput.stories.tsx +90 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextArea.stories.tsx +45 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextInput.stories.tsx +50 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBTextField.stories.tsx +102 -0
- package/cli/storybook-dist/_stories-src/RBJoyStick/RBJoyStick.stories.tsx +31 -0
- package/cli/storybook-dist/_stories-src/RBLight/RBLight.stories.tsx +36 -0
- package/cli/storybook-dist/_stories-src/RBPagination/RBPagination.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCard/RBCard.stories.tsx +89 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCommand/RBCommand.stories.tsx +116 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDialog/RBDialog.stories.tsx +74 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDrawer/RBDrawer.stories.tsx +99 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDropdownMenu/RBDropdownMenu.stories.tsx +123 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBMenubar/RBMenubar.stories.tsx +135 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBPopover/RBPopover.stories.tsx +69 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBResizable/RBResizable.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSheet/RBSheet.stories.tsx +91 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSlider/RBSlider.stories.tsx +38 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSwitch/RBSwitch.stories.tsx +112 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBTabs/RBTabs.stories.tsx +75 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggle/RBToggle.stories.tsx +51 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggleGroup/RBToggleGroup.stories.tsx +84 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBChipTab.stories.tsx +102 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBChipsBoxTab.stories.tsx +78 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBTab.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/RBTable/RBTable.stories.tsx +177 -0
- package/cli/storybook-dist/_stories-src/RBTable/RBTableRow.stories.tsx +64 -0
- package/cli/storybook-dist/_stories-src/RBToast/RBToast.stories.tsx +117 -0
- package/cli/storybook-dist/_stories-src/RBTooltip/RBTooltip.stories.tsx +50 -0
- package/cli/storybook-dist/_stories-src/loading/RBSpinner.stories.tsx +30 -0
- package/cli/storybook-dist/_stories-src/nx-button/NxButton.stories.tsx +54 -0
- package/cli/storybook-dist/_stories-src/nx-button/NxPointerHoldButton.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/nx-icons/NxIcons.stories.tsx +48 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxNumberInput.stories.tsx +103 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxRangeInput.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSelectBox.stories.tsx +67 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSlideRange.stories.tsx +45 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSwitch.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextArea.stories.tsx +48 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextInput.stories.tsx +46 -0
- package/cli/storybook-dist/assets/Color-YHDXOIA2-pCKrjUal.js +1 -0
- package/cli/storybook-dist/assets/Docs-B-Y7I1GA.js +7 -0
- package/cli/storybook-dist/assets/Docs-BFJcE_VS.js +8 -0
- package/cli/storybook-dist/assets/Docs-B_QaTtz8.js +8 -0
- package/cli/storybook-dist/assets/Docs-CryDGmfh.js +20 -0
- package/cli/storybook-dist/assets/Docs-Cw2AVNKx.js +7 -0
- package/cli/storybook-dist/assets/Docs-Q6r1fBeL.js +12 -0
- package/cli/storybook-dist/assets/DocsRenderer-CFRXHY34-_OmZBCn8.js +2 -0
- package/cli/storybook-dist/assets/NxAvatar.stories-Ctf5G2FQ.js +13 -0
- package/cli/storybook-dist/assets/NxButton.stories-DeLObVSj.js +20 -0
- package/cli/storybook-dist/assets/NxIcons.stories-DeqrVzVs.js +3 -0
- package/cli/storybook-dist/assets/NxNumberInput.stories-LqoY0ed1.js +26 -0
- package/cli/storybook-dist/assets/NxPagination.stories-DI6bXuJM.js +11 -0
- package/cli/storybook-dist/assets/NxPointerHoldButton.stories-3HSV1XmN.js +14 -0
- package/cli/storybook-dist/assets/NxRangeInput.stories-1pjgQVaG.js +17 -0
- package/cli/storybook-dist/assets/NxSelectBox.stories-bcQPZEuF.js +17 -0
- package/cli/storybook-dist/assets/NxSlideRange.stories-BosX4axk.js +14 -0
- package/cli/storybook-dist/assets/NxSwitch.stories-DxV6dS33.js +11 -0
- package/cli/storybook-dist/assets/NxTextArea.stories-CO545-LP.js +11 -0
- package/cli/storybook-dist/assets/NxTextInput.stories-BP0npai1.js +11 -0
- package/cli/storybook-dist/assets/PretendardVariable-CJuje-Rk.woff2 +0 -0
- package/cli/storybook-dist/assets/RBAccordion.stories-fVR4Va2a.js +17 -0
- package/cli/storybook-dist/assets/RBAccordionGroup.stories-Du5bsckD.js +33 -0
- package/cli/storybook-dist/assets/RBAlert.stories-DNkMXUu6.js +17 -0
- package/cli/storybook-dist/assets/RBBadge.stories-C44pXt8D.js +1 -0
- package/cli/storybook-dist/assets/RBBattery.stories-DE2JHvfL.js +10 -0
- package/cli/storybook-dist/assets/RBCard.stories-CuIda7NI.js +45 -0
- package/cli/storybook-dist/assets/RBCheckBox.stories-D1qM1ayr.js +1 -0
- package/cli/storybook-dist/assets/RBCheckIconButton.stories-e4gkliBO.js +1 -0
- package/cli/storybook-dist/assets/RBCheckLabelButton.stories-CDzCtsMI.js +24 -0
- package/cli/storybook-dist/assets/RBChipTab.stories-DBrc_3Mp.js +21 -0
- package/cli/storybook-dist/assets/RBChipsBoxTab.stories-hlrsHjKY.js +1 -0
- package/cli/storybook-dist/assets/RBColorIcons.stories-BHUvpkdu.js +3 -0
- package/cli/storybook-dist/assets/RBCommand.stories-azAF41NP.js +73 -0
- package/cli/storybook-dist/assets/RBConfirm.stories-BMNjwbmT.js +20 -0
- package/cli/storybook-dist/assets/RBDateInput.stories-D0VezDzv.js +15 -0
- package/cli/storybook-dist/assets/RBDialog.stories-AOJ975Fy.js +38 -0
- package/cli/storybook-dist/assets/RBDivider.stories-NSvnj43Z.js +1 -0
- package/cli/storybook-dist/assets/RBDrawer.stories-Du0oTvD1.js +14 -0
- package/cli/storybook-dist/assets/RBDropdownMenu.stories-Hsxve4PW.js +86 -0
- package/cli/storybook-dist/assets/RBEmptyView.stories-BlwHx3zp.js +12 -0
- package/cli/storybook-dist/assets/RBIconButton.stories-DAPDY63x.js +1 -0
- package/cli/storybook-dist/assets/RBIcons.stories-W5ZUV2L1.js +3 -0
- package/cli/storybook-dist/assets/RBInlineLabelButton.stories-C99j0Y3g.js +1 -0
- package/cli/storybook-dist/assets/RBJoyStick.stories-Du0H1iAS.js +11 -0
- package/cli/storybook-dist/assets/RBLabelButton.stories-BlvHaU_Z.js +1 -0
- package/cli/storybook-dist/assets/RBLight.stories-BY6DKrre.js +1 -0
- package/cli/storybook-dist/assets/RBMenubar.stories-D2PEGpM9.js +3 -0
- package/cli/storybook-dist/assets/RBMultiRangeInput.stories-Bm2qSmjq.js +14 -0
- package/cli/storybook-dist/assets/RBPagination.stories-DDleJa5N.js +17 -0
- package/cli/storybook-dist/assets/RBPopover.stories-27YxPSFG.js +11 -0
- package/cli/storybook-dist/assets/RBPrompt.stories-BFaIOctr.js +20 -0
- package/cli/storybook-dist/assets/RBRadioBox.stories-BroDar0t.js +1 -0
- package/cli/storybook-dist/assets/RBRadioButton.stories-M3O-wX7V.js +11 -0
- package/cli/storybook-dist/assets/RBRangeDateInput.stories-CWlM_D5X.js +15 -0
- package/cli/storybook-dist/assets/RBResizable.stories-ui8X1qnc.js +20 -0
- package/cli/storybook-dist/assets/RBSelectBox.stories-C8T6cfA0.js +74 -0
- package/cli/storybook-dist/assets/RBSheet.stories-BCOo_Zcc.js +39 -0
- package/cli/storybook-dist/assets/RBSideNumberInput.stories-CU2_MVlJ.js +5 -0
- package/cli/storybook-dist/assets/RBSlider.stories-DgOp1TFc.js +5 -0
- package/cli/storybook-dist/assets/RBSpinner.stories-qLScY3zZ.js +14 -0
- package/cli/storybook-dist/assets/RBSwitch.stories-SXSY1QMb.js +65 -0
- package/cli/storybook-dist/assets/RBTab.stories-BzXXTsXP.js +1 -0
- package/cli/storybook-dist/assets/RBTable.stories-DHTeRNVk.js +62 -0
- package/cli/storybook-dist/assets/RBTableRow.stories-DRNRsd15.js +11 -0
- package/cli/storybook-dist/assets/RBTabs.stories-DP0noBLp.js +21 -0
- package/cli/storybook-dist/assets/RBTextArea.stories-TkaejfxJ.js +5 -0
- package/cli/storybook-dist/assets/RBTextField.stories-B6VpCGyt.js +45 -0
- package/cli/storybook-dist/assets/RBTextInput.stories-D3hZ08e-.js +5 -0
- package/cli/storybook-dist/assets/RBToast.stories-BQ2wS2U0.js +11 -0
- package/cli/storybook-dist/assets/RBToggle.stories-GVOjGqo3.js +12 -0
- package/cli/storybook-dist/assets/RBToggleGroup.stories-pzx0btOD.js +17 -0
- package/cli/storybook-dist/assets/RBTooltip.stories-jufB6fa1.js +9 -0
- package/cli/storybook-dist/assets/SideNumberInput-BYlmNHEw.js +1109 -0
- package/cli/storybook-dist/assets/SideNumberInput-SAkhydsn.css +21 -0
- package/cli/storybook-dist/assets/browserUtils-CQM9Za7e.js +1 -0
- package/cli/storybook-dist/assets/chunk-XP5HYGXS-BHXC9YeQ.js +1 -0
- package/cli/storybook-dist/assets/client-DTf7SId2.js +1 -0
- package/cli/storybook-dist/assets/entry-preview-CAkU-e0D.js +2 -0
- package/cli/storybook-dist/assets/entry-preview-docs-b8bpVBXy.js +46 -0
- package/cli/storybook-dist/assets/iframe-B-BmTsxV.js +211 -0
- package/cli/storybook-dist/assets/index-B4FGfHer.js +1 -0
- package/cli/storybook-dist/assets/index-BRq5TIsn.js +24 -0
- package/cli/storybook-dist/assets/index-CT3U1fyk.js +1 -0
- package/cli/storybook-dist/assets/index-ChsGqxH_.js +9 -0
- package/cli/storybook-dist/assets/index-CkB0GfaI.js +575 -0
- package/cli/storybook-dist/assets/index-ClAc6FBW.js +240 -0
- package/cli/storybook-dist/assets/index-DKFBREX_.js +1 -0
- package/cli/storybook-dist/assets/index-DgH-xKnr.js +11 -0
- package/cli/storybook-dist/assets/index-Dmy2JGbm.js +1 -0
- package/cli/storybook-dist/assets/index-DrFu-skq.js +6 -0
- package/cli/storybook-dist/assets/jsx-runtime-BTJTZTIL.js +9 -0
- package/cli/storybook-dist/assets/preview-B8lJiyuQ.js +34 -0
- package/cli/storybook-dist/assets/preview-BBWR9nbA.js +1 -0
- package/cli/storybook-dist/assets/preview-BVJwlGUF.js +1 -0
- package/cli/storybook-dist/assets/preview-BWzBA1C2.js +396 -0
- package/cli/storybook-dist/assets/preview-CVgpLj3b.js +1 -0
- package/cli/storybook-dist/assets/preview-CvbIS5ZJ.js +1 -0
- package/cli/storybook-dist/assets/preview-CznQwwbo.js +3 -0
- package/cli/storybook-dist/assets/preview-DD_OYowb.js +1 -0
- package/cli/storybook-dist/assets/preview-DGUiP6tS.js +7 -0
- package/cli/storybook-dist/assets/preview-DHQbi4pV.js +1 -0
- package/cli/storybook-dist/assets/preview-M77JRg1A.js +2 -0
- package/cli/storybook-dist/assets/preview-kTZPgP6D.css +1 -0
- package/cli/storybook-dist/assets/react-18-hB3smqWJ.js +1 -0
- package/cli/storybook-dist/assets/react-resizable-panels-HsFbxPbn.css +1 -0
- package/cli/storybook-dist/assets/react-resizable-panels.browser-DuxpZLkF.js +120 -0
- package/cli/storybook-dist/assets/test-utils-BQudk2xt.js +9 -0
- package/cli/storybook-dist/favicon.svg +1 -0
- package/cli/storybook-dist/iframe.html +666 -0
- package/cli/storybook-dist/index.html +190 -0
- package/cli/storybook-dist/index.json +1 -0
- package/cli/storybook-dist/nunito-sans-bold-italic.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-bold.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-italic.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-regular.woff2 +0 -0
- package/cli/storybook-dist/project.json +1 -0
- package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
- package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
- package/cli/storybook-dist/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
- package/cli/storybook-dist/sb-addons/essentials-controls-2/manager-bundle.js +405 -0
- package/cli/storybook-dist/sb-addons/essentials-docs-4/manager-bundle.js +245 -0
- package/cli/storybook-dist/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/links-1/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-13/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-experimental-addon-test-12/manager-bundle.js +223 -0
- package/cli/storybook-dist/sb-addons/themes-11/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-common-assets/favicon.svg +1 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/cli/storybook-dist/sb-manager/globals-module-info.js +1052 -0
- package/cli/storybook-dist/sb-manager/globals-runtime.js +41775 -0
- package/cli/storybook-dist/sb-manager/globals.js +48 -0
- package/cli/storybook-dist/sb-manager/runtime.js +12048 -0
- package/cli/templates/common/README.md +1070 -83
- package/cli/templates/common/assets/icon.svg +44 -2
- package/cli/templates/common/manifest.json +14 -13
- package/cli/templates/common/package.json +11 -4
- package/cli/templates/common/py/main.py +125 -0
- package/cli/templates/common/requirements.txt +4 -3
- package/cli/templates/common/tsconfig.json +1 -1
- package/cli/templates/common/ui/content.tsx +216 -0
- package/cli/templates/common/ui/style.css +6 -0
- package/cli/templates/common/vite.config.ts +6 -25
- package/cli/templates/cpp/cpp/CMakeLists.txt +14 -0
- package/cli/templates/cpp/cpp/main.cpp +73 -0
- package/cli/templates/readme-cpp/README.md +1012 -0
- package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/node.py +12 -1
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/CMakeLists.txt +22 -0
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/package.xml +11 -0
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp +41 -0
- package/cli/vite.d.mts +25 -0
- package/cli/vite.mjs +292 -0
- package/package.json +34 -7
- package/cli/src/pack.mjs +0 -61
- package/cli/src/preview.mjs +0 -91
- package/cli/templates/common/main.py +0 -114
- package/cli/templates/common/src/content.tsx +0 -33
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import rclpy
|
|
2
2
|
from rclpy.node import Node
|
|
3
|
-
from rb_sdk import RBManipulateSDK # PyPI: rainbow-rb-sdk
|
|
3
|
+
from rainbow.rb_sdk import RBManipulateSDK, RBPluginCall # PyPI: rainbow-rb-sdk
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
sdk = RBManipulateSDK()
|
|
7
|
+
plugin = RBPluginCall()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# External endpoint (REST / Socket.IO / TCP / MQTT / WebRTC), e.g.
|
|
11
|
+
# curl -X POST http://<robot>/common/plugin/<plugin_id>/hello -d '{"name": "kim"}'
|
|
12
|
+
@plugin.router.on("/hello")
|
|
13
|
+
def hello(payload=None, meta=None):
|
|
14
|
+
name = (payload or {}).get("name", "there")
|
|
15
|
+
return {"msg": f"hi {name}", "via": (meta or {}).get("transport")}
|
|
7
16
|
|
|
8
17
|
|
|
9
18
|
class __PLUGIN_CLASS__Node(Node):
|
|
10
19
|
def __init__(self):
|
|
11
20
|
super().__init__("__PLUGIN_SLUG___node")
|
|
21
|
+
# Also connects the plugin to Muscat — router handlers register on the first call.
|
|
22
|
+
plugin.publish("state", {"ready": True, "plugin": "__PLUGIN_NAME__"}) # -> UI rb.sub("state")
|
|
12
23
|
self.get_logger().info("__PLUGIN_NAME__ node started")
|
|
13
24
|
# sdk is available here — use it alongside ROS2 topics as needed
|
|
14
25
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(__PLUGIN_SLUG__)
|
|
3
|
+
|
|
4
|
+
if(NOT CMAKE_CXX_STANDARD)
|
|
5
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
6
|
+
endif()
|
|
7
|
+
|
|
8
|
+
find_package(ament_cmake REQUIRED)
|
|
9
|
+
find_package(rclcpp REQUIRED)
|
|
10
|
+
# Rainbow Robotics C++ SDK (apt: rainbow-rb-sdk-dev, pre-installed in the dev
|
|
11
|
+
# container). The version here is the one the dev container installs; change it
|
|
12
|
+
# with `muscat-pk sdk update <version>`.
|
|
13
|
+
find_package(rb_sdk 0.10.3 EXACT REQUIRED)
|
|
14
|
+
|
|
15
|
+
add_executable(__PLUGIN_SLUG___node src/node.cpp)
|
|
16
|
+
ament_target_dependencies(__PLUGIN_SLUG___node rclcpp)
|
|
17
|
+
target_link_libraries(__PLUGIN_SLUG___node rb_sdk::rb_sdk)
|
|
18
|
+
|
|
19
|
+
install(TARGETS __PLUGIN_SLUG___node
|
|
20
|
+
DESTINATION lib/${PROJECT_NAME})
|
|
21
|
+
|
|
22
|
+
ament_package()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<package format="3">
|
|
3
|
+
<name>__PLUGIN_SLUG__</name>
|
|
4
|
+
<version>0.0.1</version>
|
|
5
|
+
<description>__PLUGIN_NAME__ ROS2 node (rclcpp)</description>
|
|
6
|
+
<maintainer email="todo@example.com">maintainer</maintainer>
|
|
7
|
+
<license>Proprietary</license>
|
|
8
|
+
<buildtool_depend>ament_cmake</buildtool_depend>
|
|
9
|
+
<depend>rclcpp</depend>
|
|
10
|
+
<export><build_type>ament_cmake</build_type></export>
|
|
11
|
+
</package>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// __PLUGIN_NAME__ — ROS2 node (rclcpp).
|
|
2
|
+
//
|
|
3
|
+
// Relative topic names land under the plugin's ROS namespace (plugin id with
|
|
4
|
+
// "." → "/", "-" → "_"); use an absolute name ("/cmd_vel") for shared topics.
|
|
5
|
+
// UI messaging / external endpoints: rb_plugin::RBPluginCall (plugin/rb_plugin.hpp).
|
|
6
|
+
#include "rclcpp/rclcpp.hpp"
|
|
7
|
+
// Rainbow Robotics C++ SDK (linked as rb_sdk::rb_sdk): RBManipulateSDK etc.
|
|
8
|
+
#include <rainbow/rb_sdk/manipulate/rb_manipulate_sdk.hpp>
|
|
9
|
+
#include <rainbow/rb_sdk/plugin/rb_plugin.hpp>
|
|
10
|
+
|
|
11
|
+
#include <nlohmann/json.hpp>
|
|
12
|
+
|
|
13
|
+
using nlohmann::json;
|
|
14
|
+
using rb_plugin::RBPluginCall;
|
|
15
|
+
|
|
16
|
+
class __PLUGIN_CLASS__Node : public rclcpp::Node {
|
|
17
|
+
public:
|
|
18
|
+
__PLUGIN_CLASS__Node() : Node("__PLUGIN_SLUG___node") {
|
|
19
|
+
RCLCPP_INFO(this->get_logger(), "__PLUGIN_NAME__ node started");
|
|
20
|
+
// create publishers / subscribers / services here
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
int main(int argc, char** argv) {
|
|
25
|
+
rclcpp::init(argc, argv);
|
|
26
|
+
|
|
27
|
+
// plugin id comes from RB_PLUGIN_ID.
|
|
28
|
+
auto plugin = RBPluginCall::get_instance(RBPluginCall::resolve_plugin_id(std::nullopt));
|
|
29
|
+
// External endpoint (REST / Socket.IO / TCP / MQTT / WebRTC), e.g.
|
|
30
|
+
// curl -X POST http://<robot>/common/plugin/<plugin_id>/hello -d '{"name":"kim"}'
|
|
31
|
+
plugin->router().on("/hello", [](const json& payload, const json& meta) {
|
|
32
|
+
const std::string who = payload.is_object() ? payload.value("name", std::string("there")) : "there";
|
|
33
|
+
return json{{"msg", "hi " + who}, {"via", meta.value("transport", std::string())}};
|
|
34
|
+
});
|
|
35
|
+
// Also connects the plugin to Muscat — router handlers register on the first call.
|
|
36
|
+
plugin->publish("state", {{"ready", true}, {"plugin", "__PLUGIN_NAME__"}}); // -> UI rb.sub("state")
|
|
37
|
+
|
|
38
|
+
rclcpp::spin(std::make_shared<__PLUGIN_CLASS__Node>());
|
|
39
|
+
rclcpp::shutdown();
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
package/cli/vite.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface MuscatVitePlugin {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export type MuscatVitePluginOption =
|
|
6
|
+
| MuscatVitePlugin
|
|
7
|
+
| false
|
|
8
|
+
| null
|
|
9
|
+
| undefined
|
|
10
|
+
| MuscatVitePluginOption[];
|
|
11
|
+
|
|
12
|
+
export interface MuscatReactOptions {
|
|
13
|
+
jsxImportSource?: string;
|
|
14
|
+
babel?: {
|
|
15
|
+
plugins?: unknown[];
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
};
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface MuscatOptions {
|
|
22
|
+
react?: false | MuscatReactOptions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare function muscat(options?: MuscatOptions): MuscatVitePluginOption[];
|
package/cli/vite.mjs
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import react from "@vitejs/plugin-react";
|
|
2
|
+
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
|
|
3
|
+
import postcss from "postcss";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
6
|
+
import { basename, extname, resolve } from "node:path";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const HOST_PROVIDED_EXTERNALS = [
|
|
10
|
+
/^react(\/.*)?$/,
|
|
11
|
+
/^react-dom(\/.*)?$/,
|
|
12
|
+
/^@rainbow-robotics\/plugin-ui(\/.*)?$/,
|
|
13
|
+
/^@repo\/rb-components(\/.*)?$/,
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const UI_ENTRY_PREFIX = "muscat-ui-entry:";
|
|
17
|
+
const RESOLVED_UI_ENTRY_PREFIX = "\0" + UI_ENTRY_PREFIX;
|
|
18
|
+
const SHARED_RUNTIME_PREFIX = "muscat-shared-runtime:";
|
|
19
|
+
const RESOLVED_SHARED_RUNTIME_PREFIX = "\0" + SHARED_RUNTIME_PREFIX;
|
|
20
|
+
const STYLE_EXTENSIONS = [".css", ".scss", ".sass", ".less"];
|
|
21
|
+
// `@rainbow-robotics/plugin-ui/react` ships transpiled-only (see
|
|
22
|
+
// build-dist.mjs: `bundle: false, // consumers resolve deps themselves") — its
|
|
23
|
+
// `export * from "@repo/rb-components/new_components"` is a monorepo-private
|
|
24
|
+
// package no external plugin can npm-install. So a "dev" plugin can't use its
|
|
25
|
+
// own local copy of plugin-ui/react (or /sdk, whose RbContext must stay one
|
|
26
|
+
// singleton with host.tsx's Provider) — these, plus react/react-dom itself
|
|
27
|
+
// (so elements created by rb-components match the instance rendering them)
|
|
28
|
+
// and host-ui (the plain-function toast/alert/confirm/prompt channel), all
|
|
29
|
+
// redirect to the host's already-loaded instances instead.
|
|
30
|
+
const SHARED_RUNTIME_FILES = {
|
|
31
|
+
react: "react",
|
|
32
|
+
"react/jsx-runtime": "react_jsx-runtime",
|
|
33
|
+
"react/jsx-dev-runtime": "react_jsx-dev-runtime",
|
|
34
|
+
"react-dom": "react-dom",
|
|
35
|
+
"react-dom/client": "react-dom_client",
|
|
36
|
+
"@rainbow-robotics/plugin-ui/react": "plugin-ui_react",
|
|
37
|
+
"@rainbow-robotics/plugin-ui/sdk": "plugin-ui_sdk",
|
|
38
|
+
"@rainbow-robotics/plugin-ui/host-ui": "plugin-ui_host-ui",
|
|
39
|
+
"@rainbow-robotics/plugin-ui/ws": "plugin-ui_ws",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function cssString(value) {
|
|
43
|
+
return String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\a ");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readPluginId(root) {
|
|
47
|
+
try {
|
|
48
|
+
const manifest = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8"));
|
|
49
|
+
return typeof manifest.id === "string" && manifest.id ? manifest.id : null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function pluginScopeSelector(pluginId) {
|
|
56
|
+
if (!pluginId) return ":where([data-muscat-plugin-root])";
|
|
57
|
+
return `:where([data-muscat-plugin-id="${cssString(pluginId)}"])`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function discoverUiEntries(uiDir) {
|
|
61
|
+
return Object.fromEntries(
|
|
62
|
+
readdirSync(uiDir)
|
|
63
|
+
.filter((f) => /\.(tsx?|jsx?)$/.test(f))
|
|
64
|
+
.map((f) => [basename(f, extname(f)), resolve(uiDir, f)]),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function discoverUiStyles(uiDir, entryName) {
|
|
69
|
+
return STYLE_EXTENSIONS.flatMap((ext) => [
|
|
70
|
+
resolve(uiDir, `style${ext}`),
|
|
71
|
+
resolve(uiDir, `styles${ext}`),
|
|
72
|
+
resolve(uiDir, `${entryName}${ext}`),
|
|
73
|
+
]).filter((file, index, files) => existsSync(file) && files.indexOf(file) === index);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function isKeyframesRule(rule) {
|
|
77
|
+
for (let node = rule.parent; node; node = node.parent) {
|
|
78
|
+
if (node.type === "atrule" && /keyframes$/i.test(node.name)) return true;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function scopeSelector(selector, rootSelector) {
|
|
84
|
+
const trimmed = selector.trim();
|
|
85
|
+
if (
|
|
86
|
+
!trimmed ||
|
|
87
|
+
trimmed.includes("[data-muscat-plugin-root]") ||
|
|
88
|
+
trimmed.includes("[data-muscat-plugin-id")
|
|
89
|
+
) {
|
|
90
|
+
return selector;
|
|
91
|
+
}
|
|
92
|
+
if (/^(:root|:host)\b/.test(trimmed)) {
|
|
93
|
+
return trimmed.replace(/^(:root|:host)\b/, rootSelector);
|
|
94
|
+
}
|
|
95
|
+
if (/^(html|body)\b/.test(trimmed)) {
|
|
96
|
+
return trimmed.replace(/^(html|body)\b/, rootSelector);
|
|
97
|
+
}
|
|
98
|
+
return `${rootSelector} ${trimmed}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function scopePluginCss(css, rootSelector) {
|
|
102
|
+
if (!css.trim()) return css;
|
|
103
|
+
const root = postcss.parse(css);
|
|
104
|
+
root.walkRules((rule) => {
|
|
105
|
+
if (isKeyframesRule(rule)) return;
|
|
106
|
+
rule.selectors = rule.selectors.map((selector) => scopeSelector(selector, rootSelector));
|
|
107
|
+
});
|
|
108
|
+
return root.toString();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function createUiEntryPlugin(uiDir, entries) {
|
|
112
|
+
return {
|
|
113
|
+
name: "muscat-ui-entry",
|
|
114
|
+
enforce: "pre",
|
|
115
|
+
resolveId(id) {
|
|
116
|
+
if (id.startsWith(UI_ENTRY_PREFIX)) return "\0" + id;
|
|
117
|
+
},
|
|
118
|
+
load(id) {
|
|
119
|
+
if (!id.startsWith(RESOLVED_UI_ENTRY_PREFIX)) return;
|
|
120
|
+
const entryName = id.slice(RESOLVED_UI_ENTRY_PREFIX.length);
|
|
121
|
+
const entry = entries[entryName];
|
|
122
|
+
if (!entry) throw new Error(`Unknown Muscat UI entry: ${entryName}`);
|
|
123
|
+
|
|
124
|
+
const styleImports = discoverUiStyles(uiDir, entryName)
|
|
125
|
+
.map((file) => {
|
|
126
|
+
this.addWatchFile(file);
|
|
127
|
+
return `import ${JSON.stringify(file)};`;
|
|
128
|
+
})
|
|
129
|
+
.join("\n");
|
|
130
|
+
|
|
131
|
+
return `${styleImports}\nexport { default } from ${JSON.stringify(entry)};\n`;
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function resolveFromPlugin(root, specifier) {
|
|
137
|
+
try {
|
|
138
|
+
return createRequire(resolve(root, "package.json")).resolve(specifier);
|
|
139
|
+
} catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function exactSpecifier(specifier) {
|
|
145
|
+
return new RegExp(`^${specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function reactAliases(root) {
|
|
149
|
+
return [
|
|
150
|
+
"react",
|
|
151
|
+
"react/jsx-runtime",
|
|
152
|
+
"react/jsx-dev-runtime",
|
|
153
|
+
"react-dom",
|
|
154
|
+
"react-dom/client",
|
|
155
|
+
].flatMap((specifier) => {
|
|
156
|
+
const resolved = resolveFromPlugin(root, specifier);
|
|
157
|
+
return resolved ? [{ find: exactSpecifier(specifier), replacement: resolved }] : [];
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function createSharedRuntimePlugin(baseUrl) {
|
|
162
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
name: "muscat-shared-runtime",
|
|
166
|
+
enforce: "pre",
|
|
167
|
+
resolveId(id) {
|
|
168
|
+
if (id in SHARED_RUNTIME_FILES) return "\0" + SHARED_RUNTIME_PREFIX + id;
|
|
169
|
+
},
|
|
170
|
+
load(id) {
|
|
171
|
+
if (!id.startsWith(RESOLVED_SHARED_RUNTIME_PREFIX)) return;
|
|
172
|
+
const specifier = id.slice(RESOLVED_SHARED_RUNTIME_PREFIX.length);
|
|
173
|
+
const file = SHARED_RUNTIME_FILES[specifier];
|
|
174
|
+
if (!file) throw new Error(`Unknown Muscat shared runtime module: ${specifier}`);
|
|
175
|
+
|
|
176
|
+
const url = JSON.stringify(`${base}/${file}.js`);
|
|
177
|
+
if (specifier === "react" || specifier === "react-dom") {
|
|
178
|
+
return `export * from ${url};\nimport sharedDefault from ${url};\nexport default sharedDefault;\n`;
|
|
179
|
+
}
|
|
180
|
+
return `export * from ${url};\n`;
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const REACT_REFRESH_ACCEPT_MARKER =
|
|
186
|
+
"\nif (import.meta.hot && !inWebWorker) {\n RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {";
|
|
187
|
+
|
|
188
|
+
function createManualHmrBoundaryPlugin(uiDir) {
|
|
189
|
+
const normalizedUiDir = uiDir.replace(/\/$/, "");
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
name: "muscat-manual-hmr-boundary",
|
|
193
|
+
apply: "serve",
|
|
194
|
+
enforce: "post",
|
|
195
|
+
transform(code, id) {
|
|
196
|
+
const [file] = id.split("?");
|
|
197
|
+
if (!file.startsWith(`${normalizedUiDir}/`) || !/\.[jt]sx?$/.test(file)) return null;
|
|
198
|
+
|
|
199
|
+
const markerIndex = code.lastIndexOf(REACT_REFRESH_ACCEPT_MARKER);
|
|
200
|
+
if (markerIndex === -1) return null;
|
|
201
|
+
|
|
202
|
+
// preview-host provides the same production ReactDOM as Nexus. Vite's
|
|
203
|
+
// React Fast Refresh receives updates but cannot drive that renderer, so
|
|
204
|
+
// let the bootstrap module handle HMR by re-rendering the updated entry.
|
|
205
|
+
return { code: code.slice(0, markerIndex), map: null };
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function muscat(options = {}) {
|
|
211
|
+
const pluginRoot = process.cwd();
|
|
212
|
+
const uiDir = resolve(pluginRoot, "ui");
|
|
213
|
+
const entries = discoverUiEntries(uiDir);
|
|
214
|
+
const rootSelector = pluginScopeSelector(readPluginId(pluginRoot));
|
|
215
|
+
const sharedRuntimeBase = process.env.MUSCAT_PLUGIN_SHARED_RUNTIME_BASE;
|
|
216
|
+
const wrappedEntries = Object.fromEntries(
|
|
217
|
+
Object.keys(entries).map((name) => [name, `${UI_ENTRY_PREFIX}${name}`]),
|
|
218
|
+
);
|
|
219
|
+
const reactPlugins = options.react === false ? [] : [react(options.react)];
|
|
220
|
+
|
|
221
|
+
return [
|
|
222
|
+
...reactPlugins,
|
|
223
|
+
createUiEntryPlugin(uiDir, entries),
|
|
224
|
+
...(sharedRuntimeBase ? [createSharedRuntimePlugin(sharedRuntimeBase)] : []),
|
|
225
|
+
...(sharedRuntimeBase ? [createManualHmrBoundaryPlugin(uiDir)] : []),
|
|
226
|
+
cssInjectedByJsPlugin({
|
|
227
|
+
relativeCSSInjection: true,
|
|
228
|
+
preRenderCSSCode: (css) => scopePluginCss(css, rootSelector),
|
|
229
|
+
}),
|
|
230
|
+
{
|
|
231
|
+
name: "muscat-plugin-build",
|
|
232
|
+
apply: "build",
|
|
233
|
+
config: () => ({
|
|
234
|
+
build: {
|
|
235
|
+
target: "esnext",
|
|
236
|
+
outDir: "dist",
|
|
237
|
+
emptyOutDir: false,
|
|
238
|
+
rollupOptions: {
|
|
239
|
+
input: wrappedEntries,
|
|
240
|
+
external: HOST_PROVIDED_EXTERNALS,
|
|
241
|
+
// Entries only `export default App` (the host mounts it). Without
|
|
242
|
+
// this, Vite treats entries as self-executing apps and tree-shakes
|
|
243
|
+
// the unused default export away.
|
|
244
|
+
preserveEntrySignatures: "strict",
|
|
245
|
+
output: {
|
|
246
|
+
format: "es",
|
|
247
|
+
entryFileNames: "[name].js",
|
|
248
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
249
|
+
assetFileNames: "assets/[name]-[hash][extname]",
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
}),
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "muscat-plugin-dev",
|
|
257
|
+
apply: "serve",
|
|
258
|
+
config: () => {
|
|
259
|
+
return {
|
|
260
|
+
// NOTE: even with sharedRuntimeBase set (so `alias` is empty and our
|
|
261
|
+
// resolveId below wins for every actual import), @vitejs/plugin-react
|
|
262
|
+
// still unconditionally adds react/react-dom/jsx-(dev-)runtime to
|
|
263
|
+
// optimizeDeps.include for Fast Refresh — Vite merges every plugin's
|
|
264
|
+
// optimizeDeps (arrays are concatenated, not overridden), so esbuild's
|
|
265
|
+
// pre-bundle scanner still tries to statically resolve those on disk.
|
|
266
|
+
// That's why the scaffold template keeps react/react-dom as local
|
|
267
|
+
// devDependencies even in shared-runtime mode: purely so this static
|
|
268
|
+
// scan has something real to resolve. The actual dev-server imports
|
|
269
|
+
// never reach that local copy — resolveId (enforce: "pre") below
|
|
270
|
+
// always wins first and redirects to the host's instance.
|
|
271
|
+
resolve: {
|
|
272
|
+
alias: sharedRuntimeBase ? [] : reactAliases(pluginRoot),
|
|
273
|
+
dedupe: ["react", "react-dom"],
|
|
274
|
+
},
|
|
275
|
+
optimizeDeps: sharedRuntimeBase
|
|
276
|
+
? { noDiscovery: true, include: [] }
|
|
277
|
+
: {
|
|
278
|
+
include: [
|
|
279
|
+
"react",
|
|
280
|
+
"react-dom",
|
|
281
|
+
"react-dom/client",
|
|
282
|
+
"@rainbow-robotics/plugin-ui/react",
|
|
283
|
+
"@rainbow-robotics/plugin-ui/sdk",
|
|
284
|
+
"@rainbow-robotics/plugin-ui/host-ui",
|
|
285
|
+
"@rainbow-robotics/plugin-ui/ws",
|
|
286
|
+
],
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
];
|
|
292
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rainbow-robotics/muscat-plugin-kit",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.10.1-dev.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20"
|
|
@@ -13,28 +13,55 @@
|
|
|
13
13
|
"create-muscat-plugin": "./cli/bin/create-muscat-plugin.mjs",
|
|
14
14
|
"muscat-pk": "./cli/bin/muscat-pk.mjs"
|
|
15
15
|
},
|
|
16
|
+
"exports": {
|
|
17
|
+
"./vite": {
|
|
18
|
+
"types": "./cli/vite.d.mts",
|
|
19
|
+
"default": "./cli/vite.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@vitejs/plugin-react": ">=4",
|
|
25
|
+
"vite": ">=5"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"@vitejs/plugin-react": {
|
|
29
|
+
"optional": true
|
|
30
|
+
},
|
|
31
|
+
"vite": {
|
|
32
|
+
"optional": true
|
|
33
|
+
}
|
|
34
|
+
},
|
|
16
35
|
"files": [
|
|
17
36
|
"cli",
|
|
18
|
-
"package.json"
|
|
37
|
+
"package.json",
|
|
38
|
+
"README.ko.md"
|
|
19
39
|
],
|
|
20
40
|
"scripts": {
|
|
21
41
|
"lint": "node cli/src/check-package.mjs",
|
|
22
42
|
"check": "node cli/src/check-package.mjs",
|
|
23
|
-
"check-types": "node cli/src/check-package.mjs"
|
|
43
|
+
"check-types": "node cli/src/check-package.mjs",
|
|
44
|
+
"storybook:build": "node cli/prepack.mjs",
|
|
45
|
+
"prepack": "node cli/prepack.mjs"
|
|
24
46
|
},
|
|
25
47
|
"devDependencies": {
|
|
26
48
|
"@eslint/js": "^9.22.0",
|
|
27
49
|
"@repo/eslint-config": "*",
|
|
28
50
|
"@repo/typescript-config": "*",
|
|
29
51
|
"@types/node": "^22.13.9",
|
|
30
|
-
"@types/react": "^19.0.10",
|
|
31
52
|
"@types/react-dom": "^19.0.4"
|
|
32
53
|
},
|
|
33
54
|
"dependencies": {
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
56
|
+
"@rainbow-robotics/plugin-ui": "0.10.1-dev.0",
|
|
57
|
+
"@rainbow-robotics/preview-host": "0.10.1-dev.0",
|
|
58
|
+
"@types/react": "^19.0.10",
|
|
59
|
+
"postcss": "^8.5.8",
|
|
60
|
+
"typescript": "^5.8.0",
|
|
61
|
+
"vite-plugin-css-injected-by-js": "^3.5.2",
|
|
62
|
+
"zod": "^3.25.0"
|
|
36
63
|
},
|
|
37
64
|
"optionalDependencies": {
|
|
38
65
|
"esbuild-wasm": "^0.25.0"
|
|
39
66
|
}
|
|
40
|
-
}
|
|
67
|
+
}
|
package/cli/src/pack.mjs
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// muscat-pk pack — build, then create a distributable ZIP with a size report.
|
|
2
|
-
import { execSync } from "node:child_process";
|
|
3
|
-
import { existsSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
4
|
-
import { basename, resolve } from "node:path";
|
|
5
|
-
import { buildPlugin, exportRos2Build, pinRequirements } from "./build.mjs";
|
|
6
|
-
import { findPluginRoot, humanSize, log } from "./util.mjs";
|
|
7
|
-
|
|
8
|
-
function dirSize(dir) {
|
|
9
|
-
let total = 0;
|
|
10
|
-
for (const entry of readdirSync(dir)) {
|
|
11
|
-
const full = resolve(dir, entry);
|
|
12
|
-
const st = statSync(full);
|
|
13
|
-
total += st.isDirectory() ? dirSize(full) : st.size;
|
|
14
|
-
}
|
|
15
|
-
return total;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function runPack() {
|
|
19
|
-
const pluginRoot = findPluginRoot();
|
|
20
|
-
log.step("pinning requirements.txt to latest PyPI versions");
|
|
21
|
-
await pinRequirements(pluginRoot);
|
|
22
|
-
await buildPlugin({ root: pluginRoot, minify: true });
|
|
23
|
-
await exportRos2Build(pluginRoot);
|
|
24
|
-
|
|
25
|
-
const manifest = JSON.parse(
|
|
26
|
-
readFileSync(resolve(pluginRoot, "manifest.json"), "utf8"),
|
|
27
|
-
);
|
|
28
|
-
const zipName = `${basename(pluginRoot)}-${manifest.version || "0.0.0"}.zip`;
|
|
29
|
-
const zipPath = resolve(pluginRoot, zipName);
|
|
30
|
-
rmSync(zipPath, { force: true });
|
|
31
|
-
|
|
32
|
-
// Contents: dist/ + back-end files if present.
|
|
33
|
-
const entries = ["dist"];
|
|
34
|
-
for (const f of ["main.py", "requirements.txt"]) {
|
|
35
|
-
if (existsSync(resolve(pluginRoot, f))) entries.push(f);
|
|
36
|
-
}
|
|
37
|
-
if (existsSync(resolve(pluginRoot, "ros2_ws/install"))) {
|
|
38
|
-
entries.push("ros2_ws/install");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
log.step(`packing ${entries.join(", ")} → ${zipName}`);
|
|
42
|
-
try {
|
|
43
|
-
execSync(`zip -r -q "${zipPath}" ${entries.map((e) => `"${e}"`).join(" ")}`, {
|
|
44
|
-
cwd: pluginRoot,
|
|
45
|
-
stdio: "inherit",
|
|
46
|
-
});
|
|
47
|
-
} catch {
|
|
48
|
-
throw new Error("`zip` not found. Install zip or pack manually.");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const zipBytes = statSync(zipPath).size;
|
|
52
|
-
log.ok(`${zipName} ${humanSize(zipBytes)}`);
|
|
53
|
-
for (const e of entries) {
|
|
54
|
-
const full = resolve(pluginRoot, e);
|
|
55
|
-
const size = statSync(full).isDirectory() ? dirSize(full) : statSync(full).size;
|
|
56
|
-
log.info(` ├─ ${e} ${humanSize(size)}`);
|
|
57
|
-
}
|
|
58
|
-
log.warn(
|
|
59
|
-
"robot install checks free space via GET /plugin/capacity (507 if low).",
|
|
60
|
-
);
|
|
61
|
-
}
|
package/cli/src/preview.mjs
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// muscat-pk preview — build the plugin and open preview-host connected to a
|
|
2
|
-
// real Muscat server (robot or local). No local Socket.IO server is started.
|
|
3
|
-
import { createInterface } from "node:readline";
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
5
|
-
import { existsSync } from "node:fs";
|
|
6
|
-
import { resolve } from "node:path";
|
|
7
|
-
import { buildPlugin } from "./build.mjs";
|
|
8
|
-
import { findPreviewHostRoot } from "./devUi.mjs";
|
|
9
|
-
import { checkKitUpdate, log, parseArgs } from "./util.mjs";
|
|
10
|
-
|
|
11
|
-
function prompt(question, defaultValue) {
|
|
12
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
13
|
-
return new Promise((res) => {
|
|
14
|
-
rl.question(question, (answer) => {
|
|
15
|
-
rl.close();
|
|
16
|
-
res(answer.trim() || defaultValue);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export async function runPreview(args = []) {
|
|
22
|
-
const opts = parseArgs(args, { booleans: ["help"] });
|
|
23
|
-
|
|
24
|
-
if (opts.help) {
|
|
25
|
-
console.log(
|
|
26
|
-
[
|
|
27
|
-
"",
|
|
28
|
-
"Usage: muscat-pk preview [options]",
|
|
29
|
-
"",
|
|
30
|
-
" 빌드된 플러그인을 실제 Muscat 서버에 연결해 미리봅니다.",
|
|
31
|
-
" Socket.IO 서버를 직접 띄우지 않습니다.",
|
|
32
|
-
"",
|
|
33
|
-
"Options:",
|
|
34
|
-
" --host <ip> Muscat 서버 IP 또는 hostname (default: localhost)",
|
|
35
|
-
" --port <n> preview-host 로컬 포트 (default: 4180)",
|
|
36
|
-
" --ws-port <n> Muscat Socket.IO 포트 (default: 10000)",
|
|
37
|
-
"",
|
|
38
|
-
].join("\n"),
|
|
39
|
-
);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
await checkKitUpdate();
|
|
44
|
-
|
|
45
|
-
// ── 로봇 IP 결정 ────────────────────────────────────────────────────────────
|
|
46
|
-
let robotHost = opts.host ?? "";
|
|
47
|
-
if (!robotHost) {
|
|
48
|
-
robotHost = await prompt(
|
|
49
|
-
"Muscat 서버 IP 또는 hostname [localhost]: ",
|
|
50
|
-
"localhost",
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
const wsPort = opts["ws-port"] ?? "10000";
|
|
54
|
-
const socketUrl = `ws://${robotHost}:${wsPort}`;
|
|
55
|
-
|
|
56
|
-
const previewPort = opts.port ?? "4180";
|
|
57
|
-
|
|
58
|
-
log.step(`Muscat 서버: ${socketUrl}`);
|
|
59
|
-
|
|
60
|
-
// ── 플러그인 빌드 ────────────────────────────────────────────────────────────
|
|
61
|
-
const { distDir } = await buildPlugin();
|
|
62
|
-
|
|
63
|
-
// ── preview-host 실행 ────────────────────────────────────────────────────────
|
|
64
|
-
const previewRoot = findPreviewHostRoot();
|
|
65
|
-
const serveEntry = resolve(previewRoot, "serve.mjs");
|
|
66
|
-
|
|
67
|
-
if (!existsSync(resolve(previewRoot, "dist", "index.html"))) {
|
|
68
|
-
log.step("preview-host 번들 빌드 중 (최초 1회)…");
|
|
69
|
-
await new Promise((res, rej) => {
|
|
70
|
-
const p = spawn(process.execPath, [resolve(previewRoot, "build.mjs")], {
|
|
71
|
-
stdio: "inherit",
|
|
72
|
-
});
|
|
73
|
-
p.on("exit", (c) => (c === 0 ? res() : rej(new Error("preview-host build failed"))));
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
log.step(`preview-host 시작 → http://localhost:${previewPort}`);
|
|
78
|
-
log.step(`Socket.IO URL: ${socketUrl}`);
|
|
79
|
-
|
|
80
|
-
const child = spawn(
|
|
81
|
-
process.execPath,
|
|
82
|
-
[
|
|
83
|
-
serveEntry,
|
|
84
|
-
"--plugin", distDir,
|
|
85
|
-
"--port", String(previewPort),
|
|
86
|
-
"--socket-url", socketUrl,
|
|
87
|
-
],
|
|
88
|
-
{ stdio: "inherit" },
|
|
89
|
-
);
|
|
90
|
-
child.on("exit", (code) => process.exit(code ?? 0));
|
|
91
|
-
}
|