@tuongaz/seeflow 0.1.64 → 0.1.68
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.md +4 -0
- package/dist/web/assets/abap-DsBKuouk.js +1 -0
- package/dist/web/assets/actionscript-3-D_z4Izcz.js +1 -0
- package/dist/web/assets/ada-727ZlQH0.js +1 -0
- package/dist/web/assets/andromeeda-C3khCPGq.js +1 -0
- package/dist/web/assets/angular-html-4alyEGLm.js +1 -0
- package/dist/web/assets/angular-ts-BixEUTMq.js +1 -0
- package/dist/web/assets/apache-Dn00JSTd.js +1 -0
- package/dist/web/assets/apex-COJ4H7py.js +1 -0
- package/dist/web/assets/apl-BBq3IX1j.js +1 -0
- package/dist/web/assets/applescript-Bu5BbsvL.js +1 -0
- package/dist/web/assets/ara-7O62HKoU.js +1 -0
- package/dist/web/assets/asciidoc-BPT9niGB.js +1 -0
- package/dist/web/assets/asm-Dhn9LcZ4.js +1 -0
- package/dist/web/assets/astro-CqkE3fuf.js +1 -0
- package/dist/web/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/web/assets/awk-eg146-Ew.js +1 -0
- package/dist/web/assets/ayu-dark-Cv9koXgw.js +1 -0
- package/dist/web/assets/ballerina-Du268qiB.js +1 -0
- package/dist/web/assets/bat-fje9CFhw.js +1 -0
- package/dist/web/assets/beancount-BwXTMy5W.js +1 -0
- package/dist/web/assets/berry-3xVqZejG.js +1 -0
- package/dist/web/assets/bibtex-xW4inM5L.js +1 -0
- package/dist/web/assets/bicep-DHo0CJ0O.js +1 -0
- package/dist/web/assets/blade-a8OxSdnT.js +1 -0
- package/dist/web/assets/bsl-Dgyn0ogV.js +1 -0
- package/dist/web/assets/c-C3t2pwGQ.js +1 -0
- package/dist/web/assets/cadence-DNquZEk8.js +1 -0
- package/dist/web/assets/cairo--RitsXJZ.js +1 -0
- package/dist/web/assets/catppuccin-frappe-CD_QflpE.js +1 -0
- package/dist/web/assets/catppuccin-latte-DRW-0cLl.js +1 -0
- package/dist/web/assets/catppuccin-macchiato-C-_shW-Y.js +1 -0
- package/dist/web/assets/catppuccin-mocha-LGGdnPYs.js +1 -0
- package/dist/web/assets/chart-8DxAnLoD.js +73 -0
- package/dist/web/assets/clarity-BHOwM8T6.js +1 -0
- package/dist/web/assets/clojure-DxSadP1t.js +1 -0
- package/dist/web/assets/cmake-DbXoA79R.js +1 -0
- package/dist/web/assets/cobol-PTqiYgYu.js +1 -0
- package/dist/web/assets/code-block-cx7LPXvE.js +13 -0
- package/dist/web/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/web/assets/codeql-sacFqUAJ.js +1 -0
- package/dist/web/assets/coffee-dyiR41kL.js +1 -0
- package/dist/web/assets/common-lisp-C7gG9l05.js +1 -0
- package/dist/web/assets/coq-Dsg_Bt_b.js +1 -0
- package/dist/web/assets/cpp-BksuvNSY.js +1 -0
- package/dist/web/assets/crystal-DtDmRg-F.js +1 -0
- package/dist/web/assets/csharp-D9R-vmeu.js +1 -0
- package/dist/web/assets/css-BPhBrDlE.js +1 -0
- package/dist/web/assets/csv-B0qRVHPH.js +1 -0
- package/dist/web/assets/cue-DtFQj3wx.js +1 -0
- package/dist/web/assets/cypher-m2LEI-9-.js +1 -0
- package/dist/web/assets/d-BoXegm-a.js +1 -0
- package/dist/web/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/web/assets/dart-B9wLZaAG.js +1 -0
- package/dist/web/assets/dax-ClGRhx96.js +1 -0
- package/dist/web/assets/desktop-DEIpsLCJ.js +1 -0
- package/dist/web/assets/diff-BgYniUM_.js +1 -0
- package/dist/web/assets/docker-COcR7UxN.js +1 -0
- package/dist/web/assets/dotenv-BjQB5zDj.js +1 -0
- package/dist/web/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/web/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/web/assets/dream-maker-C-nORZOA.js +1 -0
- package/dist/web/assets/edge-D5gP-w-T.js +1 -0
- package/dist/web/assets/elixir-CLiX3zqd.js +1 -0
- package/dist/web/assets/elm-CmHSxxaM.js +1 -0
- package/dist/web/assets/emacs-lisp-BX77sIaO.js +1 -0
- package/dist/web/assets/erb-BYTLMnw6.js +1 -0
- package/dist/web/assets/erlang-B-DoSBHF.js +1 -0
- package/dist/web/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/web/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/web/assets/fennel-bCA53EVm.js +1 -0
- package/dist/web/assets/fish-w-ucz2PV.js +1 -0
- package/dist/web/assets/fluent-Dayu4EKP.js +1 -0
- package/dist/web/assets/fortran-fixed-form-TqA4NnZg.js +1 -0
- package/dist/web/assets/fortran-free-form-DKXYxT9g.js +1 -0
- package/dist/web/assets/fsharp-XplgxFYe.js +1 -0
- package/dist/web/assets/gdresource-BHYsBjWJ.js +1 -0
- package/dist/web/assets/gdscript-DfxzS6Rs.js +1 -0
- package/dist/web/assets/gdshader-SKMF96pI.js +1 -0
- package/dist/web/assets/genie-ajMbGru0.js +1 -0
- package/dist/web/assets/gherkin--30QC5Em.js +1 -0
- package/dist/web/assets/git-commit-i4q6IMui.js +1 -0
- package/dist/web/assets/git-rebase-B-v9cOL2.js +1 -0
- package/dist/web/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/web/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/web/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/web/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/web/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/web/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/web/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/web/assets/gleam-B430Bg39.js +1 -0
- package/dist/web/assets/glimmer-js-D-cwc0-E.js +1 -0
- package/dist/web/assets/glimmer-ts-pgjy16dm.js +1 -0
- package/dist/web/assets/glsl-DBO2IWDn.js +1 -0
- package/dist/web/assets/gnuplot-CM8KxXT1.js +1 -0
- package/dist/web/assets/go-B1SYOhNW.js +1 -0
- package/dist/web/assets/graphql-cDcHW_If.js +1 -0
- package/dist/web/assets/groovy-DkBy-JyN.js +1 -0
- package/dist/web/assets/hack-D1yCygmZ.js +1 -0
- package/dist/web/assets/haml-B2EZWmdv.js +1 -0
- package/dist/web/assets/handlebars-BQGss363.js +1 -0
- package/dist/web/assets/haskell-BILxekzW.js +1 -0
- package/dist/web/assets/haxe-C5wWYbrZ.js +1 -0
- package/dist/web/assets/hcl-HzYwdGDm.js +1 -0
- package/dist/web/assets/hjson-T-Tgc4AT.js +1 -0
- package/dist/web/assets/hlsl-ifBTmRxC.js +1 -0
- package/dist/web/assets/houston-DnULxvSX.js +1 -0
- package/dist/web/assets/html-C2L_23MC.js +1 -0
- package/dist/web/assets/html-derivative-CSfWNPLT.js +1 -0
- package/dist/web/assets/http-FRrOvY1W.js +1 -0
- package/dist/web/assets/hxml-TIA70rKU.js +1 -0
- package/dist/web/assets/hy-BMj5Y0dO.js +1 -0
- package/dist/web/assets/imba-bv_oIlVt.js +1 -0
- package/dist/web/assets/index-CeLShda7.css +1 -0
- package/dist/web/assets/index-Dp4QwEl0.js +8608 -0
- package/dist/web/assets/{index.es-DZEdTXNJ.js → index.es-C-uXEdZB.js} +1 -1
- package/dist/web/assets/ini-BjABl1g7.js +1 -0
- package/dist/web/assets/java-xI-RfyKK.js +1 -0
- package/dist/web/assets/javascript-ySlJ1b_l.js +1 -0
- package/dist/web/assets/jinja-DGy0s7-h.js +1 -0
- package/dist/web/assets/jison-BqZprYcd.js +1 -0
- package/dist/web/assets/json-BQoSv7ci.js +1 -0
- package/dist/web/assets/json5-w8dY5SsB.js +1 -0
- package/dist/web/assets/jsonc-TU54ms6u.js +1 -0
- package/dist/web/assets/jsonl-DREVFZK8.js +1 -0
- package/dist/web/assets/jsonnet-BfivnA6A.js +1 -0
- package/dist/web/assets/{jspdf.es.min-DT1Li8zz.js → jspdf.es.min-BFQufOcQ.js} +3 -3
- package/dist/web/assets/jssm-P4WzXJd0.js +1 -0
- package/dist/web/assets/jsx-BAng5TT0.js +1 -0
- package/dist/web/assets/julia-BBuGR-5E.js +1 -0
- package/dist/web/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/web/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/web/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/web/assets/kotlin-B5lbUyaz.js +1 -0
- package/dist/web/assets/kusto-mebxcVVE.js +1 -0
- package/dist/web/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/web/assets/latex-C-cWTeAZ.js +1 -0
- package/dist/web/assets/lean-XBlWyCtg.js +1 -0
- package/dist/web/assets/less-BfCpw3nA.js +1 -0
- package/dist/web/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/web/assets/liquid-D3W5UaiH.js +1 -0
- package/dist/web/assets/log-Cc5clBb7.js +1 -0
- package/dist/web/assets/logo-IuBKFhSY.js +1 -0
- package/dist/web/assets/lua-CvWAzNxB.js +1 -0
- package/dist/web/assets/luau-Du5NY7AG.js +1 -0
- package/dist/web/assets/make-Bvotw-X0.js +1 -0
- package/dist/web/assets/markdown-DK_1WFMa.js +1 -0
- package/dist/web/assets/markdown-UIAJJxZW.js +1 -0
- package/dist/web/assets/marko-z0MBrx5-.js +1 -0
- package/dist/web/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/web/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/web/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/web/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/web/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/web/assets/matlab-D9-PGadD.js +1 -0
- package/dist/web/assets/mdc-DB_EDNY_.js +1 -0
- package/dist/web/assets/mdx-sdHcTMYB.js +1 -0
- package/dist/web/assets/mermaid-Ci6OQyBP.js +1 -0
- package/dist/web/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/web/assets/min-light-CTRr51gU.js +1 -0
- package/dist/web/assets/mipsasm-BC5c_5Pe.js +1 -0
- package/dist/web/assets/mojo-Tz6hzZYG.js +1 -0
- package/dist/web/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/web/assets/move-DB_GagMm.js +1 -0
- package/dist/web/assets/narrat-DLbgOhZU.js +1 -0
- package/dist/web/assets/nextflow-B0XVJmRM.js +1 -0
- package/dist/web/assets/nginx-D_VnBJ67.js +1 -0
- package/dist/web/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/web/assets/nim-ZlGxZxc3.js +1 -0
- package/dist/web/assets/nix-shcSOmrb.js +1 -0
- package/dist/web/assets/nord-Ddv68eIx.js +1 -0
- package/dist/web/assets/nushell-D4Tzg5kh.js +1 -0
- package/dist/web/assets/objective-c-Deuh7S70.js +1 -0
- package/dist/web/assets/objective-cpp-BUEGK8hf.js +1 -0
- package/dist/web/assets/ocaml-BNioltXt.js +1 -0
- package/dist/web/assets/one-dark-pro-GBQ2dnAY.js +1 -0
- package/dist/web/assets/one-light-PoHY5YXO.js +1 -0
- package/dist/web/assets/pascal-JqZropPD.js +1 -0
- package/dist/web/assets/perl-CHQXSrWU.js +1 -0
- package/dist/web/assets/php-B5ebYQev.js +1 -0
- package/dist/web/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/web/assets/plsql-LKU2TuZ1.js +1 -0
- package/dist/web/assets/po-BFLt1xDp.js +1 -0
- package/dist/web/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/web/assets/polar-DKykz6zU.js +1 -0
- package/dist/web/assets/postcss-B3ZDOciz.js +1 -0
- package/dist/web/assets/powerquery-CSHBycmS.js +1 -0
- package/dist/web/assets/powershell-BIEUsx6d.js +1 -0
- package/dist/web/assets/prisma-B48N-Iqd.js +1 -0
- package/dist/web/assets/prolog-BY-TUvya.js +1 -0
- package/dist/web/assets/proto-zocC4JxJ.js +1 -0
- package/dist/web/assets/pug-CM9l7STV.js +1 -0
- package/dist/web/assets/puppet-Cza_XSSt.js +1 -0
- package/dist/web/assets/purescript-Bg-kzb6g.js +1 -0
- package/dist/web/assets/python-DhUJRlN_.js +1 -0
- package/dist/web/assets/qml-D8XfuvdV.js +1 -0
- package/dist/web/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/web/assets/qss-DhMKtDLN.js +1 -0
- package/dist/web/assets/r-CwjWoCRV.js +1 -0
- package/dist/web/assets/racket-CzouJOBO.js +1 -0
- package/dist/web/assets/raku-B1bQXN8T.js +1 -0
- package/dist/web/assets/razor-CNLDkMZG.js +1 -0
- package/dist/web/assets/red-bN70gL4F.js +1 -0
- package/dist/web/assets/reg-5LuOXUq_.js +1 -0
- package/dist/web/assets/regexp-DWJ3fJO_.js +1 -0
- package/dist/web/assets/rel-DJlmqQ1C.js +1 -0
- package/dist/web/assets/riscv-QhoSD0DR.js +1 -0
- package/dist/web/assets/rose-pine-CmCqftbK.js +1 -0
- package/dist/web/assets/rose-pine-dawn-Ds-gbosJ.js +1 -0
- package/dist/web/assets/rose-pine-moon-CjDtw9vr.js +1 -0
- package/dist/web/assets/rst-4NLicBqY.js +1 -0
- package/dist/web/assets/ruby-DeZ3UC14.js +1 -0
- package/dist/web/assets/rust-Be6lgOlo.js +1 -0
- package/dist/web/assets/sas-BmTFh92c.js +1 -0
- package/dist/web/assets/sass-BJ4Li9vH.js +1 -0
- package/dist/web/assets/scala-DQVVAn-B.js +1 -0
- package/dist/web/assets/scheme-BJGe-b2p.js +1 -0
- package/dist/web/assets/scss-C31hgJw-.js +1 -0
- package/dist/web/assets/sdbl-BLhTXw86.js +1 -0
- package/dist/web/assets/shaderlab-B7qAK45m.js +1 -0
- package/dist/web/assets/shellscript-atvbtKCR.js +1 -0
- package/dist/web/assets/shellsession-C_rIy8kc.js +1 -0
- package/dist/web/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/web/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/web/assets/smalltalk-DkLiglaE.js +1 -0
- package/dist/web/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/web/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/web/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/web/assets/solidity-C1w2a3ep.js +1 -0
- package/dist/web/assets/soy-C-lX7w71.js +1 -0
- package/dist/web/assets/sparql-bYkjHRlG.js +1 -0
- package/dist/web/assets/splunk-Cf8iN4DR.js +1 -0
- package/dist/web/assets/sql-COK4E0Yg.js +1 -0
- package/dist/web/assets/ssh-config-BknIz3MU.js +1 -0
- package/dist/web/assets/stata-DorPZHa4.js +1 -0
- package/dist/web/assets/stylus-BeQkCIfX.js +1 -0
- package/dist/web/assets/svelte-MSaWC3Je.js +1 -0
- package/dist/web/assets/swift-BSxZ-RaX.js +1 -0
- package/dist/web/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/web/assets/system-verilog-C7L56vO4.js +1 -0
- package/dist/web/assets/systemd-CUnW07Te.js +1 -0
- package/dist/web/assets/talonscript-C1XDQQGZ.js +1 -0
- package/dist/web/assets/tasl-CQjiPCtT.js +1 -0
- package/dist/web/assets/tcl-DQ1-QYvQ.js +1 -0
- package/dist/web/assets/templ-dwX3ZSMB.js +1 -0
- package/dist/web/assets/terraform-BbSNqyBO.js +1 -0
- package/dist/web/assets/tex-rYs2v40G.js +1 -0
- package/dist/web/assets/tokyo-night-DBQeEorK.js +1 -0
- package/dist/web/assets/toml-CB2ApiWb.js +1 -0
- package/dist/web/assets/ts-tags-CipyTH0X.js +1 -0
- package/dist/web/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/web/assets/tsx-B6W0miNI.js +1 -0
- package/dist/web/assets/turtle-BMR_PYu6.js +1 -0
- package/dist/web/assets/twig-NC5TFiHP.js +1 -0
- package/dist/web/assets/typescript-Dj6nwHGl.js +1 -0
- package/dist/web/assets/typespec-BpWG_bgh.js +1 -0
- package/dist/web/assets/typst-BVUVsWT6.js +1 -0
- package/dist/web/assets/v-CAQ2eGtk.js +1 -0
- package/dist/web/assets/vala-BFOHcciG.js +1 -0
- package/dist/web/assets/vb-CdO5JTpU.js +1 -0
- package/dist/web/assets/verilog-CJaU5se_.js +1 -0
- package/dist/web/assets/vesper-BEBZ7ncR.js +1 -0
- package/dist/web/assets/vhdl-DYoNaHQp.js +1 -0
- package/dist/web/assets/viml-m4uW47V2.js +1 -0
- package/dist/web/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/web/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/web/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/web/assets/vue-BuYVFjOK.js +1 -0
- package/dist/web/assets/vue-html-xdeiXROB.js +1 -0
- package/dist/web/assets/vyper-nyqBNV6O.js +1 -0
- package/dist/web/assets/wasm-C6j12Q_x.js +1 -0
- package/dist/web/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/web/assets/wenyan-7A4Fjokl.js +1 -0
- package/dist/web/assets/wgsl-CB0Krxn9.js +1 -0
- package/dist/web/assets/wikitext-DCE3LsBG.js +1 -0
- package/dist/web/assets/wolfram-C3FkfJm5.js +1 -0
- package/dist/web/assets/xml-e3z08dGr.js +1 -0
- package/dist/web/assets/xsl-Dd0NUgwM.js +1 -0
- package/dist/web/assets/yaml-CVw76BM1.js +1 -0
- package/dist/web/assets/zenscript-HnGAYVZD.js +1 -0
- package/dist/web/assets/zig-BVz_zdnA.js +1 -0
- package/dist/web/index.html +2 -2
- package/examples/component-showcase/README.md +29 -0
- package/examples/component-showcase/flow.json +40 -0
- package/examples/component-showcase/nodes/chart/spec.json +66 -0
- package/examples/component-showcase/nodes/counter/spec.json +57 -0
- package/examples/component-showcase/nodes/fetcher/actions/refresh.ts +35 -0
- package/examples/component-showcase/nodes/fetcher/spec.json +68 -0
- package/examples/component-showcase/nodes/form/spec.json +87 -0
- package/examples/component-showcase/package.json +6 -0
- package/examples/component-showcase/style.json +28 -0
- package/examples/ecommerce-platform/flow.json +28 -30
- package/examples/order-pipeline/flow.json +16 -16
- package/package.json +2 -1
- package/src/api.ts +73 -23
- package/src/cli-e2e.ts +6 -7
- package/src/cli-manifest.ts +3 -5
- package/src/cli.ts +27 -0
- package/src/component-action-runner.ts +188 -0
- package/src/component-spec-resolver.ts +60 -0
- package/src/diagram.ts +8 -5
- package/src/layout.ts +23 -26
- package/src/mcp.ts +2 -2
- package/src/merge.ts +8 -3
- package/src/node-files.ts +1 -1
- package/src/operations.ts +109 -52
- package/src/runtime.ts +37 -0
- package/src/schema-catalog.ts +23 -11
- package/src/schema.ts +256 -262
- package/src/server.ts +1 -1
- package/src/status-runner.ts +2 -1
- package/src/watcher.ts +46 -10
- package/dist/web/assets/index-BAEA18IR.js +0 -7838
- package/dist/web/assets/index-CwfFCUzZ.css +0 -1
|
@@ -4,23 +4,22 @@
|
|
|
4
4
|
"nodes": [
|
|
5
5
|
{
|
|
6
6
|
"id": "node-cQOUPXanaX",
|
|
7
|
-
"type": "
|
|
7
|
+
"type": "user",
|
|
8
8
|
"data": {
|
|
9
|
-
"shape": "user",
|
|
10
9
|
"name": "Customer",
|
|
11
10
|
"description": "Web / Mobile / Partner"
|
|
12
11
|
}
|
|
13
12
|
},
|
|
14
13
|
{
|
|
15
14
|
"id": "node-CbwYqb7NfB",
|
|
16
|
-
"type": "
|
|
15
|
+
"type": "rectangle",
|
|
17
16
|
"data": {
|
|
18
17
|
"name": "API Gateway",
|
|
18
|
+
"description": "Auth, rate-limiting, routing.",
|
|
19
|
+
"detail": "file://detail.md",
|
|
19
20
|
"stateSource": {
|
|
20
21
|
"kind": "request"
|
|
21
22
|
},
|
|
22
|
-
"description": "Auth, rate-limiting, routing.",
|
|
23
|
-
"detail": "file://detail.md",
|
|
24
23
|
"playAction": {
|
|
25
24
|
"kind": "script",
|
|
26
25
|
"interpreter": "bun",
|
|
@@ -31,38 +30,38 @@
|
|
|
31
30
|
},
|
|
32
31
|
{
|
|
33
32
|
"id": "node-3zFtHg6ENc",
|
|
34
|
-
"type": "
|
|
33
|
+
"type": "rectangle",
|
|
35
34
|
"data": {
|
|
36
35
|
"name": "Auth Service",
|
|
36
|
+
"description": "JWT issuance + OAuth2 / OIDC.",
|
|
37
|
+
"detail": "file://detail.md",
|
|
37
38
|
"stateSource": {
|
|
38
39
|
"kind": "request"
|
|
39
|
-
}
|
|
40
|
-
"description": "JWT issuance + OAuth2 / OIDC.",
|
|
41
|
-
"detail": "file://detail.md"
|
|
40
|
+
}
|
|
42
41
|
}
|
|
43
42
|
},
|
|
44
43
|
{
|
|
45
44
|
"id": "node-kwBY8YPmYM",
|
|
46
|
-
"type": "
|
|
45
|
+
"type": "rectangle",
|
|
47
46
|
"data": {
|
|
48
47
|
"name": "Product Catalog",
|
|
48
|
+
"description": "SKUs, variants, pricing, full-text search.",
|
|
49
|
+
"detail": "file://detail.md",
|
|
49
50
|
"stateSource": {
|
|
50
51
|
"kind": "request"
|
|
51
|
-
}
|
|
52
|
-
"description": "SKUs, variants, pricing, full-text search.",
|
|
53
|
-
"detail": "file://detail.md"
|
|
52
|
+
}
|
|
54
53
|
}
|
|
55
54
|
},
|
|
56
55
|
{
|
|
57
56
|
"id": "node-5F424NWbEu",
|
|
58
|
-
"type": "
|
|
57
|
+
"type": "rectangle",
|
|
59
58
|
"data": {
|
|
60
59
|
"name": "Cart Service",
|
|
60
|
+
"description": "Add/remove items, apply coupons, checkout.",
|
|
61
|
+
"detail": "file://detail.md",
|
|
61
62
|
"stateSource": {
|
|
62
63
|
"kind": "request"
|
|
63
64
|
},
|
|
64
|
-
"description": "Add/remove items, apply coupons, checkout.",
|
|
65
|
-
"detail": "file://detail.md",
|
|
66
65
|
"playAction": {
|
|
67
66
|
"kind": "script",
|
|
68
67
|
"interpreter": "bun",
|
|
@@ -73,14 +72,14 @@
|
|
|
73
72
|
},
|
|
74
73
|
{
|
|
75
74
|
"id": "node-yKrg9DV5fJ",
|
|
76
|
-
"type": "
|
|
75
|
+
"type": "rectangle",
|
|
77
76
|
"data": {
|
|
78
77
|
"name": "Order Service",
|
|
78
|
+
"description": "pending → confirmed → shipped → delivered.",
|
|
79
|
+
"detail": "file://detail.md",
|
|
79
80
|
"stateSource": {
|
|
80
81
|
"kind": "event"
|
|
81
82
|
},
|
|
82
|
-
"description": "pending → confirmed → shipped → delivered.",
|
|
83
|
-
"detail": "file://detail.md",
|
|
84
83
|
"playAction": {
|
|
85
84
|
"kind": "script",
|
|
86
85
|
"interpreter": "bun",
|
|
@@ -91,40 +90,39 @@
|
|
|
91
90
|
},
|
|
92
91
|
{
|
|
93
92
|
"id": "node-mPqan8rFYN",
|
|
94
|
-
"type": "
|
|
93
|
+
"type": "rectangle",
|
|
95
94
|
"data": {
|
|
96
95
|
"name": "Payment Service",
|
|
96
|
+
"description": "Stripe + PayPal gateway integration.",
|
|
97
|
+
"detail": "file://detail.md",
|
|
97
98
|
"stateSource": {
|
|
98
99
|
"kind": "event"
|
|
99
|
-
}
|
|
100
|
-
"description": "Stripe + PayPal gateway integration.",
|
|
101
|
-
"detail": "file://detail.md"
|
|
100
|
+
}
|
|
102
101
|
}
|
|
103
102
|
},
|
|
104
103
|
{
|
|
105
104
|
"id": "node-fkptXw7uvs",
|
|
106
|
-
"type": "
|
|
105
|
+
"type": "rectangle",
|
|
107
106
|
"data": {
|
|
108
107
|
"name": "Notification Service",
|
|
108
|
+
"description": "Email + SMS + push via AWS SES / SNS.",
|
|
109
|
+
"detail": "file://detail.md",
|
|
109
110
|
"stateSource": {
|
|
110
111
|
"kind": "event"
|
|
111
|
-
}
|
|
112
|
-
"description": "Email + SMS + push via AWS SES / SNS.",
|
|
113
|
-
"detail": "file://detail.md"
|
|
112
|
+
}
|
|
114
113
|
}
|
|
115
114
|
},
|
|
116
115
|
{
|
|
117
116
|
"id": "node-5SDiw3Wz6s",
|
|
118
|
-
"type": "
|
|
117
|
+
"type": "database",
|
|
119
118
|
"data": {
|
|
120
|
-
"shape": "database",
|
|
121
119
|
"name": "PostgreSQL",
|
|
122
120
|
"description": "Orders, users, products — primary OLTP store"
|
|
123
121
|
}
|
|
124
122
|
},
|
|
125
123
|
{
|
|
126
124
|
"id": "node-XwygzfKPZ5",
|
|
127
|
-
"type": "
|
|
125
|
+
"type": "html",
|
|
128
126
|
"data": {
|
|
129
127
|
"name": "Platform Health",
|
|
130
128
|
"html": "file://view.html"
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"nodes": [
|
|
5
5
|
{
|
|
6
6
|
"id": "node-XKIyds0TDg",
|
|
7
|
-
"type": "
|
|
7
|
+
"type": "rectangle",
|
|
8
8
|
"data": {
|
|
9
9
|
"name": "POST /orders",
|
|
10
|
+
"description": "Creates order, kicks off the pipeline.",
|
|
11
|
+
"detail": "file://detail.md",
|
|
10
12
|
"stateSource": {
|
|
11
13
|
"kind": "request"
|
|
12
14
|
},
|
|
13
|
-
"description": "Creates order, kicks off the pipeline.",
|
|
14
|
-
"detail": "file://detail.md",
|
|
15
15
|
"playAction": {
|
|
16
16
|
"kind": "script",
|
|
17
17
|
"interpreter": "bun",
|
|
@@ -22,39 +22,39 @@
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"id": "node-GXTKUcE3ye",
|
|
25
|
-
"type": "
|
|
25
|
+
"type": "rectangle",
|
|
26
26
|
"data": {
|
|
27
27
|
"name": "Inventory Service",
|
|
28
|
-
"stateSource": {
|
|
29
|
-
"kind": "event"
|
|
30
|
-
},
|
|
31
28
|
"description": "Reserves stock.",
|
|
32
29
|
"detail": "file://detail.md",
|
|
33
|
-
"icon": "a-arrow-down-icon"
|
|
30
|
+
"icon": "a-arrow-down-icon",
|
|
31
|
+
"stateSource": {
|
|
32
|
+
"kind": "event"
|
|
33
|
+
}
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"id": "node-YOYiHJpY0i",
|
|
38
|
-
"type": "
|
|
38
|
+
"type": "rectangle",
|
|
39
39
|
"data": {
|
|
40
40
|
"name": "Payment Service",
|
|
41
|
+
"description": "Charges card.",
|
|
42
|
+
"detail": "file://detail.md",
|
|
41
43
|
"stateSource": {
|
|
42
44
|
"kind": "event"
|
|
43
|
-
}
|
|
44
|
-
"description": "Charges card.",
|
|
45
|
-
"detail": "file://detail.md"
|
|
45
|
+
}
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"id": "node-zUIH7WFnhK",
|
|
50
|
-
"type": "
|
|
50
|
+
"type": "rectangle",
|
|
51
51
|
"data": {
|
|
52
52
|
"name": "Fulfillment Service",
|
|
53
|
+
"description": "Enqueues shipment.",
|
|
54
|
+
"detail": "file://detail.md",
|
|
53
55
|
"stateSource": {
|
|
54
56
|
"kind": "event"
|
|
55
|
-
}
|
|
56
|
-
"description": "Enqueues shipment.",
|
|
57
|
-
"detail": "file://detail.md"
|
|
57
|
+
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuongaz/seeflow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.68",
|
|
4
4
|
"description": "Local studio that hosts file-defined demos as React Flow canvases wired to a running app via REST + SSE + Zod schema.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"seeflow",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
|
+
"@seeflow/canvas": "workspace:*",
|
|
46
47
|
"elkjs": "^0.11.1",
|
|
47
48
|
"hono": "^4.6.14",
|
|
48
49
|
"zod": "^3.23.8",
|
package/src/api.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
|
3
3
|
import { Hono } from 'hono';
|
|
4
4
|
import { streamSSE } from 'hono/streaming';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { runComponentAction } from './component-action-runner.ts';
|
|
6
7
|
import {
|
|
7
8
|
AssembleRequestSchema,
|
|
8
9
|
ProposeScopeRequestSchema,
|
|
@@ -38,6 +39,7 @@ import {
|
|
|
38
39
|
} from './proxy.ts';
|
|
39
40
|
import type { Registry } from './registry.ts';
|
|
40
41
|
import { getSchemaCategory, listSchemaCategories, schemaCategoryNames } from './schema-catalog.ts';
|
|
42
|
+
import type { ComponentAction } from './schema.ts';
|
|
41
43
|
import { FlowSchema, ResolvedFlowSchema } from './schema.ts';
|
|
42
44
|
import { type Spawner, defaultSpawner } from './shellout.ts';
|
|
43
45
|
import { ID_TYPES, MAX_ID_COUNT, generateIds, isIdType } from './short-id.ts';
|
|
@@ -345,14 +347,7 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
345
347
|
}
|
|
346
348
|
const flow = flowParse.data;
|
|
347
349
|
const result = await computeLayout(
|
|
348
|
-
flow.nodes.map((n) => ({
|
|
349
|
-
id: n.id,
|
|
350
|
-
type: n.type,
|
|
351
|
-
// Only `shape` matters for layout (floating-annotation detection +
|
|
352
|
-
// shape-specific sizing). Other Flow data fields are irrelevant.
|
|
353
|
-
data:
|
|
354
|
-
n.type === 'shapeNode' ? { shape: (n.data as { shape?: string }).shape } : undefined,
|
|
355
|
-
})),
|
|
350
|
+
flow.nodes.map((n) => ({ id: n.id, type: n.type })),
|
|
356
351
|
flow.connectors.map((c) => ({ id: c.id, source: c.source, target: c.target })),
|
|
357
352
|
options,
|
|
358
353
|
);
|
|
@@ -375,12 +370,18 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
375
370
|
.map((n) => ({
|
|
376
371
|
id: n.id,
|
|
377
372
|
type: n.type as
|
|
378
|
-
| '
|
|
379
|
-
| '
|
|
380
|
-
| '
|
|
381
|
-
| '
|
|
382
|
-
| '
|
|
383
|
-
| '
|
|
373
|
+
| 'rectangle'
|
|
374
|
+
| 'ellipse'
|
|
375
|
+
| 'sticky'
|
|
376
|
+
| 'text'
|
|
377
|
+
| 'database'
|
|
378
|
+
| 'server'
|
|
379
|
+
| 'user'
|
|
380
|
+
| 'queue'
|
|
381
|
+
| 'cloud'
|
|
382
|
+
| 'image'
|
|
383
|
+
| 'html'
|
|
384
|
+
| 'icon',
|
|
384
385
|
data:
|
|
385
386
|
typeof n.width === 'number' && typeof n.height === 'number'
|
|
386
387
|
? { width: n.width, height: n.height }
|
|
@@ -582,7 +583,7 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
582
583
|
});
|
|
583
584
|
|
|
584
585
|
// POST /api/projects/:id/files/open — shell out to `$EDITOR <abs>` so the
|
|
585
|
-
// user can edit a project-scoped file (
|
|
586
|
+
// user can edit a project-scoped file (type:'html' block, image asset) in
|
|
586
587
|
// their IDE. The endpoint always returns the resolved absolute path in
|
|
587
588
|
// the response body so the frontend can copy-to-clipboard when $EDITOR
|
|
588
589
|
// isn't set or the spawn fails. Path safety mirrors the GET route.
|
|
@@ -815,13 +816,10 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
815
816
|
|
|
816
817
|
const node = merged.flow.nodes.find((n) => n.id === nodeId);
|
|
817
818
|
if (!node) return c.json({ error: `Unknown nodeId: ${nodeId}` }, 404);
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
node.type === 'htmlNode' ||
|
|
823
|
-
!node.data.playAction
|
|
824
|
-
) {
|
|
819
|
+
// playAction is optional on every node type post-flat-types. The runtime
|
|
820
|
+
// gate is purely "is the field set?" — visual kind doesn't constrain
|
|
821
|
+
// playability.
|
|
822
|
+
if (!node.data.playAction) {
|
|
825
823
|
return c.json({ error: `Node ${nodeId} has no playAction` }, 400);
|
|
826
824
|
}
|
|
827
825
|
|
|
@@ -854,6 +852,58 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
854
852
|
return c.json(result);
|
|
855
853
|
});
|
|
856
854
|
|
|
855
|
+
// POST /api/flows/:id/nodes/:nodeId/actions/:name — dispatch a component
|
|
856
|
+
// node's named action over HTTP. Only `script`-kind actions cross this seam;
|
|
857
|
+
// `set`-kind actions mutate canvas state locally and never round-trip
|
|
858
|
+
// through the API (the runner rejects them with statusHint 400).
|
|
859
|
+
// Payload is the JSON request body (defaults to {} on parse failure) and is
|
|
860
|
+
// piped to the script's stdin by `runComponentAction`. Response is the
|
|
861
|
+
// script's parsed JSON stdout on success.
|
|
862
|
+
api.post('/flows/:id/nodes/:nodeId/actions/:name', async (c) => {
|
|
863
|
+
const id = c.req.param('id');
|
|
864
|
+
const nodeId = c.req.param('nodeId');
|
|
865
|
+
const actionName = c.req.param('name');
|
|
866
|
+
|
|
867
|
+
const entry = registry.getById(id);
|
|
868
|
+
if (!entry) return c.json({ error: 'unknown demo' }, 404);
|
|
869
|
+
if (!events) return c.json({ error: 'events not enabled' }, 500);
|
|
870
|
+
|
|
871
|
+
const fullPath = resolveFilePath(entry.repoPath, entry.flowPath);
|
|
872
|
+
if (!existsSync(fullPath)) {
|
|
873
|
+
return c.json({ error: `Flow file not found: ${fullPath}` }, 404);
|
|
874
|
+
}
|
|
875
|
+
const merged = readMergedFlow(fullPath);
|
|
876
|
+
if (!merged.flow) {
|
|
877
|
+
return c.json({ error: merged.error ?? 'Flow read failed' }, 400);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
const node = merged.flow.nodes.find((n) => n.id === nodeId);
|
|
881
|
+
if (!node) return c.json({ error: `Unknown nodeId: ${nodeId}` }, 404);
|
|
882
|
+
if (node.type !== 'component') {
|
|
883
|
+
return c.json({ error: `Node ${nodeId} is not a component node` }, 400);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
const action = (node.data as { spec: { actions?: Record<string, ComponentAction> } }).spec
|
|
887
|
+
.actions?.[actionName];
|
|
888
|
+
if (!action) return c.json({ error: `Unknown action: ${actionName}` }, 404);
|
|
889
|
+
|
|
890
|
+
const payload = await c.req.json().catch(() => ({}));
|
|
891
|
+
const result = await runComponentAction({
|
|
892
|
+
events,
|
|
893
|
+
flowId: id,
|
|
894
|
+
nodeId,
|
|
895
|
+
cwd: entry.repoPath,
|
|
896
|
+
actionName,
|
|
897
|
+
action,
|
|
898
|
+
payload,
|
|
899
|
+
spawner: processSpawner,
|
|
900
|
+
});
|
|
901
|
+
if (!result.ok) {
|
|
902
|
+
return c.json({ error: result.error }, result.statusHint as 400 | 404 | 500 | 504);
|
|
903
|
+
}
|
|
904
|
+
return c.json(result.body);
|
|
905
|
+
});
|
|
906
|
+
|
|
857
907
|
// POST /api/flows/:id/reset — the "Restart demo" workflow (US-008). Order:
|
|
858
908
|
// 1. Stop every live play-script + every long-running status-script for
|
|
859
909
|
// this demo in parallel — both must complete before any reset script
|
|
@@ -1007,7 +1057,7 @@ export function createApi(options: ApiOptions): Hono {
|
|
|
1007
1057
|
});
|
|
1008
1058
|
|
|
1009
1059
|
// PATCH a single node — partial update of position, label, detail, visual
|
|
1010
|
-
// fields, or
|
|
1060
|
+
// fields, or geometric-only fields. Every UI-driven node edit (other than
|
|
1011
1061
|
// the high-frequency drag fast-path above) flows through here. The mutation
|
|
1012
1062
|
// is performed against the raw parsed JSON (so unknown v2 fields the schema
|
|
1013
1063
|
// doesn't yet recognize survive round-trips) and the WHOLE resulting demo
|
package/src/cli-e2e.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// End-to-end validator used by `seeflow e2e <flowId>`. Opens an SSE channel to
|
|
2
|
-
// the studio, triggers every
|
|
2
|
+
// the studio, triggers every node carrying a playAction (sequentially), then drains
|
|
3
3
|
// the channel for node:done/error + node:status reports. Mirrors the algorithm
|
|
4
4
|
// in skills/seeflow/scripts/validate-end-to-end.ts — kept here so the CLI does
|
|
5
5
|
// not depend on the skill folder.
|
|
@@ -167,15 +167,14 @@ function openSseChannel(body: ReadableStream<Uint8Array>): SseChannel {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
function hasPlayAction(node: NodeShape): boolean {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
// Flat-types refactor: capabilities are top-level data fields on every
|
|
171
|
+
// type, not gated by the type tag. The e2e runner iterates every node
|
|
172
|
+
// carrying a playAction regardless of variant.
|
|
173
|
+
return node.data?.playAction !== undefined;
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
function hasStatusAction(node: NodeShape): boolean {
|
|
176
|
-
return
|
|
177
|
-
(node.type === 'playNode' || node.type === 'stateNode') && node.data?.statusAction !== undefined
|
|
178
|
-
);
|
|
177
|
+
return node.data?.statusAction !== undefined;
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
export async function validateEndToEnd(options: ValidateOptions): Promise<ValidationReport> {
|
package/src/cli-manifest.ts
CHANGED
|
@@ -281,7 +281,7 @@ export const COMMAND_MANIFEST: CommandManifestEntry[] = [
|
|
|
281
281
|
},
|
|
282
282
|
requiresStudio: false,
|
|
283
283
|
examples: [
|
|
284
|
-
'seeflow flow:add-bulk abc12345 --json \'{"nodes":[{"id":"a","type":"
|
|
284
|
+
'seeflow flow:add-bulk abc12345 --json \'{"nodes":[{"id":"a","type":"rectangle","data":{}}],"connectors":[]}\'',
|
|
285
285
|
'seeflow flow:add-bulk abc12345 --file batch.json',
|
|
286
286
|
],
|
|
287
287
|
},
|
|
@@ -344,7 +344,7 @@ export const COMMAND_MANIFEST: CommandManifestEntry[] = [
|
|
|
344
344
|
flags: BODY_FLAGS,
|
|
345
345
|
body: {
|
|
346
346
|
example: {
|
|
347
|
-
type: '
|
|
347
|
+
type: 'rectangle',
|
|
348
348
|
data: { name: 'hello', stateSource: { kind: 'request' } },
|
|
349
349
|
},
|
|
350
350
|
},
|
|
@@ -360,9 +360,7 @@ export const COMMAND_MANIFEST: CommandManifestEntry[] = [
|
|
|
360
360
|
],
|
|
361
361
|
},
|
|
362
362
|
requiresStudio: false,
|
|
363
|
-
examples: [
|
|
364
|
-
'seeflow nodes:add abc12345 --json \'{"type":"shapeNode","data":{"shape":"rectangle"}}\'',
|
|
365
|
-
],
|
|
363
|
+
examples: ['seeflow nodes:add abc12345 --json \'{"type":"rectangle","data":{}}\''],
|
|
366
364
|
},
|
|
367
365
|
{
|
|
368
366
|
name: 'nodes:get',
|
package/src/cli.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
clearPid,
|
|
21
21
|
defaultPidPath,
|
|
22
22
|
isPidAlive,
|
|
23
|
+
portInUse,
|
|
23
24
|
readConfig,
|
|
24
25
|
readPid,
|
|
25
26
|
studioUrl,
|
|
@@ -266,6 +267,20 @@ async function runHelp() {
|
|
|
266
267
|
console.log(renderCommandList());
|
|
267
268
|
}
|
|
268
269
|
|
|
270
|
+
// Pre-flight: refuse to start if the studio port already has a TCP listener.
|
|
271
|
+
// We deliberately do NOT probe Vite's port (5173) here — `bun run dev` spawns
|
|
272
|
+
// Vite alongside the studio, so Vite legitimately owns 5173 in dev mode and a
|
|
273
|
+
// probe can't distinguish "our Vite" from a stranger. If Vite's port is taken
|
|
274
|
+
// by something else, Vite itself surfaces the conflict.
|
|
275
|
+
async function assertPortFree(studioPort: number, host: string): Promise<void> {
|
|
276
|
+
if (!(await portInUse(host, studioPort))) return;
|
|
277
|
+
console.error(
|
|
278
|
+
`Cannot start SeeFlow: port ${studioPort} already in use.\n` +
|
|
279
|
+
`Stop the running server on ${studioPort} first, then retry.`,
|
|
280
|
+
);
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
|
|
269
284
|
async function runStart() {
|
|
270
285
|
mkdirSync(seeflowHome(), { recursive: true });
|
|
271
286
|
const config = readConfig();
|
|
@@ -294,6 +309,12 @@ async function runStart() {
|
|
|
294
309
|
return;
|
|
295
310
|
}
|
|
296
311
|
|
|
312
|
+
// Defense-in-depth: parent already checked in spawnDaemon, but a race
|
|
313
|
+
// between parent-check and child-bind can still let another process grab
|
|
314
|
+
// the port. Re-check here so the child fails fast with a clear error
|
|
315
|
+
// instead of EADDRINUSE at bind time.
|
|
316
|
+
await assertPortFree(port, config.host);
|
|
317
|
+
|
|
297
318
|
// persist the chosen address so other subcommands can find us
|
|
298
319
|
writeConfig({ port, host: config.host });
|
|
299
320
|
|
|
@@ -329,6 +350,7 @@ async function runStart() {
|
|
|
329
350
|
async function seedExamples(registry: Registry) {
|
|
330
351
|
await seedExample(registry, 'order-pipeline');
|
|
331
352
|
await seedExample(registry, 'ecommerce-platform');
|
|
353
|
+
await seedExample(registry, 'component-showcase');
|
|
332
354
|
}
|
|
333
355
|
|
|
334
356
|
async function seedExample(registry: Registry, exampleName: string) {
|
|
@@ -368,6 +390,11 @@ async function spawnDaemon(port: number, host: string) {
|
|
|
368
390
|
return;
|
|
369
391
|
}
|
|
370
392
|
|
|
393
|
+
// Studio port must be free before we fork a detached child — otherwise the
|
|
394
|
+
// user waits HEALTH_TIMEOUT_MS for a doomed health probe before seeing a
|
|
395
|
+
// generic timeout error.
|
|
396
|
+
await assertPortFree(port, host);
|
|
397
|
+
|
|
371
398
|
const proc = spawnDetachedStudio(port);
|
|
372
399
|
writePid(proc.pid);
|
|
373
400
|
writeConfig({ port, host });
|